incur 0.4.8 → 0.4.10

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 (88) hide show
  1. package/dist/Cli.d.ts +69 -19
  2. package/dist/Cli.d.ts.map +1 -1
  3. package/dist/Cli.js +419 -73
  4. package/dist/Cli.js.map +1 -1
  5. package/dist/Completions.d.ts +2 -1
  6. package/dist/Completions.d.ts.map +1 -1
  7. package/dist/Completions.js +52 -13
  8. package/dist/Completions.js.map +1 -1
  9. package/dist/Formatter.d.ts.map +1 -1
  10. package/dist/Formatter.js +6 -5
  11. package/dist/Formatter.js.map +1 -1
  12. package/dist/Help.d.ts +5 -0
  13. package/dist/Help.d.ts.map +1 -1
  14. package/dist/Help.js +19 -5
  15. package/dist/Help.js.map +1 -1
  16. package/dist/Mcp.d.ts +21 -0
  17. package/dist/Mcp.d.ts.map +1 -1
  18. package/dist/Mcp.js +44 -13
  19. package/dist/Mcp.js.map +1 -1
  20. package/dist/Parser.d.ts +14 -0
  21. package/dist/Parser.d.ts.map +1 -1
  22. package/dist/Parser.js +127 -1
  23. package/dist/Parser.js.map +1 -1
  24. package/dist/Skill.d.ts.map +1 -1
  25. package/dist/Skill.js +5 -2
  26. package/dist/Skill.js.map +1 -1
  27. package/dist/Skillgen.d.ts.map +1 -1
  28. package/dist/Skillgen.js +4 -38
  29. package/dist/Skillgen.js.map +1 -1
  30. package/dist/SyncMcp.d.ts.map +1 -1
  31. package/dist/SyncMcp.js +75 -8
  32. package/dist/SyncMcp.js.map +1 -1
  33. package/dist/SyncSkills.d.ts +9 -0
  34. package/dist/SyncSkills.d.ts.map +1 -1
  35. package/dist/SyncSkills.js +13 -74
  36. package/dist/SyncSkills.js.map +1 -1
  37. package/dist/bin.d.ts +1 -1
  38. package/dist/bin.d.ts.map +1 -1
  39. package/dist/internal/command.d.ts +31 -19
  40. package/dist/internal/command.d.ts.map +1 -1
  41. package/dist/internal/command.js +10 -5
  42. package/dist/internal/command.js.map +1 -1
  43. package/dist/internal/cta.d.ts +22 -0
  44. package/dist/internal/cta.d.ts.map +1 -0
  45. package/dist/internal/cta.js +25 -0
  46. package/dist/internal/cta.js.map +1 -0
  47. package/dist/internal/json.d.ts +5 -0
  48. package/dist/internal/json.d.ts.map +1 -0
  49. package/dist/internal/json.js +13 -0
  50. package/dist/internal/json.js.map +1 -0
  51. package/dist/internal/yaml.d.ts +12 -0
  52. package/dist/internal/yaml.d.ts.map +1 -0
  53. package/dist/internal/yaml.js +20 -0
  54. package/dist/internal/yaml.js.map +1 -0
  55. package/dist/middleware.d.ts +8 -4
  56. package/dist/middleware.d.ts.map +1 -1
  57. package/dist/middleware.js +1 -1
  58. package/dist/middleware.js.map +1 -1
  59. package/package.json +1 -1
  60. package/src/Cli.test-d.ts +73 -0
  61. package/src/Cli.test.ts +1536 -48
  62. package/src/Cli.ts +606 -108
  63. package/src/Completions.test.ts +85 -0
  64. package/src/Completions.ts +48 -9
  65. package/src/Formatter.test.ts +17 -0
  66. package/src/Formatter.ts +7 -5
  67. package/src/Help.test.ts +32 -1
  68. package/src/Help.ts +42 -4
  69. package/src/Mcp.test.ts +289 -0
  70. package/src/Mcp.ts +68 -13
  71. package/src/Parser.test.ts +173 -0
  72. package/src/Parser.ts +132 -1
  73. package/src/Skill.test.ts +6 -0
  74. package/src/Skill.ts +8 -5
  75. package/src/Skillgen.test.ts +55 -6
  76. package/src/Skillgen.ts +9 -35
  77. package/src/SyncMcp.test.ts +89 -0
  78. package/src/SyncMcp.ts +72 -8
  79. package/src/SyncSkills.test.ts +78 -1
  80. package/src/SyncSkills.ts +20 -78
  81. package/src/bun-compile.test.ts +5 -0
  82. package/src/e2e.test.ts +166 -12
  83. package/src/internal/command.ts +12 -4
  84. package/src/internal/cta.ts +58 -0
  85. package/src/internal/json.ts +16 -0
  86. package/src/internal/yaml.ts +23 -0
  87. package/src/lazy-imports.test.ts +94 -0
  88. package/src/middleware.ts +12 -3
