incur 0.4.0 → 0.4.2

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 (115) hide show
  1. package/README.md +83 -22
  2. package/SKILL.md +6 -6
  3. package/dist/Cli.d.ts +46 -26
  4. package/dist/Cli.d.ts.map +1 -1
  5. package/dist/Cli.js +728 -441
  6. package/dist/Cli.js.map +1 -1
  7. package/dist/Completions.d.ts +4 -3
  8. package/dist/Completions.d.ts.map +1 -1
  9. package/dist/Completions.js +17 -10
  10. package/dist/Completions.js.map +1 -1
  11. package/dist/Fetch.d.ts.map +1 -1
  12. package/dist/Fetch.js +10 -9
  13. package/dist/Fetch.js.map +1 -1
  14. package/dist/Filter.js +0 -18
  15. package/dist/Filter.js.map +1 -1
  16. package/dist/Formatter.d.ts.map +1 -1
  17. package/dist/Formatter.js +6 -1
  18. package/dist/Formatter.js.map +1 -1
  19. package/dist/Help.d.ts +7 -1
  20. package/dist/Help.d.ts.map +1 -1
  21. package/dist/Help.js +44 -27
  22. package/dist/Help.js.map +1 -1
  23. package/dist/Mcp.d.ts +37 -5
  24. package/dist/Mcp.d.ts.map +1 -1
  25. package/dist/Mcp.js +71 -72
  26. package/dist/Mcp.js.map +1 -1
  27. package/dist/Openapi.d.ts.map +1 -1
  28. package/dist/Openapi.js +22 -14
  29. package/dist/Openapi.js.map +1 -1
  30. package/dist/Parser.d.ts +4 -0
  31. package/dist/Parser.d.ts.map +1 -1
  32. package/dist/Parser.js +70 -38
  33. package/dist/Parser.js.map +1 -1
  34. package/dist/Schema.d.ts +5 -1
  35. package/dist/Schema.d.ts.map +1 -1
  36. package/dist/Schema.js +13 -2
  37. package/dist/Schema.js.map +1 -1
  38. package/dist/Skill.d.ts +2 -1
  39. package/dist/Skill.d.ts.map +1 -1
  40. package/dist/Skill.js +33 -19
  41. package/dist/Skill.js.map +1 -1
  42. package/dist/Skillgen.js +1 -1
  43. package/dist/Skillgen.js.map +1 -1
  44. package/dist/SyncSkills.d.ts +48 -0
  45. package/dist/SyncSkills.d.ts.map +1 -1
  46. package/dist/SyncSkills.js +108 -10
  47. package/dist/SyncSkills.js.map +1 -1
  48. package/dist/Typegen.js +4 -2
  49. package/dist/Typegen.js.map +1 -1
  50. package/dist/bin.d.ts +2 -1
  51. package/dist/bin.d.ts.map +1 -1
  52. package/dist/bin.js +17 -2
  53. package/dist/bin.js.map +1 -1
  54. package/dist/internal/command.d.ts +170 -0
  55. package/dist/internal/command.d.ts.map +1 -0
  56. package/dist/internal/command.js +292 -0
  57. package/dist/internal/command.js.map +1 -0
  58. package/dist/internal/configSchema.d.ts +8 -0
  59. package/dist/internal/configSchema.d.ts.map +1 -0
  60. package/dist/internal/configSchema.js +57 -0
  61. package/dist/internal/configSchema.js.map +1 -0
  62. package/dist/internal/dereference.d.ts +12 -0
  63. package/dist/internal/dereference.d.ts.map +1 -0
  64. package/dist/internal/dereference.js +71 -0
  65. package/dist/internal/dereference.js.map +1 -0
  66. package/dist/internal/helpers.d.ts +9 -0
  67. package/dist/internal/helpers.d.ts.map +1 -0
  68. package/dist/internal/helpers.js +54 -0
  69. package/dist/internal/helpers.js.map +1 -0
  70. package/dist/middleware.d.ts +6 -8
  71. package/dist/middleware.d.ts.map +1 -1
  72. package/dist/middleware.js +1 -1
  73. package/dist/middleware.js.map +1 -1
  74. package/examples/npm/.npmrc.json +21 -0
  75. package/examples/npm/config.schema.json +134 -0
  76. package/package.json +6 -29
  77. package/src/Cli.test-d.ts +44 -33
  78. package/src/Cli.test.ts +1231 -101
  79. package/src/Cli.ts +877 -569
  80. package/src/Completions.test.ts +136 -12
  81. package/src/Completions.ts +18 -13
  82. package/src/Fetch.test.ts +21 -0
  83. package/src/Fetch.ts +8 -10
  84. package/src/Filter.ts +0 -17
  85. package/src/Formatter.test.ts +15 -2
  86. package/src/Formatter.ts +5 -1
  87. package/src/Help.test.ts +184 -20
  88. package/src/Help.ts +52 -28
  89. package/src/Mcp.test.ts +159 -0
  90. package/src/Mcp.ts +108 -86
  91. package/src/Openapi.test.ts +17 -5
  92. package/src/Openapi.ts +21 -15
  93. package/src/Parser.test-d.ts +22 -0
  94. package/src/Parser.test.ts +89 -0
  95. package/src/Parser.ts +87 -36
  96. package/src/Schema.test.ts +29 -0
  97. package/src/Schema.ts +12 -2
  98. package/src/Skill.test.ts +87 -6
  99. package/src/Skill.ts +38 -21
  100. package/src/Skillgen.ts +1 -1
  101. package/src/SyncMcp.test.ts +6 -8
  102. package/src/SyncSkills.test.ts +146 -3
  103. package/src/SyncSkills.ts +191 -10
  104. package/src/Typegen.test.ts +15 -0
  105. package/src/Typegen.ts +4 -2
  106. package/src/bin.ts +21 -2
  107. package/src/e2e.test.ts +188 -98
  108. package/src/internal/command.ts +449 -0
  109. package/src/internal/configSchema.test.ts +193 -0
  110. package/src/internal/configSchema.ts +66 -0
  111. package/src/internal/dereference.test.ts +695 -0
  112. package/src/internal/dereference.ts +75 -0
  113. package/src/internal/helpers.test.ts +75 -0
  114. package/src/internal/helpers.ts +59 -0
  115. package/src/middleware.ts +5 -12
