terminal-pilot 0.0.30 → 0.0.31
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/dist/cli.js +1375 -435
- package/dist/cli.js.map +4 -4
- package/dist/commands/close-session.js +485 -6
- package/dist/commands/close-session.js.map +4 -4
- package/dist/commands/create-session.js +485 -6
- package/dist/commands/create-session.js.map +4 -4
- package/dist/commands/fill.js +485 -6
- package/dist/commands/fill.js.map +4 -4
- package/dist/commands/get-session.js +485 -6
- package/dist/commands/get-session.js.map +4 -4
- package/dist/commands/index.js +626 -44
- package/dist/commands/index.js.map +4 -4
- package/dist/commands/install.js +622 -40
- package/dist/commands/install.js.map +4 -4
- package/dist/commands/installer.js +68 -17
- package/dist/commands/installer.js.map +4 -4
- package/dist/commands/list-sessions.js +485 -6
- package/dist/commands/list-sessions.js.map +4 -4
- package/dist/commands/press-key.js +485 -6
- package/dist/commands/press-key.js.map +4 -4
- package/dist/commands/read-history.js +485 -6
- package/dist/commands/read-history.js.map +4 -4
- package/dist/commands/read-screen.js +485 -6
- package/dist/commands/read-screen.js.map +4 -4
- package/dist/commands/resize.js +485 -6
- package/dist/commands/resize.js.map +4 -4
- package/dist/commands/screenshot.js +485 -6
- package/dist/commands/screenshot.js.map +4 -4
- package/dist/commands/send-signal.js +485 -6
- package/dist/commands/send-signal.js.map +4 -4
- package/dist/commands/type.js +485 -6
- package/dist/commands/type.js.map +4 -4
- package/dist/commands/uninstall.js +550 -20
- package/dist/commands/uninstall.js.map +4 -4
- package/dist/commands/wait-for-exit.js +485 -6
- package/dist/commands/wait-for-exit.js.map +4 -4
- package/dist/commands/wait-for.js +485 -6
- package/dist/commands/wait-for.js.map +4 -4
- package/dist/testing/cli-repl.js +1375 -435
- package/dist/testing/cli-repl.js.map +4 -4
- package/dist/testing/qa-cli.js +1385 -445
- package/dist/testing/qa-cli.js.map +4 -4
- package/node_modules/@poe-code/agent-defs/README.md +35 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/claude-code.js +21 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/claude-desktop.js +18 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/codex.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/codex.js +25 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/cursor.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/cursor.js +15 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/gemini-cli.js +16 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/goose.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/goose.js +16 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/index.d.ts +9 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/index.js +9 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/kimi.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/kimi.js +16 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/opencode.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/opencode.js +20 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.d.ts +2 -0
- package/node_modules/@poe-code/agent-defs/dist/agents/poe-agent.js +14 -0
- package/node_modules/@poe-code/agent-defs/dist/index.d.ts +5 -0
- package/node_modules/@poe-code/agent-defs/dist/index.js +3 -0
- package/node_modules/@poe-code/agent-defs/dist/registry.d.ts +3 -0
- package/node_modules/@poe-code/agent-defs/dist/registry.js +45 -0
- package/node_modules/@poe-code/agent-defs/dist/specifier.d.ts +7 -0
- package/node_modules/@poe-code/agent-defs/dist/specifier.js +40 -0
- package/node_modules/@poe-code/agent-defs/dist/types.d.ts +28 -0
- package/node_modules/@poe-code/agent-defs/dist/types.js +1 -0
- package/node_modules/@poe-code/agent-defs/package.json +20 -0
- package/node_modules/@poe-code/agent-skill-config/dist/apply.js +2 -1
- package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.d.ts +1 -0
- package/node_modules/@poe-code/agent-skill-config/dist/bridge-active-skills.js +37 -18
- package/node_modules/@poe-code/agent-skill-config/dist/resolve-skill-reference.js +8 -4
- package/node_modules/@poe-code/agent-skill-config/package.json +1 -5
- package/node_modules/@poe-code/config-mutations/README.md +55 -0
- package/node_modules/@poe-code/config-mutations/dist/error-codes.d.ts +1 -0
- package/node_modules/@poe-code/config-mutations/dist/error-codes.js +6 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.d.ts +6 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/apply-mutation.js +829 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.d.ts +17 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/path-utils.js +64 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.d.ts +7 -0
- package/node_modules/@poe-code/config-mutations/dist/execution/run-mutations.js +39 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/index.d.ts +13 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/index.js +49 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/json.d.ts +32 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/json.js +171 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/object.d.ts +4 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/object.js +27 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/toml.d.ts +2 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/toml.js +75 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/yaml.d.ts +2 -0
- package/node_modules/@poe-code/config-mutations/dist/formats/yaml.js +76 -0
- package/node_modules/@poe-code/config-mutations/dist/fs-utils.d.ts +18 -0
- package/node_modules/@poe-code/config-mutations/dist/fs-utils.js +43 -0
- package/node_modules/@poe-code/config-mutations/dist/index.d.ts +8 -0
- package/node_modules/@poe-code/config-mutations/dist/index.js +8 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.d.ts +47 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/config-mutation.js +34 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.d.ts +62 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/file-mutation.js +55 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.d.ts +40 -0
- package/node_modules/@poe-code/config-mutations/dist/mutations/template-mutation.js +32 -0
- package/node_modules/@poe-code/config-mutations/dist/template/render.d.ts +6 -0
- package/node_modules/@poe-code/config-mutations/dist/template/render.js +8 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.d.ts +7 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/format-utils.js +21 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/index.d.ts +3 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/index.js +2 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.d.ts +25 -0
- package/node_modules/@poe-code/config-mutations/dist/testing/mock-fs.js +194 -0
- package/node_modules/@poe-code/config-mutations/dist/types.d.ts +168 -0
- package/node_modules/@poe-code/config-mutations/dist/types.js +6 -0
- package/node_modules/@poe-code/config-mutations/package.json +29 -0
- package/node_modules/@poe-code/frontmatter/README.md +35 -0
- package/node_modules/@poe-code/frontmatter/dist/fences.d.ts +25 -0
- package/node_modules/@poe-code/frontmatter/dist/fences.js +100 -0
- package/node_modules/@poe-code/frontmatter/dist/index.d.ts +3 -0
- package/node_modules/@poe-code/frontmatter/dist/index.js +3 -0
- package/node_modules/@poe-code/frontmatter/dist/parse.d.ts +20 -0
- package/node_modules/@poe-code/frontmatter/dist/parse.js +209 -0
- package/node_modules/@poe-code/frontmatter/dist/stringify.d.ts +1 -0
- package/node_modules/@poe-code/frontmatter/dist/stringify.js +48 -0
- package/node_modules/@poe-code/frontmatter/package.json +25 -0
- package/node_modules/toolcraft-design/README.md +160 -0
- package/node_modules/toolcraft-design/dist/acp/components.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/acp/components.js +137 -0
- package/node_modules/toolcraft-design/dist/acp/index.d.ts +3 -0
- package/node_modules/toolcraft-design/dist/acp/index.js +2 -0
- package/node_modules/toolcraft-design/dist/acp/writer.d.ts +13 -0
- package/node_modules/toolcraft-design/dist/acp/writer.js +21 -0
- package/node_modules/toolcraft-design/dist/components/browser.d.ts +15 -0
- package/node_modules/toolcraft-design/dist/components/browser.js +31 -0
- package/node_modules/toolcraft-design/dist/components/catalog.d.ts +26 -0
- package/node_modules/toolcraft-design/dist/components/catalog.js +95 -0
- package/node_modules/toolcraft-design/dist/components/color.d.ts +31 -0
- package/node_modules/toolcraft-design/dist/components/color.js +102 -0
- package/node_modules/toolcraft-design/dist/components/command-errors.d.ts +16 -0
- package/node_modules/toolcraft-design/dist/components/command-errors.js +23 -0
- package/node_modules/toolcraft-design/dist/components/detail-card.d.ts +22 -0
- package/node_modules/toolcraft-design/dist/components/detail-card.js +45 -0
- package/node_modules/toolcraft-design/dist/components/help-formatter-plain.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/components/help-formatter-plain.js +132 -0
- package/node_modules/toolcraft-design/dist/components/help-formatter.d.ts +33 -0
- package/node_modules/toolcraft-design/dist/components/help-formatter.js +213 -0
- package/node_modules/toolcraft-design/dist/components/index.d.ts +16 -0
- package/node_modules/toolcraft-design/dist/components/index.js +10 -0
- package/node_modules/toolcraft-design/dist/components/logger.d.ts +11 -0
- package/node_modules/toolcraft-design/dist/components/logger.js +60 -0
- package/node_modules/toolcraft-design/dist/components/symbols.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/components/symbols.js +71 -0
- package/node_modules/toolcraft-design/dist/components/table.d.ts +15 -0
- package/node_modules/toolcraft-design/dist/components/table.js +302 -0
- package/node_modules/toolcraft-design/dist/components/template.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/components/template.js +437 -0
- package/node_modules/toolcraft-design/dist/components/text.d.ts +16 -0
- package/node_modules/toolcraft-design/dist/components/text.js +145 -0
- package/node_modules/toolcraft-design/dist/dashboard/ansi.d.ts +18 -0
- package/node_modules/toolcraft-design/dist/dashboard/ansi.js +343 -0
- package/node_modules/toolcraft-design/dist/dashboard/buffer.d.ts +25 -0
- package/node_modules/toolcraft-design/dist/dashboard/buffer.js +219 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/border.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/border.js +123 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/footer.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/footer.js +56 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/output-pane.js +268 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.d.ts +7 -0
- package/node_modules/toolcraft-design/dist/dashboard/components/stats-pane.js +107 -0
- package/node_modules/toolcraft-design/dist/dashboard/dashboard.d.ts +20 -0
- package/node_modules/toolcraft-design/dist/dashboard/dashboard.js +167 -0
- package/node_modules/toolcraft-design/dist/dashboard/demo.d.ts +13 -0
- package/node_modules/toolcraft-design/dist/dashboard/demo.js +145 -0
- package/node_modules/toolcraft-design/dist/dashboard/index.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/dashboard/index.js +4 -0
- package/node_modules/toolcraft-design/dist/dashboard/keymap.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/dashboard/keymap.js +233 -0
- package/node_modules/toolcraft-design/dist/dashboard/layout.d.ts +25 -0
- package/node_modules/toolcraft-design/dist/dashboard/layout.js +79 -0
- package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/dashboard/should-use-dashboard.js +7 -0
- package/node_modules/toolcraft-design/dist/dashboard/snapshot.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/dashboard/snapshot.js +68 -0
- package/node_modules/toolcraft-design/dist/dashboard/store.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/dashboard/store.js +51 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal-width.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal-width.js +71 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal.d.ts +37 -0
- package/node_modules/toolcraft-design/dist/dashboard/terminal.js +264 -0
- package/node_modules/toolcraft-design/dist/dashboard/types.d.ts +38 -0
- package/node_modules/toolcraft-design/dist/dashboard/types.js +1 -0
- package/node_modules/toolcraft-design/dist/explorer/actions.d.ts +16 -0
- package/node_modules/toolcraft-design/dist/explorer/actions.js +39 -0
- package/node_modules/toolcraft-design/dist/explorer/demo.d.ts +13 -0
- package/node_modules/toolcraft-design/dist/explorer/demo.js +297 -0
- package/node_modules/toolcraft-design/dist/explorer/events.d.ts +67 -0
- package/node_modules/toolcraft-design/dist/explorer/events.js +1 -0
- package/node_modules/toolcraft-design/dist/explorer/filter.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/explorer/filter.js +95 -0
- package/node_modules/toolcraft-design/dist/explorer/index.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/explorer/index.js +8 -0
- package/node_modules/toolcraft-design/dist/explorer/jobs.d.ts +7 -0
- package/node_modules/toolcraft-design/dist/explorer/jobs.js +59 -0
- package/node_modules/toolcraft-design/dist/explorer/keymap.d.ts +21 -0
- package/node_modules/toolcraft-design/dist/explorer/keymap.js +376 -0
- package/node_modules/toolcraft-design/dist/explorer/layout.d.ts +20 -0
- package/node_modules/toolcraft-design/dist/explorer/layout.js +73 -0
- package/node_modules/toolcraft-design/dist/explorer/reducer.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/explorer/reducer.js +782 -0
- package/node_modules/toolcraft-design/dist/explorer/render/detail.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/explorer/render/detail.js +97 -0
- package/node_modules/toolcraft-design/dist/explorer/render/footer.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/explorer/render/footer.js +73 -0
- package/node_modules/toolcraft-design/dist/explorer/render/header.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/explorer/render/header.js +49 -0
- package/node_modules/toolcraft-design/dist/explorer/render/index.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/explorer/render/index.js +53 -0
- package/node_modules/toolcraft-design/dist/explorer/render/list.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/explorer/render/list.js +116 -0
- package/node_modules/toolcraft-design/dist/explorer/render/modal.d.ts +3 -0
- package/node_modules/toolcraft-design/dist/explorer/render/modal.js +87 -0
- package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/explorer/render/test-fixtures.js +156 -0
- package/node_modules/toolcraft-design/dist/explorer/render/text.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/explorer/render/text.js +81 -0
- package/node_modules/toolcraft-design/dist/explorer/runtime.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/explorer/runtime.js +340 -0
- package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.d.ts +50 -0
- package/node_modules/toolcraft-design/dist/explorer/runtime.test-helpers.js +101 -0
- package/node_modules/toolcraft-design/dist/explorer/state.d.ts +137 -0
- package/node_modules/toolcraft-design/dist/explorer/state.js +86 -0
- package/node_modules/toolcraft-design/dist/explorer/theme.d.ts +27 -0
- package/node_modules/toolcraft-design/dist/explorer/theme.js +29 -0
- package/node_modules/toolcraft-design/dist/index.d.ts +50 -0
- package/node_modules/toolcraft-design/dist/index.js +43 -0
- package/node_modules/toolcraft-design/dist/internal/color-support.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/internal/color-support.js +12 -0
- package/node_modules/toolcraft-design/dist/internal/output-format.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/internal/output-format.js +22 -0
- package/node_modules/toolcraft-design/dist/internal/strip-ansi.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/internal/strip-ansi.js +50 -0
- package/node_modules/toolcraft-design/dist/internal/theme-detect.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/internal/theme-detect.js +71 -0
- package/node_modules/toolcraft-design/dist/internal/theme-state.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/internal/theme-state.js +35 -0
- package/node_modules/toolcraft-design/dist/prompts/index.d.ts +91 -0
- package/node_modules/toolcraft-design/dist/prompts/index.js +137 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/cancel-symbol.js +4 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.d.ts +9 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/confirm.js +47 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/core.d.ts +55 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/core.js +274 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.d.ts +20 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/glyphs.js +53 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/index.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/index.js +6 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/keys.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/keys.js +28 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.d.ts +13 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/multiselect.js +131 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/pagination.js +52 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/password.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/password.js +55 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/select.d.ts +18 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/select.js +89 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.d.ts +21 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/test-helpers.js +32 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/text.d.ts +12 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/text.js +60 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/prompts/interactive/wrap.js +18 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/cancel.js +9 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/intro.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/intro.js +16 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/log.d.ts +18 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/log.js +104 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/note.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/note.js +39 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/outro.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/outro.js +16 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/prompts/primitives/spinner.js +74 -0
- package/node_modules/toolcraft-design/dist/prompts/theme.d.ts +11 -0
- package/node_modules/toolcraft-design/dist/prompts/theme.js +15 -0
- package/node_modules/toolcraft-design/dist/static/index.d.ts +4 -0
- package/node_modules/toolcraft-design/dist/static/index.js +2 -0
- package/node_modules/toolcraft-design/dist/static/menu.d.ts +11 -0
- package/node_modules/toolcraft-design/dist/static/menu.js +42 -0
- package/node_modules/toolcraft-design/dist/static/spinner.d.ts +14 -0
- package/node_modules/toolcraft-design/dist/static/spinner.js +52 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/ast.d.ts +92 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/ast.js +1 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.d.ts +2 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/demo-content.js +139 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/index.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/index.js +8 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.d.ts +7 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/block.js +1495 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.d.ts +8 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/frontmatter.js +36 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.d.ts +10 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser/inline.js +1190 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/parser.js +42 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/renderer.js +615 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.d.ts +1 -0
- package/node_modules/toolcraft-design/dist/terminal-markdown/testing/theme-render-fixture.js +27 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/tokens/brand.js +5 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.d.ts +37 -0
- package/node_modules/toolcraft-design/dist/tokens/colors.js +85 -0
- package/node_modules/toolcraft-design/dist/tokens/index.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/tokens/index.js +5 -0
- package/node_modules/toolcraft-design/dist/tokens/spacing.d.ts +6 -0
- package/node_modules/toolcraft-design/dist/tokens/spacing.js +6 -0
- package/node_modules/toolcraft-design/dist/tokens/typography.d.ts +7 -0
- package/node_modules/toolcraft-design/dist/tokens/typography.js +8 -0
- package/node_modules/toolcraft-design/dist/tokens/widths.d.ts +5 -0
- package/node_modules/toolcraft-design/dist/tokens/widths.js +5 -0
- package/node_modules/toolcraft-design/package.json +44 -0
- package/package.json +15 -5
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { PathMapper } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Expand ~ shortcut to the provided home directory.
|
|
4
|
+
*/
|
|
5
|
+
export declare function expandHome(targetPath: string, homeDir: string): string;
|
|
6
|
+
/**
|
|
7
|
+
* Validate that a path is home-relative (starts with ~).
|
|
8
|
+
* Throws if the path is not home-relative.
|
|
9
|
+
*/
|
|
10
|
+
export declare function validateHomePath(targetPath: string): void;
|
|
11
|
+
/**
|
|
12
|
+
* Resolve a path with optional path mapping for isolated configurations.
|
|
13
|
+
* 1. Validates the path starts with ~
|
|
14
|
+
* 2. Expands ~ to home directory
|
|
15
|
+
* 3. If pathMapper is provided, maps the directory portion and reconstructs the path
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolvePath(rawPath: string, homeDir: string, pathMapper?: PathMapper): string;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Expand ~ shortcut to the provided home directory.
|
|
4
|
+
*/
|
|
5
|
+
export function expandHome(targetPath, homeDir) {
|
|
6
|
+
if (!targetPath?.startsWith("~")) {
|
|
7
|
+
return targetPath;
|
|
8
|
+
}
|
|
9
|
+
// Handle ~./ -> ~/.
|
|
10
|
+
if (targetPath.startsWith("~./")) {
|
|
11
|
+
targetPath = `~/.${targetPath.slice(3)}`;
|
|
12
|
+
}
|
|
13
|
+
let remainder = targetPath.slice(1);
|
|
14
|
+
// Remove leading slash or backslash
|
|
15
|
+
if (remainder.startsWith("/") || remainder.startsWith("\\")) {
|
|
16
|
+
remainder = remainder.slice(1);
|
|
17
|
+
}
|
|
18
|
+
else if (remainder.startsWith(".")) {
|
|
19
|
+
// Handle ~/.
|
|
20
|
+
remainder = remainder.slice(1);
|
|
21
|
+
if (remainder.startsWith("/") || remainder.startsWith("\\")) {
|
|
22
|
+
remainder = remainder.slice(1);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return remainder.length === 0 ? homeDir : path.join(homeDir, remainder);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Validate that a path is home-relative (starts with ~).
|
|
29
|
+
* Throws if the path is not home-relative.
|
|
30
|
+
*/
|
|
31
|
+
export function validateHomePath(targetPath) {
|
|
32
|
+
if (typeof targetPath !== "string" || targetPath.length === 0) {
|
|
33
|
+
throw new Error("Target path must be a non-empty string.");
|
|
34
|
+
}
|
|
35
|
+
if (!targetPath.startsWith("~")) {
|
|
36
|
+
throw new Error(`All target paths must be home-relative (start with ~). Received: "${targetPath}"`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Resolve a path with optional path mapping for isolated configurations.
|
|
41
|
+
* 1. Validates the path starts with ~
|
|
42
|
+
* 2. Expands ~ to home directory
|
|
43
|
+
* 3. If pathMapper is provided, maps the directory portion and reconstructs the path
|
|
44
|
+
*/
|
|
45
|
+
export function resolvePath(rawPath, homeDir, pathMapper) {
|
|
46
|
+
validateHomePath(rawPath);
|
|
47
|
+
const expanded = expandHome(rawPath, homeDir);
|
|
48
|
+
const canonicalHome = path.resolve(homeDir);
|
|
49
|
+
const canonicalExpanded = path.resolve(expanded);
|
|
50
|
+
const relative = path.relative(canonicalHome, canonicalExpanded);
|
|
51
|
+
if (relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
52
|
+
throw new Error(`Target path resolves outside home directory: "${rawPath}"`);
|
|
53
|
+
}
|
|
54
|
+
if (!pathMapper) {
|
|
55
|
+
return canonicalExpanded;
|
|
56
|
+
}
|
|
57
|
+
// Map the directory portion
|
|
58
|
+
const rawDirectory = path.dirname(expanded);
|
|
59
|
+
const mappedDirectory = pathMapper.mapTargetDirectory({
|
|
60
|
+
targetDirectory: rawDirectory
|
|
61
|
+
});
|
|
62
|
+
const filename = path.basename(expanded);
|
|
63
|
+
return filename.length === 0 ? mappedDirectory : path.join(mappedDirectory, filename);
|
|
64
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Mutation, MutationContext, MutationResult, MutationOptions } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute an array of mutations in order.
|
|
4
|
+
*
|
|
5
|
+
* All dependencies must be injected - no defaults, no globals.
|
|
6
|
+
*/
|
|
7
|
+
export declare function runMutations(mutations: Mutation[], context: MutationContext, options?: MutationOptions): Promise<MutationResult>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { applyMutation, resolveMutationDetails } from "./apply-mutation.js";
|
|
2
|
+
/**
|
|
3
|
+
* Execute an array of mutations in order.
|
|
4
|
+
*
|
|
5
|
+
* All dependencies must be injected - no defaults, no globals.
|
|
6
|
+
*/
|
|
7
|
+
export async function runMutations(mutations, context, options) {
|
|
8
|
+
const effects = [];
|
|
9
|
+
let anyChanged = false;
|
|
10
|
+
const resolverOptions = options ?? {};
|
|
11
|
+
for (const mutation of mutations) {
|
|
12
|
+
const { outcome } = await executeMutation(mutation, context, resolverOptions);
|
|
13
|
+
effects.push(outcome);
|
|
14
|
+
if (outcome.changed) {
|
|
15
|
+
anyChanged = true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
changed: anyChanged,
|
|
20
|
+
effects
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
async function executeMutation(mutation, context, options) {
|
|
24
|
+
const pendingDetails = resolveMutationDetails(mutation, context, options);
|
|
25
|
+
// Call onStart observer
|
|
26
|
+
context.observers?.onStart?.(pendingDetails);
|
|
27
|
+
try {
|
|
28
|
+
const { outcome, details } = await applyMutation(mutation, context, options);
|
|
29
|
+
// Call onComplete observer
|
|
30
|
+
context.observers?.onComplete?.(details, outcome);
|
|
31
|
+
return { outcome, details };
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
// Call onError observer
|
|
35
|
+
context.observers?.onError?.(pendingDetails, error);
|
|
36
|
+
// Re-throw the error
|
|
37
|
+
throw error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ConfigFormat } from "../types.js";
|
|
2
|
+
export type FormatName = "json" | "toml" | "yaml";
|
|
3
|
+
/**
|
|
4
|
+
* Get a format handler by path (auto-detect from extension) or explicit format name.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getConfigFormat(pathOrFormat: string): ConfigFormat;
|
|
7
|
+
/**
|
|
8
|
+
* Detect format name from a file path.
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectFormat(path: string): FormatName | undefined;
|
|
11
|
+
export { jsonFormat } from "./json.js";
|
|
12
|
+
export { tomlFormat } from "./toml.js";
|
|
13
|
+
export { yamlFormat } from "./yaml.js";
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { jsonFormat } from "./json.js";
|
|
2
|
+
import { tomlFormat } from "./toml.js";
|
|
3
|
+
import { yamlFormat } from "./yaml.js";
|
|
4
|
+
const formatRegistry = {
|
|
5
|
+
json: jsonFormat,
|
|
6
|
+
toml: tomlFormat,
|
|
7
|
+
yaml: yamlFormat
|
|
8
|
+
};
|
|
9
|
+
const extensionMap = {
|
|
10
|
+
".json": "json",
|
|
11
|
+
".toml": "toml",
|
|
12
|
+
".yaml": "yaml",
|
|
13
|
+
".yml": "yaml"
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Get a format handler by path (auto-detect from extension) or explicit format name.
|
|
17
|
+
*/
|
|
18
|
+
export function getConfigFormat(pathOrFormat) {
|
|
19
|
+
// Check if it's an explicit format name
|
|
20
|
+
if (Object.prototype.hasOwnProperty.call(formatRegistry, pathOrFormat)) {
|
|
21
|
+
return formatRegistry[pathOrFormat];
|
|
22
|
+
}
|
|
23
|
+
// Try to detect from extension
|
|
24
|
+
const ext = getExtension(pathOrFormat);
|
|
25
|
+
const formatName = extensionMap[ext];
|
|
26
|
+
if (!formatName) {
|
|
27
|
+
throw new Error(`Unsupported config format. Cannot detect format from "${pathOrFormat}". ` +
|
|
28
|
+
`Supported extensions: ${Object.keys(extensionMap).join(", ")}. ` +
|
|
29
|
+
`Supported format names: ${Object.keys(formatRegistry).join(", ")}.`);
|
|
30
|
+
}
|
|
31
|
+
return formatRegistry[formatName];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Detect format name from a file path.
|
|
35
|
+
*/
|
|
36
|
+
export function detectFormat(path) {
|
|
37
|
+
const ext = getExtension(path);
|
|
38
|
+
return extensionMap[ext];
|
|
39
|
+
}
|
|
40
|
+
function getExtension(path) {
|
|
41
|
+
const lastDot = path.lastIndexOf(".");
|
|
42
|
+
if (lastDot === -1) {
|
|
43
|
+
return "";
|
|
44
|
+
}
|
|
45
|
+
return path.slice(lastDot).toLowerCase();
|
|
46
|
+
}
|
|
47
|
+
export { jsonFormat } from "./json.js";
|
|
48
|
+
export { tomlFormat } from "./toml.js";
|
|
49
|
+
export { yamlFormat } from "./yaml.js";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { ConfigFormat, ConfigObject, ConfigValue } from "../types.js";
|
|
2
|
+
declare function detectIndent(content: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* Modify JSON content at a specific path while preserving comments and formatting.
|
|
5
|
+
* Uses jsonc-parser's modify() for targeted updates.
|
|
6
|
+
*
|
|
7
|
+
* @param content - The original JSON content (may include comments)
|
|
8
|
+
* @param path - JSON path array, e.g. ["mcpServers", "my-server"]
|
|
9
|
+
* @param value - The value to set (or undefined to remove)
|
|
10
|
+
* @returns The modified JSON content with comments preserved
|
|
11
|
+
*/
|
|
12
|
+
declare function modifyAtPath(content: string, path: (string | number)[], value: ConfigValue | undefined): string;
|
|
13
|
+
/**
|
|
14
|
+
* Merge a patch into JSON content while preserving comments and formatting.
|
|
15
|
+
* Uses jsonc.modify() for each top-level key to preserve existing comments.
|
|
16
|
+
*
|
|
17
|
+
* @param content - The original JSON content (may include comments)
|
|
18
|
+
* @param patch - Object with values to merge
|
|
19
|
+
* @returns The modified JSON content with comments preserved
|
|
20
|
+
*/
|
|
21
|
+
declare function mergePreservingComments(content: string, patch: ConfigObject): string;
|
|
22
|
+
/**
|
|
23
|
+
* Remove a key from JSON content while preserving comments and formatting.
|
|
24
|
+
*
|
|
25
|
+
* @param content - The original JSON content
|
|
26
|
+
* @param path - JSON path array to the key to remove
|
|
27
|
+
* @returns The modified JSON content with comments preserved
|
|
28
|
+
*/
|
|
29
|
+
declare function removeAtPath(content: string, path: (string | number)[]): string;
|
|
30
|
+
declare function serializeUpdate(content: string, current: ConfigObject, next: ConfigObject): string;
|
|
31
|
+
export { detectIndent, modifyAtPath, mergePreservingComments, removeAtPath, serializeUpdate };
|
|
32
|
+
export declare const jsonFormat: ConfigFormat;
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import * as jsonc from "jsonc-parser";
|
|
2
|
+
import { cloneConfigObject, hasConfigEntry, setConfigEntry } from "./object.js";
|
|
3
|
+
function isConfigObject(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function detectIndent(content) {
|
|
7
|
+
const match = content.match(/^[\t ]+/m);
|
|
8
|
+
if (match) {
|
|
9
|
+
return match[0];
|
|
10
|
+
}
|
|
11
|
+
return " ";
|
|
12
|
+
}
|
|
13
|
+
function parse(content) {
|
|
14
|
+
if (!content || content.trim() === "") {
|
|
15
|
+
return {};
|
|
16
|
+
}
|
|
17
|
+
const errors = [];
|
|
18
|
+
const parsed = jsonc.parse(content, errors, {
|
|
19
|
+
allowTrailingComma: true,
|
|
20
|
+
disallowComments: false
|
|
21
|
+
});
|
|
22
|
+
if (errors.length > 0) {
|
|
23
|
+
throw new Error(`JSON parse error: ${jsonc.printParseErrorCode(errors[0].error)}`);
|
|
24
|
+
}
|
|
25
|
+
if (parsed === null || parsed === undefined) {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
if (!isConfigObject(parsed)) {
|
|
29
|
+
throw new Error("Expected JSON object.");
|
|
30
|
+
}
|
|
31
|
+
return cloneConfigObject(parsed);
|
|
32
|
+
}
|
|
33
|
+
function serialize(obj) {
|
|
34
|
+
return `${JSON.stringify(obj, null, 2)}\n`;
|
|
35
|
+
}
|
|
36
|
+
function merge(base, patch) {
|
|
37
|
+
const result = cloneConfigObject(base);
|
|
38
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
39
|
+
if (value === undefined) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const existing = hasConfigEntry(result, key) ? result[key] : undefined;
|
|
43
|
+
if (isConfigObject(existing) && isConfigObject(value)) {
|
|
44
|
+
setConfigEntry(result, key, merge(existing, value));
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
setConfigEntry(result, key, value);
|
|
48
|
+
}
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
function configValuesEqual(left, right) {
|
|
52
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
53
|
+
}
|
|
54
|
+
function prune(obj, shape) {
|
|
55
|
+
let changed = false;
|
|
56
|
+
const result = cloneConfigObject(obj);
|
|
57
|
+
for (const [key, pattern] of Object.entries(shape)) {
|
|
58
|
+
if (!hasConfigEntry(result, key)) {
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
const current = result[key];
|
|
62
|
+
// Empty object pattern means "delete this key entirely"
|
|
63
|
+
if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {
|
|
64
|
+
delete result[key];
|
|
65
|
+
changed = true;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// Non-empty object pattern with object current: recurse
|
|
69
|
+
if (isConfigObject(pattern) && isConfigObject(current)) {
|
|
70
|
+
const { changed: childChanged, result: childResult } = prune(current, pattern);
|
|
71
|
+
if (childChanged) {
|
|
72
|
+
changed = true;
|
|
73
|
+
}
|
|
74
|
+
if (Object.keys(childResult).length === 0) {
|
|
75
|
+
delete result[key];
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
setConfigEntry(result, key, childResult);
|
|
79
|
+
}
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
if (isConfigObject(pattern) && Object.keys(pattern).length > 0) {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
delete result[key];
|
|
86
|
+
changed = true;
|
|
87
|
+
}
|
|
88
|
+
return { changed, result };
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Modify JSON content at a specific path while preserving comments and formatting.
|
|
92
|
+
* Uses jsonc-parser's modify() for targeted updates.
|
|
93
|
+
*
|
|
94
|
+
* @param content - The original JSON content (may include comments)
|
|
95
|
+
* @param path - JSON path array, e.g. ["mcpServers", "my-server"]
|
|
96
|
+
* @param value - The value to set (or undefined to remove)
|
|
97
|
+
* @returns The modified JSON content with comments preserved
|
|
98
|
+
*/
|
|
99
|
+
function modifyAtPath(content, path, value) {
|
|
100
|
+
const indent = detectIndent(content);
|
|
101
|
+
const formattingOptions = {
|
|
102
|
+
tabSize: indent === "\t" ? 1 : indent.length,
|
|
103
|
+
insertSpaces: indent !== "\t",
|
|
104
|
+
eol: "\n"
|
|
105
|
+
};
|
|
106
|
+
const edits = jsonc.modify(content, path, value, { formattingOptions });
|
|
107
|
+
let result = jsonc.applyEdits(content, edits);
|
|
108
|
+
if (!result.endsWith("\n")) {
|
|
109
|
+
result += "\n";
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Merge a patch into JSON content while preserving comments and formatting.
|
|
115
|
+
* Uses jsonc.modify() for each top-level key to preserve existing comments.
|
|
116
|
+
*
|
|
117
|
+
* @param content - The original JSON content (may include comments)
|
|
118
|
+
* @param patch - Object with values to merge
|
|
119
|
+
* @returns The modified JSON content with comments preserved
|
|
120
|
+
*/
|
|
121
|
+
function mergePreservingComments(content, patch) {
|
|
122
|
+
const current = parse(content);
|
|
123
|
+
return serializeUpdate(content || "{}", current, merge(current, patch));
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Remove a key from JSON content while preserving comments and formatting.
|
|
127
|
+
*
|
|
128
|
+
* @param content - The original JSON content
|
|
129
|
+
* @param path - JSON path array to the key to remove
|
|
130
|
+
* @returns The modified JSON content with comments preserved
|
|
131
|
+
*/
|
|
132
|
+
function removeAtPath(content, path) {
|
|
133
|
+
return modifyAtPath(content, path, undefined);
|
|
134
|
+
}
|
|
135
|
+
function serializeUpdate(content, current, next) {
|
|
136
|
+
let result = content || "{}";
|
|
137
|
+
result = applyObjectUpdate(result, [], current, next);
|
|
138
|
+
if (!result.endsWith("\n")) {
|
|
139
|
+
result += "\n";
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
}
|
|
143
|
+
function applyObjectUpdate(content, path, current, next) {
|
|
144
|
+
let result = content;
|
|
145
|
+
for (const key of Object.keys(current)) {
|
|
146
|
+
if (!hasConfigEntry(next, key)) {
|
|
147
|
+
result = removeAtPath(result, [...path, key]);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
for (const [key, nextValue] of Object.entries(next)) {
|
|
151
|
+
const nextPath = [...path, key];
|
|
152
|
+
const hasCurrent = hasConfigEntry(current, key);
|
|
153
|
+
const currentValue = hasCurrent ? current[key] : undefined;
|
|
154
|
+
if (hasCurrent && isConfigObject(currentValue) && isConfigObject(nextValue)) {
|
|
155
|
+
result = applyObjectUpdate(result, nextPath, currentValue, nextValue);
|
|
156
|
+
continue;
|
|
157
|
+
}
|
|
158
|
+
if (!hasCurrent || !configValuesEqual(currentValue, nextValue)) {
|
|
159
|
+
result = modifyAtPath(result, nextPath, nextValue);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
export { detectIndent, modifyAtPath, mergePreservingComments, removeAtPath, serializeUpdate };
|
|
165
|
+
export const jsonFormat = {
|
|
166
|
+
parse,
|
|
167
|
+
serialize,
|
|
168
|
+
serializeUpdate,
|
|
169
|
+
merge,
|
|
170
|
+
prune
|
|
171
|
+
};
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ConfigObject, ConfigValue } from "../types.js";
|
|
2
|
+
export declare function cloneConfigObject(value: ConfigObject): ConfigObject;
|
|
3
|
+
export declare function setConfigEntry(target: ConfigObject, key: string, value: ConfigValue): void;
|
|
4
|
+
export declare function hasConfigEntry(target: ConfigObject, key: string): boolean;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export function cloneConfigObject(value) {
|
|
2
|
+
const result = {};
|
|
3
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
4
|
+
setConfigEntry(result, key, cloneConfigValue(entry));
|
|
5
|
+
}
|
|
6
|
+
return result;
|
|
7
|
+
}
|
|
8
|
+
export function setConfigEntry(target, key, value) {
|
|
9
|
+
Object.defineProperty(target, key, {
|
|
10
|
+
configurable: true,
|
|
11
|
+
enumerable: true,
|
|
12
|
+
writable: true,
|
|
13
|
+
value
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function hasConfigEntry(target, key) {
|
|
17
|
+
return Object.prototype.hasOwnProperty.call(target, key);
|
|
18
|
+
}
|
|
19
|
+
function cloneConfigValue(value) {
|
|
20
|
+
if (Array.isArray(value)) {
|
|
21
|
+
return value.map((entry) => cloneConfigValue(entry));
|
|
22
|
+
}
|
|
23
|
+
if (value && typeof value === "object" && !(value instanceof Date)) {
|
|
24
|
+
return cloneConfigObject(value);
|
|
25
|
+
}
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
2
|
+
import { cloneConfigObject, hasConfigEntry, setConfigEntry } from "./object.js";
|
|
3
|
+
function isConfigObject(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function parse(content) {
|
|
7
|
+
if (!content || content.trim() === "") {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
const parsed = parseToml(content);
|
|
11
|
+
if (!isConfigObject(parsed)) {
|
|
12
|
+
throw new Error("Expected TOML document to be a table.");
|
|
13
|
+
}
|
|
14
|
+
return cloneConfigObject(parsed);
|
|
15
|
+
}
|
|
16
|
+
function serialize(obj) {
|
|
17
|
+
const serialized = stringifyToml(obj);
|
|
18
|
+
return serialized.endsWith("\n") ? serialized : `${serialized}\n`;
|
|
19
|
+
}
|
|
20
|
+
function merge(base, patch) {
|
|
21
|
+
const result = cloneConfigObject(base);
|
|
22
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
23
|
+
if (value === undefined) {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
const existing = hasConfigEntry(result, key) ? result[key] : undefined;
|
|
27
|
+
if (isConfigObject(existing) && isConfigObject(value)) {
|
|
28
|
+
setConfigEntry(result, key, merge(existing, value));
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
setConfigEntry(result, key, value);
|
|
32
|
+
}
|
|
33
|
+
return result;
|
|
34
|
+
}
|
|
35
|
+
function prune(obj, shape) {
|
|
36
|
+
let changed = false;
|
|
37
|
+
const result = cloneConfigObject(obj);
|
|
38
|
+
for (const [key, pattern] of Object.entries(shape)) {
|
|
39
|
+
if (!hasConfigEntry(result, key)) {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
const current = result[key];
|
|
43
|
+
// Empty object pattern means "delete this key entirely"
|
|
44
|
+
if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {
|
|
45
|
+
delete result[key];
|
|
46
|
+
changed = true;
|
|
47
|
+
continue;
|
|
48
|
+
}
|
|
49
|
+
// Non-empty object pattern with object current: recurse
|
|
50
|
+
if (isConfigObject(pattern) && isConfigObject(current)) {
|
|
51
|
+
const { changed: childChanged, result: childResult } = prune(current, pattern);
|
|
52
|
+
if (childChanged) {
|
|
53
|
+
changed = true;
|
|
54
|
+
}
|
|
55
|
+
if (Object.keys(childResult).length === 0) {
|
|
56
|
+
delete result[key];
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
setConfigEntry(result, key, childResult);
|
|
60
|
+
}
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {
|
|
64
|
+
delete result[key];
|
|
65
|
+
changed = true;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return { changed, result };
|
|
69
|
+
}
|
|
70
|
+
export const tomlFormat = {
|
|
71
|
+
parse,
|
|
72
|
+
serialize,
|
|
73
|
+
merge,
|
|
74
|
+
prune
|
|
75
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
2
|
+
import { cloneConfigObject, hasConfigEntry, setConfigEntry } from "./object.js";
|
|
3
|
+
function isConfigObject(value) {
|
|
4
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
5
|
+
}
|
|
6
|
+
function parse(content) {
|
|
7
|
+
if (!content || content.trim() === "") {
|
|
8
|
+
return {};
|
|
9
|
+
}
|
|
10
|
+
const parsed = parseYaml(content);
|
|
11
|
+
if (parsed === null || parsed === undefined) {
|
|
12
|
+
return {};
|
|
13
|
+
}
|
|
14
|
+
if (!isConfigObject(parsed)) {
|
|
15
|
+
throw new Error("Expected YAML object.");
|
|
16
|
+
}
|
|
17
|
+
return cloneConfigObject(parsed);
|
|
18
|
+
}
|
|
19
|
+
function serialize(obj) {
|
|
20
|
+
const serialized = stringifyYaml(obj);
|
|
21
|
+
return serialized.endsWith("\n") ? serialized : `${serialized}\n`;
|
|
22
|
+
}
|
|
23
|
+
function merge(base, patch) {
|
|
24
|
+
const result = cloneConfigObject(base);
|
|
25
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
26
|
+
if (value === undefined) {
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
const existing = hasConfigEntry(result, key) ? result[key] : undefined;
|
|
30
|
+
if (isConfigObject(existing) && isConfigObject(value)) {
|
|
31
|
+
setConfigEntry(result, key, merge(existing, value));
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
setConfigEntry(result, key, value);
|
|
35
|
+
}
|
|
36
|
+
return result;
|
|
37
|
+
}
|
|
38
|
+
function prune(obj, shape) {
|
|
39
|
+
let changed = false;
|
|
40
|
+
const result = cloneConfigObject(obj);
|
|
41
|
+
for (const [key, pattern] of Object.entries(shape)) {
|
|
42
|
+
if (!hasConfigEntry(result, key)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
const current = result[key];
|
|
46
|
+
if (isConfigObject(pattern) && Object.keys(pattern).length === 0) {
|
|
47
|
+
delete result[key];
|
|
48
|
+
changed = true;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (isConfigObject(pattern) && isConfigObject(current)) {
|
|
52
|
+
const { changed: childChanged, result: childResult } = prune(current, pattern);
|
|
53
|
+
if (childChanged) {
|
|
54
|
+
changed = true;
|
|
55
|
+
}
|
|
56
|
+
if (Object.keys(childResult).length === 0) {
|
|
57
|
+
delete result[key];
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
setConfigEntry(result, key, childResult);
|
|
61
|
+
}
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (!isConfigObject(pattern) || Object.keys(pattern).length === 0) {
|
|
65
|
+
delete result[key];
|
|
66
|
+
changed = true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return { changed, result };
|
|
70
|
+
}
|
|
71
|
+
export const yamlFormat = {
|
|
72
|
+
parse,
|
|
73
|
+
serialize,
|
|
74
|
+
merge,
|
|
75
|
+
prune
|
|
76
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { FileSystem } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check if an error is a "file not found" (ENOENT) error.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isNotFound(error: unknown): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Read a file if it exists, returning null if not found.
|
|
8
|
+
*/
|
|
9
|
+
export declare function readFileIfExists(fs: FileSystem, target: string): Promise<string | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Check if a path exists (file or directory).
|
|
12
|
+
*/
|
|
13
|
+
export declare function pathExists(fs: FileSystem, target: string): Promise<boolean>;
|
|
14
|
+
/**
|
|
15
|
+
* Create an ISO timestamp safe for use in filenames.
|
|
16
|
+
* Replaces colons and dots with dashes.
|
|
17
|
+
*/
|
|
18
|
+
export declare function createTimestamp(): string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { hasOwnErrorCode } from "./error-codes.js";
|
|
2
|
+
/**
|
|
3
|
+
* Check if an error is a "file not found" (ENOENT) error.
|
|
4
|
+
*/
|
|
5
|
+
export function isNotFound(error) {
|
|
6
|
+
return hasOwnErrorCode(error, "ENOENT");
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Read a file if it exists, returning null if not found.
|
|
10
|
+
*/
|
|
11
|
+
export async function readFileIfExists(fs, target) {
|
|
12
|
+
try {
|
|
13
|
+
return await fs.readFile(target, "utf8");
|
|
14
|
+
}
|
|
15
|
+
catch (error) {
|
|
16
|
+
if (isNotFound(error)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
throw error;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Check if a path exists (file or directory).
|
|
24
|
+
*/
|
|
25
|
+
export async function pathExists(fs, target) {
|
|
26
|
+
try {
|
|
27
|
+
await fs.stat(target);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (isNotFound(error)) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Create an ISO timestamp safe for use in filenames.
|
|
39
|
+
* Replaces colons and dots with dashes.
|
|
40
|
+
*/
|
|
41
|
+
export function createTimestamp() {
|
|
42
|
+
return new Date().toISOString().replaceAll(":", "-").replaceAll(".", "-");
|
|
43
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { configMutation } from "./mutations/config-mutation.js";
|
|
2
|
+
export { fileMutation } from "./mutations/file-mutation.js";
|
|
3
|
+
export { templateMutation } from "./mutations/template-mutation.js";
|
|
4
|
+
export { runMutations } from "./execution/run-mutations.js";
|
|
5
|
+
export { renderTemplate, type TemplateVariables } from "./template/render.js";
|
|
6
|
+
export { isNotFound, readFileIfExists, pathExists, createTimestamp } from "./fs-utils.js";
|
|
7
|
+
export type { ConfigObject, ConfigValue, Mutation, MutationContext, MutationResult, MutationObservers, MutationDetails, MutationOutcome, FileSystem, TemplateLoader, ConfigFormat, PathMapper } from "./types.js";
|
|
8
|
+
export { isConfigObject } from "./types.js";
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Main exports
|
|
2
|
+
export { configMutation } from "./mutations/config-mutation.js";
|
|
3
|
+
export { fileMutation } from "./mutations/file-mutation.js";
|
|
4
|
+
export { templateMutation } from "./mutations/template-mutation.js";
|
|
5
|
+
export { runMutations } from "./execution/run-mutations.js";
|
|
6
|
+
export { renderTemplate } from "./template/render.js";
|
|
7
|
+
export { isNotFound, readFileIfExists, pathExists, createTimestamp } from "./fs-utils.js";
|
|
8
|
+
export { isConfigObject } from "./types.js";
|