@@ -0,0 +1,94 @@
1
+ import { execFile } from 'node:child_process'
2
+ import { mkdtemp, rm, writeFile } from 'node:fs/promises'
3
+ import { tmpdir } from 'node:os'
4
+ import { join } from 'node:path'
5
+
6
+ function exec(cmd: string, args: string[]): Promise<{ stdout: string; stderr: string }> {
7
+ return new Promise((resolve, reject) => {
8
+ execFile(
9
+ cmd,
10
+ args,
11
+ { cwd: join(import.meta.dirname, '..'), timeout: 30_000 },
12
+ (error, stdout, stderr) => {
13
+ if (error) reject(new Error(stderr?.trim() || stdout?.trim() || error.message))
14
+ else resolve({ stdout, stderr })
15
+ },
16
+ )
17
+ })
18
+ }
19
+
20
+ let dir: string
21
+ let src: string
22
+
23
+ describe('lazy imports', () => {
24
+ beforeAll(async () => {
25
+ dir = await mkdtemp(join(tmpdir(), 'incur-lazy-'))
26
+ src = join(dir, 'cli.mts')
27
+
28
+ // Records every module loaded during a CLI run, then prints the heavy ones.
29
+ await writeFile(
30
+ src,
31
+ `
32
+ import { registerHooks } from 'node:module'
33
+
34
+ const loaded: string[] = []
35
+ registerHooks({
36
+ resolve(specifier, context, next) {
37
+ const result = next(specifier, context)
38
+ loaded.push(result.url)
39
+ return result
40
+ },
41
+ })
42
+
43
+ const { Cli, z } = await import('${join(import.meta.dirname, 'index.ts')}')
44
+
45
+ const cli = Cli.create('lazy-cli', { version: '1.0.0' })
46
+
47
+ cli.command('ping', {
48
+ description: 'Health check',
49
+ options: z.object({ upper: z.boolean().default(false) }),
50
+ run() {
51
+ return { pong: true }
52
+ },
53
+ })
54
+
55
+ await cli.serve(process.argv.slice(2))
56
+
57
+ const heavy = loaded.filter(
58
+ (url) => url.includes('@modelcontextprotocol') || url.includes('node_modules/yaml'),
59
+ )
60
+ console.log(JSON.stringify({ heavy }))
61
+ `,
62
+ )
63
+ })
64
+
65
+ afterAll(async () => {
66
+ await rm(dir, { recursive: true, force: true })
67
+ })
68
+
69
+ function parseHeavy(stdout: string): string[] {
70
+ const line = stdout.trim().split('\n').at(-1)!
71
+ return (JSON.parse(line) as { heavy: string[] }).heavy
72
+ }
73
+
74
+ test('plain command run does not load yaml or the MCP SDK', async () => {
75
+ const { stdout } = await exec(process.execPath, ['--import', 'tsx', src, 'ping'])
76
+ expect(stdout).toContain('pong: true')
77
+ expect(parseHeavy(stdout)).toEqual([])
78
+ })
79
+
80
+ test('--format yaml loads yaml on demand, but not the MCP SDK', async () => {
81
+ const { stdout } = await exec(process.execPath, [
82
+ '--import',
83
+ 'tsx',
84
+ src,
85
+ 'ping',
86
+ '--format',
87
+ 'yaml',
88
+ ])
89
+ expect(stdout).toContain('pong: true')
90
+ const heavy = parseHeavy(stdout)
91
+ expect(heavy.some((url) => url.includes('node_modules/yaml'))).toBe(true)
92
+ expect(heavy.some((url) => url.includes('@modelcontextprotocol'))).toBe(false)
93
+ })
94
+ })
package/src/middleware.ts CHANGED
@@ -10,11 +10,16 @@ type InferVars<vars extends z.ZodObject<any> | undefined> =
10
10
  type InferEnv<env extends z.ZodObject<any> | undefined> =
11
11
  env extends z.ZodObject<any> ? z.output<env> : {}
12
12
 
13
+ /** @internal Infers the output type of a globals schema, or `{}` if undefined. */
14
+ type InferGlobals<globals extends z.ZodObject<any> | undefined> =
15
+ globals extends z.ZodObject<any> ? z.output<globals> : {}
16
+
13
17
  /** Middleware handler that runs before/after command execution. */
14
18
  export type Handler<
15
19
  vars extends z.ZodObject<any> | undefined = undefined,
16
20
  env extends z.ZodObject<any> | undefined = undefined,
17
- > = (context: Context<vars, env>, next: () => Promise<void>) => Promise<void> | void
21
+ globals extends z.ZodObject<any> | undefined = undefined,
22
+ > = (context: Context<vars, env, globals>, next: () => Promise<void>) => Promise<void> | void
18
23
 
19
24
  /** CTA block for middleware error/ok responses. */
20
25
  type CtaBlock = {
@@ -28,6 +33,7 @@ type CtaBlock = {
28
33
  export type Context<
29
34
  vars extends z.ZodObject<any> | undefined = undefined,
30
35
  env extends z.ZodObject<any> | undefined = undefined,
36
+ globals extends z.ZodObject<any> | undefined = undefined,
31
37
  > = {
32
38
  /** Whether the consumer is an agent (stdout is not a TTY). */
33
39
  agent: boolean
@@ -49,6 +55,8 @@ export type Context<
49
55
  format: Formatter.Format
50
56
  /** Whether the user explicitly passed `--format` or `--json`. */
51
57
  formatExplicit: boolean
58
+ /** Parsed global options from the CLI-level globals schema. */
59
+ globals: InferGlobals<globals>
52
60
  /** The CLI name. */
53
61
  name: string
54
62
  /** Set a typed variable for downstream middleware and handlers. */
@@ -59,10 +67,11 @@ export type Context<
59
67
  version: string | undefined
60
68
  }
61
69
 
62
- /** 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`. */
70
+ /** 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 globals schema for typed `c.globals`. */
63
71
  export default function middleware<
64
72
  const vars extends z.ZodObject<any> | undefined = undefined,
65
73
  const env extends z.ZodObject<any> | undefined = undefined,
66
- >(handler: Handler<vars, env>): Handler<vars, env> {
74
+ const globals extends z.ZodObject<any> | undefined = undefined,
75
+ >(handler: Handler<vars, env, globals>): Handler<vars, env, globals> {
67
76
  return handler
68
77
  }