@@ -0,0 +1,9 @@
1
+ /** Checks whether a value is a plain object record. */
2
+ export declare function isRecord(value: unknown): value is Record<string, unknown>;
3
+ /** Converts a camelCase string to kebab-case. */
4
+ export declare function toKebab(value: string): string;
5
+ /** Computes the Levenshtein edit distance between two strings. */
6
+ export declare function levenshtein(a: string, b: string): number;
7
+ /** Suggests the closest command name from a set, returning it if within a reasonable edit distance. */
8
+ export declare function suggest(input: string, candidates: Iterable<string>): string | undefined;
9
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/internal/helpers.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAEzE;AAED,iDAAiD;AACjD,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,kEAAkE;AAClE,wBAAgB,WAAW,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAcxD;AAED,uGAAuG;AACvG,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,SAAS,CA8BvF"}
@@ -0,0 +1,54 @@
1
+ /** Checks whether a value is a plain object record. */
2
+ export function isRecord(value) {
3
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
4
+ }
5
+ /** Converts a camelCase string to kebab-case. */
6
+ export function toKebab(value) {
7
+ return value.replace(/[A-Z]/g, (c) => `-${c.toLowerCase()}`);
8
+ }
9
+ /** Computes the Levenshtein edit distance between two strings. */
10
+ export function levenshtein(a, b) {
11
+ const m = a.length;
12
+ const n = b.length;
13
+ const dp = Array.from({ length: n + 1 }, (_, i) => i);
14
+ for (let i = 1; i <= m; i++) {
15
+ let prev = dp[0];
16
+ dp[0] = i;
17
+ for (let j = 1; j <= n; j++) {
18
+ const tmp = dp[j];
19
+ dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, dp[j], dp[j - 1]);
20
+ prev = tmp;
21
+ }
22
+ }
23
+ return dp[n];
24
+ }
25
+ /** Suggests the closest command name from a set, returning it if within a reasonable edit distance. */
26
+ export function suggest(input, candidates) {
27
+ const threshold = input.length <= 4 ? 2 : Math.floor(input.length / 2);
28
+ const lower = input.toLowerCase();
29
+ const all = Array.isArray(candidates) ? candidates : [...candidates];
30
+ let best;
31
+ let bestScore = Infinity;
32
+ for (const c of all) {
33
+ const lc = c.toLowerCase();
34
+ const dist = levenshtein(lower, lc);
35
+ let score;
36
+ if (lc.startsWith(lower) && lc !== lower)
37
+ // prefix match — best tier
38
+ score = dist;
39
+ else if (lc.includes(lower))
40
+ // contains match — middle tier
41
+ score = 100 + dist;
42
+ else if (dist <= threshold)
43
+ // fuzzy match — last tier
44
+ score = 200 + dist;
45
+ else
46
+ continue;
47
+ if (score < bestScore) {
48
+ bestScore = score;
49
+ best = c;
50
+ }
51
+ }
52
+ return best;
53
+ }
54
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/internal/helpers.ts"],"names":[],"mappings":"AAAA,uDAAuD;AACvD,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,iDAAiD;AACjD,MAAM,UAAU,OAAO,CAAC,KAAa;IACnC,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CAAA;AAC9D,CAAC;AAED,kEAAkE;AAClE,MAAM,UAAU,WAAW,CAAC,CAAS,EAAE,CAAS;IAC9C,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAA;IAClB,MAAM,EAAE,GAAa,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAA;IAC/D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5B,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAE,CAAA;QACjB,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;QACT,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5B,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAE,CAAA;YAClB,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAE,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAE,CAAC,CAAA;YAC7E,IAAI,GAAG,GAAG,CAAA;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC,CAAC,CAAE,CAAA;AACf,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,OAAO,CAAC,KAAa,EAAE,UAA4B;IACjE,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IACtE,MAAM,KAAK,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;IACjC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAA;IAEpE,IAAI,IAAwB,CAAA;IAC5B,IAAI,SAAS,GAAG,QAAQ,CAAA;IAExB,KAAK,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC;QACpB,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,CAAA;QAC1B,MAAM,IAAI,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;QAEnC,IAAI,KAAa,CAAA;QACjB,IAAI,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,KAAK;YACtC,2BAA2B;YAC3B,KAAK,GAAG,IAAI,CAAA;aACT,IAAI,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YACzB,+BAA+B;YAC/B,KAAK,GAAG,GAAG,GAAG,IAAI,CAAA;aACf,IAAI,IAAI,IAAI,SAAS;YACxB,0BAA0B;YAC1B,KAAK,GAAG,GAAG,GAAG,IAAI,CAAA;;YACf,SAAQ;QAEb,IAAI,KAAK,GAAG,SAAS,EAAE,CAAC;YACtB,SAAS,GAAG,KAAK,CAAA;YACjB,IAAI,GAAG,CAAC,CAAA;QACV,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC"}
@@ -4,10 +4,8 @@ import type * as Formatter from './Formatter.js';
4
4
  type InferVars<vars extends z.ZodObject<any> | undefined> = vars extends z.ZodObject<any> ? z.output<vars> : {};
5
5
  /** @internal Infers the output type of an env schema, or `{}` if undefined. */
6
6
  type InferEnv<env extends z.ZodObject<any> | undefined> = env extends z.ZodObject<any> ? z.output<env> : {};
7
- /** @internal Infers the output type of an options schema, or `{}` if undefined. */
8
- type InferOptions<options extends z.ZodObject<any> | undefined> = options extends z.ZodObject<any> ? z.output<options> : {};
9
7
  /** Middleware handler that runs before/after command execution. */
10
- export type Handler<vars extends z.ZodObject<any> | undefined = undefined, env extends z.ZodObject<any> | undefined = undefined, options extends z.ZodObject<any> | undefined = undefined> = (context: Context<vars, env, options>, next: () => Promise<void>) => Promise<void> | void;
8
+ export type Handler<vars extends z.ZodObject<any> | undefined = undefined, env extends z.ZodObject<any> | undefined = undefined> = (context: Context<vars, env>, next: () => Promise<void>) => Promise<void> | void;
11
9
  /** CTA block for middleware error/ok responses. */
12
10
  type CtaBlock = {
13
11
  /** Commands to suggest. */
@@ -19,11 +17,13 @@ type CtaBlock = {
19
17
  description?: string | undefined;
20
18
  };
21
19
  /** Context available inside middleware. */
22
- export type Context<vars extends z.ZodObject<any> | undefined = undefined, env extends z.ZodObject<any> | undefined = undefined, options extends z.ZodObject<any> | undefined = undefined> = {
20
+ export type Context<vars extends z.ZodObject<any> | undefined = undefined, env extends z.ZodObject<any> | undefined = undefined> = {
23
21
  /** Whether the consumer is an agent (stdout is not a TTY). */
24
22
  agent: boolean;
25
23
  /** The resolved command path. */
26
24
  command: string;
25
+ /** The binary name the user invoked (e.g. an alias). Falls back to `name` when not resolvable. */
26
+ displayName: string;
27
27
  /** Parsed environment variables from the CLI-level env schema. */
28
28
  env: InferEnv<env>;
29
29
  /** Return an error result, short-circuiting the middleware chain. */
@@ -40,8 +40,6 @@ export type Context<vars extends z.ZodObject<any> | undefined = undefined, env e
40
40
  formatExplicit: boolean;
41
41
  /** The CLI name. */
42
42
  name: string;
43
- /** Parsed options from the root CLI-level options schema. */
44
- options: InferOptions<options>;
45
43
  /** Set a typed variable for downstream middleware and handlers. */
46
44
  set<key extends string & keyof InferVars<vars>>(key: key, value: InferVars<vars>[key]): void;
47
45
  /** Variables set by upstream middleware. */
@@ -49,7 +47,7 @@ export type Context<vars extends z.ZodObject<any> | undefined = undefined, env e
49
47
  /** The CLI version string. */
50
48
  version: string | undefined;
51
49
  };
52
- /** Creates a strictly typed middleware handler. Pass the vars schema as a generic for typed `c.set()` and `c.var`, the env schema for typed `c.env`, and the options schema for typed `c.options`. */
53
- export default function middleware<const vars extends z.ZodObject<any> | undefined = undefined, const env extends z.ZodObject<any> | undefined = undefined, const options extends z.ZodObject<any> | undefined = undefined>(handler: Handler<vars, env, options>): Handler<vars, env, options>;
50
+ /** Creates a strictly typed middleware handler. Pass the vars schema as a generic for typed `c.set()` and `c.var`, and the env schema for typed `c.env`. */
51
+ export default function middleware<const vars extends z.ZodObject<any> | undefined = undefined, const env extends z.ZodObject<any> | undefined = undefined>(handler: Handler<vars, env>): Handler<vars, env>;
54
52
  export {};
55
53
  //# sourceMappingURL=middleware.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- /** Creates a strictly typed middleware handler. Pass the vars schema as a generic for typed `c.set()` and `c.var`, the env schema for typed `c.env`, and the options schema for typed `c.options`. */
1
+ /** Creates a strictly typed middleware handler. Pass the vars schema as a generic for typed `c.set()` and `c.var`, and the env schema for typed `c.env`. */
2
2
  export default function middleware(handler) {
3
3
  return handler;
4
4
  }
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAmEA,sMAAsM;AACtM,MAAM,CAAC,OAAO,UAAU,UAAU,CAIhC,OAAoC;IACpC,OAAO,OAAO,CAAA;AAChB,CAAC"}
1
+ {"version":3,"file":"middleware.js","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AA6DA,4JAA4J;AAC5J,MAAM,CAAC,OAAO,UAAU,UAAU,CAGhC,OAA2B;IAC3B,OAAO,OAAO,CAAA;AAChB,CAAC"}
@@ -0,0 +1,21 @@
1
+ {
2
+ "$schema": "./config.schema.json",
3
+ "commands": {
4
+ "install": {
5
+ "options": {
6
+ "saveExact": true
7
+ }
8
+ },
9
+ "publish": {
10
+ "options": {
11
+ "access": "public",
12
+ "tag": "latest"
13
+ }
14
+ },
15
+ "outdated": {
16
+ "options": {
17
+ "long": true
18
+ }
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,134 @@
1
+ {
2
+ "type": "object",
3
+ "additionalProperties": false,
4
+ "properties": {
5
+ "$schema": {
6
+ "type": "string"
7
+ },
8
+ "commands": {
9
+ "type": "object",
10
+ "additionalProperties": false,
11
+ "properties": {
12
+ "install": {
13
+ "type": "object",
14
+ "additionalProperties": false,
15
+ "properties": {
16
+ "options": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "saveDev": {
21
+ "description": "Save as dev dependency",
22
+ "type": "boolean"
23
+ },
24
+ "saveExact": {
25
+ "description": "Save exact version",
26
+ "type": "boolean"
27
+ },
28
+ "global": {
29
+ "description": "Install globally",
30
+ "type": "boolean"
31
+ }
32
+ }
33
+ }
34
+ }
35
+ },
36
+ "info": {
37
+ "type": "object",
38
+ "additionalProperties": false
39
+ },
40
+ "init": {
41
+ "type": "object",
42
+ "additionalProperties": false,
43
+ "properties": {
44
+ "options": {
45
+ "type": "object",
46
+ "additionalProperties": false,
47
+ "properties": {
48
+ "yes": {
49
+ "type": "boolean",
50
+ "description": "Skip prompts and use defaults"
51
+ },
52
+ "scope": {
53
+ "description": "Package scope",
54
+ "type": "string"
55
+ }
56
+ }
57
+ }
58
+ }
59
+ },
60
+ "publish": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "properties": {
64
+ "options": {
65
+ "type": "object",
66
+ "additionalProperties": false,
67
+ "properties": {
68
+ "tag": {
69
+ "default": "latest",
70
+ "description": "Distribution tag",
71
+ "type": "string"
72
+ },
73
+ "access": {
74
+ "default": "public",
75
+ "description": "Package access level",
76
+ "type": "string",
77
+ "enum": ["public", "restricted"]
78
+ },
79
+ "dryRun": {
80
+ "type": "boolean",
81
+ "description": "Report what would be published"
82
+ },
83
+ "otp": {
84
+ "description": "One-time password for 2FA",
85
+ "type": "string"
86
+ }
87
+ }
88
+ }
89
+ }
90
+ },
91
+ "run": {
92
+ "type": "object",
93
+ "additionalProperties": false
94
+ },
95
+ "uninstall": {
96
+ "type": "object",
97
+ "additionalProperties": false,
98
+ "properties": {
99
+ "options": {
100
+ "type": "object",
101
+ "additionalProperties": false,
102
+ "properties": {
103
+ "global": {
104
+ "type": "boolean",
105
+ "description": "Remove global package"
106
+ }
107
+ }
108
+ }
109
+ }
110
+ },
111
+ "outdated": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "properties": {
115
+ "options": {
116
+ "type": "object",
117
+ "additionalProperties": false,
118
+ "properties": {
119
+ "global": {
120
+ "type": "boolean",
121
+ "description": "Check global packages"
122
+ },
123
+ "long": {
124
+ "type": "boolean",
125
+ "description": "Show extended information"
126
+ }
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
package/package.json CHANGED
@@ -1,22 +1,7 @@
1
1
  {
2
- "devDependencies": {
3
- "@changesets/cli": "latest",
4
- "@hono/zod-openapi": "^1.2.2",
5
- "@types/node": "latest",
6
- "@vitest/coverage-v8": "^4.0.18",
7
- "bun": "^1.3.10",
8
- "hono": "^4.12.5",
9
- "oxfmt": "^0.35.0",
10
- "oxlint": "^1.50.0",
11
- "tsx": "^4.21.0",
12
- "typescript": "latest",
13
- "vitest": "latest",
14
- "zile": "latest"
15
- },
16
- "[!start-pkg]": "",
17
2
  "name": "incur",
18
3
  "type": "module",
19
- "version": "0.4.0",
4
+ "version": "0.4.2",
20
5
  "license": "MIT",
21
6
  "repository": {
22
7
  "type": "git",
@@ -29,13 +14,16 @@
29
14
  "SKILL.md"
30
15
  ],
31
16
  "dependencies": {
32
- "@modelcontextprotocol/sdk": "^1.27.1",
33
- "@readme/openapi-parser": "^6.0.0",
17
+ "@cfworker/json-schema": "^4.1.1",
18
+ "@modelcontextprotocol/server": "^2.0.0-alpha.2",
34
19
  "@toon-format/toon": "^2.1.0",
35
20
  "tokenx": "^1.3.0",
36
21
  "yaml": "^2.8.2",
37
22
  "zod": "^4.3.6"
38
23
  },
24
+ "engines": {
25
+ "node": ">=22"
26
+ },
39
27
  "sideEffects": false,
40
28
  "bin": {
41
29
  "incur": "./dist/bin.js",
@@ -50,16 +38,5 @@
50
38
  "src": "./src/index.ts",
51
39
  "default": "./dist/index.js"
52
40
  }
53
- },
54
- "scripts": {
55
- "build": "zile",
56
- "changeset:publish": "zile publish:prepare && changeset publish && zile publish:post",
57
- "changeset:version": "changeset version",
58
- "check": "oxlint --fix --ignore-pattern package.json && oxfmt",
59
- "check:types": "tsc -b",
60
- "incur": "node --import tsx src/bin.ts",
61
- "cli:skills": "pnpm incur skills add",
62
- "dev": "zile dev",
63
- "test": "vitest"
64
41
  }
65
42
  }
package/src/Cli.test-d.ts CHANGED
@@ -279,50 +279,61 @@ test('env is typed in per-command middleware', () => {
279
279
  })
280
280
  })
281
281
 
282
- test('options are typed in middleware via .use()', () => {
283
- Cli.create('test', {
284
- options: z.object({
285
- token: z.string(),
286
- verbose: z.boolean().default(false),
287
- }),
288
- }).use((c, _next) => {
289
- expectTypeOf(c.options.token).toEqualTypeOf<string>()
290
- expectTypeOf(c.options.verbose).toEqualTypeOf<boolean>()
282
+ test('run() context exposes format metadata', () => {
283
+ const cli = Cli.create('test')
284
+ cli.command('ping', {
285
+ run(c) {
286
+ expectTypeOf(c.format).toEqualTypeOf<'toon' | 'json' | 'yaml' | 'md' | 'jsonl'>()
287
+ expectTypeOf(c.formatExplicit).toEqualTypeOf<boolean>()
288
+ return { pong: true }
289
+ },
291
290
  })
292
291
  })
293
292
 
294
- test('without options, c.options is empty object in middleware', () => {
295
- Cli.create('test').use((c, _next) => {
296
- expectTypeOf(c.options).toEqualTypeOf<{}>()
293
+ test('root run() context exposes displayName', () => {
294
+ Cli.create('test', {
295
+ run(c) {
296
+ expectTypeOf(c.displayName).toEqualTypeOf<string>()
297
+ return { pong: true }
298
+ },
297
299
  })
298
300
  })
299
301
 
300
- test('middleware<vars, env, options>() infers all three types', () => {
301
- const cli = Cli.create('test', {
302
- env: z.object({ API_TOKEN: z.string() }),
303
- options: z.object({ token: z.string() }),
304
- vars: z.object({ user: z.string() }),
302
+ test('create() accepts config-file defaults options', () => {
303
+ Cli.create('test', {
304
+ config: {},
305
305
  })
306
306
 
307
- const mw = middleware<typeof cli.vars, typeof cli.env, typeof cli.options>((c, _next) => {
308
- expectTypeOf(c.env.API_TOKEN).toEqualTypeOf<string>()
309
- expectTypeOf(c.options.token).toEqualTypeOf<string>()
310
- expectTypeOf(c.var.user).toEqualTypeOf<string>()
311
- c.set('user', 'alice')
307
+ Cli.create('test', {
308
+ config: { flag: 'config' },
312
309
  })
313
310
 
314
- expectTypeOf(mw).toEqualTypeOf<
315
- MiddlewareHandler<typeof cli.vars, typeof cli.env, typeof cli.options>
316
- >()
317
- })
311
+ Cli.create('test', {
312
+ config: { files: ['.myrc.json', '~/.config/my/config.json'] },
313
+ })
318
314
 
319
- test('run() context exposes format metadata', () => {
320
- const cli = Cli.create('test')
321
- cli.command('ping', {
322
- run(c) {
323
- expectTypeOf(c.format).toEqualTypeOf<'toon' | 'json' | 'yaml' | 'md' | 'jsonl'>()
324
- expectTypeOf(c.formatExplicit).toEqualTypeOf<boolean>()
325
- return { pong: true }
315
+ Cli.create('test', {
316
+ config: {
317
+ flag: 'config',
318
+ files: ['config.toml'],
319
+ loader: async (path) => {
320
+ if (!path) return undefined
321
+ return { key: 'value' }
322
+ },
326
323
  },
327
324
  })
325
+
326
+ Cli.create('test', {
327
+ config: { loader: async () => ({ key: 'value' }) },
328
+ })
329
+
330
+ Cli.create('test', {
331
+ // @ts-expect-error — flag must be a string
332
+ config: { flag: true },
333
+ })
334
+
335
+ Cli.create('test', {
336
+ // @ts-expect-error — files must be string[]
337
+ config: { files: [42] },
338
+ })
328
339
  })