@flisk-sh/flisk 0.0.0-stage → 1.3.190
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 +492 -0
- package/LICENSE +21 -0
- package/README.md +479 -2
- package/Tiltfile +151 -0
- package/cli/bin/flisk.js +42 -0
- package/cli/dist/agent-runtimes/custom.js +335 -0
- package/cli/dist/agent-runtimes/registry.js +34 -0
- package/cli/dist/backend-frameworks/elysia.js +38 -0
- package/cli/dist/backend-frameworks/express.js +49 -0
- package/cli/dist/backend-frameworks/fastify.js +43 -0
- package/cli/dist/backend-frameworks/h3.js +37 -0
- package/cli/dist/backend-frameworks/koa.js +47 -0
- package/cli/dist/backend-frameworks/mcp.js +86 -0
- package/cli/dist/backend-frameworks/nestjs.js +55 -0
- package/cli/dist/backend-frameworks/registry.js +134 -0
- package/cli/dist/backend-frameworks/types.js +1 -0
- package/cli/dist/backend-languages/bun.js +76 -0
- package/cli/dist/backend-languages/go.js +125 -0
- package/cli/dist/backend-languages/node.js +122 -0
- package/cli/dist/backend-languages/python.js +94 -0
- package/cli/dist/backend-languages/registry.js +37 -0
- package/cli/dist/backend-languages/rust.js +82 -0
- package/cli/dist/backend-languages/types.js +1 -0
- package/cli/dist/cli.js +29 -0
- package/cli/dist/commands/__tests__/project-e2e-helpers.js +49 -0
- package/cli/dist/commands/__tests__/ui-loading-screen.test.js +16 -0
- package/cli/dist/commands/agent.js +182 -0
- package/cli/dist/commands/completion-candidates.js +116 -0
- package/cli/dist/commands/completion.js +843 -0
- package/cli/dist/commands/config.js +362 -0
- package/cli/dist/commands/doctor.js +1504 -0
- package/cli/dist/commands/down.js +114 -0
- package/cli/dist/commands/eject.js +108 -0
- package/cli/dist/commands/help.js +152 -0
- package/cli/dist/commands/import.js +164 -0
- package/cli/dist/commands/logs.js +119 -0
- package/cli/dist/commands/maintainers.js +102 -0
- package/cli/dist/commands/mcp.js +28 -0
- package/cli/dist/commands/networks.js +306 -0
- package/cli/dist/commands/project.js +447 -0
- package/cli/dist/commands/projects.js +103 -0
- package/cli/dist/commands/registry.js +53 -0
- package/cli/dist/commands/resource.js +992 -0
- package/cli/dist/commands/resources.js +127 -0
- package/cli/dist/commands/restart.js +89 -0
- package/cli/dist/commands/runtime.js +75 -0
- package/cli/dist/commands/stack.js +171 -0
- package/cli/dist/commands/stacks.js +71 -0
- package/cli/dist/commands/status.js +211 -0
- package/cli/dist/commands/ui.js +725 -0
- package/cli/dist/commands/up.js +609 -0
- package/cli/dist/commands/upgrade.js +840 -0
- package/cli/dist/commands/version.js +10 -0
- package/cli/dist/components/Accessible.js +11 -0
- package/cli/dist/components/BaseTooltip.js +30 -0
- package/cli/dist/components/DetailPanel.js +33 -0
- package/cli/dist/components/FileTree.js +51 -0
- package/cli/dist/components/ResourceSelectInput.js +42 -0
- package/cli/dist/components/ResourceTable.js +35 -0
- package/cli/dist/components/ServiceIssues.js +13 -0
- package/cli/dist/components/TUIHeader.js +27 -0
- package/cli/dist/components/TabBar.js +27 -0
- package/cli/dist/components/Tooltip.js +13 -0
- package/cli/dist/components/index.js +11 -0
- package/cli/dist/components/ui-theme.js +120 -0
- package/cli/dist/config/platform-standards.js +182 -0
- package/cli/dist/frontend-frameworks/lit.js +64 -0
- package/cli/dist/frontend-frameworks/preact.js +62 -0
- package/cli/dist/frontend-frameworks/qwik.js +61 -0
- package/cli/dist/frontend-frameworks/react.js +69 -0
- package/cli/dist/frontend-frameworks/registry.js +83 -0
- package/cli/dist/frontend-frameworks/solid.js +62 -0
- package/cli/dist/frontend-frameworks/svelte.js +67 -0
- package/cli/dist/frontend-frameworks/tanstack-router.js +101 -0
- package/cli/dist/frontend-frameworks/types.js +1 -0
- package/cli/dist/frontend-frameworks/vanilla.js +59 -0
- package/cli/dist/frontend-frameworks/vue.js +72 -0
- package/cli/dist/generator/__tests__/golden-helpers.js +43 -0
- package/cli/dist/generator/extension-fetch.js +291 -0
- package/cli/dist/generator/resource-templates.js +133 -0
- package/cli/dist/generator/template-engine.js +801 -0
- package/cli/dist/index.js +10 -0
- package/cli/dist/mcp/server.js +101 -0
- package/cli/dist/mcp/tools.js +351 -0
- package/cli/dist/program.js +37 -0
- package/cli/dist/types/index.js +38 -0
- package/cli/dist/utils/agent-host.js +36 -0
- package/cli/dist/utils/atomic-write.js +36 -0
- package/cli/dist/utils/bun-floor.js +9 -0
- package/cli/dist/utils/bun-requirement.js +10 -0
- package/cli/dist/utils/cache.js +63 -0
- package/cli/dist/utils/cold-preflight.js +257 -0
- package/cli/dist/utils/command-helpers.js +57 -0
- package/cli/dist/utils/constants.js +160 -0
- package/cli/dist/utils/discovery-context.js +71 -0
- package/cli/dist/utils/discovery-paths.js +93 -0
- package/cli/dist/utils/docker.js +34 -0
- package/cli/dist/utils/doctor-crashloop.js +161 -0
- package/cli/dist/utils/doctor-fix.js +391 -0
- package/cli/dist/utils/doctor-host.js +66 -0
- package/cli/dist/utils/doctor-report.js +78 -0
- package/cli/dist/utils/doctor-runtime.js +880 -0
- package/cli/dist/utils/doctor-starlark.js +132 -0
- package/cli/dist/utils/doctor-wiring.js +698 -0
- package/cli/dist/utils/down-cleanup.js +125 -0
- package/cli/dist/utils/env-validator.js +266 -0
- package/cli/dist/utils/errors.js +175 -0
- package/cli/dist/utils/exec-async.js +31 -0
- package/cli/dist/utils/file-helpers.js +104 -0
- package/cli/dist/utils/formatting.js +165 -0
- package/cli/dist/utils/generated-paths.js +51 -0
- package/cli/dist/utils/help-command.js +11 -0
- package/cli/dist/utils/host-port-config.js +140 -0
- package/cli/dist/utils/host-port-plan.js +100 -0
- package/cli/dist/utils/json-output.js +29 -0
- package/cli/dist/utils/machine-output.js +33 -0
- package/cli/dist/utils/paths.js +43 -0
- package/cli/dist/utils/platform.js +58 -0
- package/cli/dist/utils/port-assignment.js +75 -0
- package/cli/dist/utils/port-conflict-fix.js +25 -0
- package/cli/dist/utils/port-fallback-notice.js +17 -0
- package/cli/dist/utils/port-listener-probe.js +20 -0
- package/cli/dist/utils/project-config-defaults.js +17 -0
- package/cli/dist/utils/project-features.js +91 -0
- package/cli/dist/utils/project-templates.js +32 -0
- package/cli/dist/utils/prompt.js +97 -0
- package/cli/dist/utils/resource-features.js +184 -0
- package/cli/dist/utils/resource-kind.js +9 -0
- package/cli/dist/utils/schema-version-gate.js +45 -0
- package/cli/dist/utils/search-status.js +12 -0
- package/cli/dist/utils/secret-redaction.js +73 -0
- package/cli/dist/utils/service-config-checks.js +189 -0
- package/cli/dist/utils/service-manifest.js +254 -0
- package/cli/dist/utils/service-runtime-state.js +66 -0
- package/cli/dist/utils/service-urls.js +112 -0
- package/cli/dist/utils/services.js +360 -0
- package/cli/dist/utils/shared-infra.js +45 -0
- package/cli/dist/utils/shared-platform-postgres.js +232 -0
- package/cli/dist/utils/single-flight.js +21 -0
- package/cli/dist/utils/smoke.js +401 -0
- package/cli/dist/utils/spinner.js +40 -0
- package/cli/dist/utils/stack-features.js +15 -0
- package/cli/dist/utils/stack-status.js +14 -0
- package/cli/dist/utils/startup-report.js +78 -0
- package/cli/dist/utils/status-message.js +21 -0
- package/cli/dist/utils/status-ports.js +33 -0
- package/cli/dist/utils/suggestions.js +63 -0
- package/cli/dist/utils/tar.js +46 -0
- package/cli/dist/utils/tdk-version.js +51 -0
- package/cli/dist/utils/terminal-layout.js +19 -0
- package/cli/dist/utils/tilt-events.js +194 -0
- package/cli/dist/utils/tilt-logs.js +61 -0
- package/cli/dist/utils/tilt-port-owner.js +63 -0
- package/cli/dist/utils/tilt-process.js +54 -0
- package/cli/dist/utils/tilt-resource-state.js +32 -0
- package/cli/dist/utils/tilt-startup.js +49 -0
- package/cli/dist/utils/tilt-unreachable-message.js +9 -0
- package/cli/dist/utils/tilt.js +104 -0
- package/cli/dist/utils/ui-keymap.js +129 -0
- package/cli/dist/utils/ui-service-state.js +34 -0
- package/cli/dist/utils/up-only.js +28 -0
- package/cli/dist/utils/up-readiness.js +118 -0
- package/cli/dist/utils/url-actions.js +103 -0
- package/cli/dist/utils/validation.js +62 -0
- package/cli/dist/utils/which.js +56 -0
- package/cli/dist/utils/windows-doctor.js +176 -0
- package/cli/dist-bundle/chunk-6EA4DGCY.js +2 -0
- package/cli/dist-bundle/chunk-BZ4H7MM4.js +3 -0
- package/cli/dist-bundle/chunk-CLCUIDBH.js +510 -0
- package/cli/dist-bundle/cli.js +2017 -0
- package/cli/dist-bundle/cold-preflight-SY26O2IG.js +2 -0
- package/cli/dist-bundle/devtools-ZUHXW33W.js +5 -0
- package/cli/dist-bundle/extension-fetch-J4FFH7TJ.js +2 -0
- package/cli/package.json +83 -0
- package/cli/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
- package/cli/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
- package/cli/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
- package/cli/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
- package/cli/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
- package/cli/templates/.tiltignore.hbs +72 -0
- package/cli/templates/TILT_RESOURCE_DEFAULTS.star.hbs +220 -0
- package/cli/templates/TILT_TECH_STACK.star.hbs +149 -0
- package/cli/templates/Tiltfile.hbs +381 -0
- package/cli/templates/spec.master.hbs +192 -0
- package/discovery/AGENTS.md +362 -0
- package/discovery/TILT_DISCOVERY.star +429 -0
- package/discovery/Tiltfile +58 -0
- package/discovery/config.star +265 -0
- package/discovery/constants.star +167 -0
- package/discovery/deterministic.star +213 -0
- package/discovery/discovery_daemon.star +193 -0
- package/discovery/discovery_orchestrator.star +492 -0
- package/discovery/filtering.star +7 -0
- package/discovery/identity-management-backend/service.yaml +26 -0
- package/discovery/identity-management-frontend/service.yaml +29 -0
- package/discovery/identity-sdk/service.yaml +9 -0
- package/discovery/incremental_discovery.star +215 -0
- package/discovery/indexing.star +9 -0
- package/discovery/json_manifest_scanner.star +57 -0
- package/discovery/libraries.star +48 -0
- package/discovery/loading.star +25 -0
- package/discovery/manifest/constants.star +106 -0
- package/discovery/manifest/loading.star +418 -0
- package/discovery/manifest/normalize.star +289 -0
- package/discovery/manifest/validation.star +110 -0
- package/discovery/normalization.star +13 -0
- package/discovery/registry.star +562 -0
- package/discovery/resource_snapshot.py +384 -0
- package/discovery/resource_snapshot.star +145 -0
- package/discovery/schemas.star +3 -0
- package/discovery/services/platform/cdc/debezium/nats-connector/service.yaml +9 -0
- package/discovery/services/platform/cdc/nats-http-bridge/service.yaml +9 -0
- package/discovery/services/platform/orchestrator/orchestrator-glue-backend/service.yaml +26 -0
- package/discovery/services/platform/synthetic-monitor/service.yaml +9 -0
- package/discovery/test_resource_snapshot.py +253 -0
- package/discovery/validation.star +80 -0
- package/discovery/versioning.star +3 -0
- package/engine/AGENTS.md +706 -0
- package/engine/README.md +31 -0
- package/engine/REFACTORING_MANIFEST_SYSTEM.md +974 -0
- package/engine/Tiltfile +86 -0
- package/engine/assets/docker/golden-layers.Dockerfile +204 -0
- package/engine/assets/docker/wake-gateway/Dockerfile +28 -0
- package/engine/assets/docker/wake-gateway/decide.test.ts +177 -0
- package/engine/assets/docker/wake-gateway/decide.ts +135 -0
- package/engine/assets/docker/wake-gateway/server.ts +363 -0
- package/engine/assets/scripts/cleanup-completed-migrator-images.sh +39 -0
- package/engine/assets/scripts/cleanup-tilt-images.sh +122 -0
- package/engine/assets/scripts/mac-m1-resource-monitor.sh +123 -0
- package/engine/config.star +5 -0
- package/engine/entrypoint.star +101 -0
- package/engine/lifecycle/orchestrator.star +263 -0
- package/engine/paths.star +719 -0
- package/engine/schemas/project-schema.json +147 -0
- package/engine/schemas/service-schema.json +537 -0
- package/engine/scripts/README.md +89 -0
- package/engine/scripts/build-and-publish-lib.sh +207 -0
- package/engine/scripts/check-lib-publish.sh +87 -0
- package/engine/scripts/debug-container.sh +265 -0
- package/engine/scripts/generate-manifest.sh +200 -0
- package/engine/spec.master +702 -0
- package/engine/spec.master.example +341 -0
- package/engine/topologies/README.md +33 -0
- package/engine/topologies/platform/docker/AGENTS.md +59 -0
- package/engine/topologies/platform/docker/auth/auth.star +207 -0
- package/engine/topologies/platform/docker/build/frontend_build_plan.star +65 -0
- package/engine/topologies/platform/docker/build/golden_image.star +37 -0
- package/engine/topologies/platform/docker/build/golden_image_build.star +144 -0
- package/engine/topologies/platform/docker/build/golden_image_constants.star +100 -0
- package/engine/topologies/platform/docker/build/golden_image_dockerfile.star +263 -0
- package/engine/topologies/platform/docker/compose/compose.star +637 -0
- package/engine/topologies/platform/docker/compose/compose_helpers.star +54 -0
- package/engine/topologies/platform/docker/compose/traefik_standalone.star +171 -0
- package/engine/topologies/platform/docker/config/bunignore.star +144 -0
- package/engine/topologies/platform/docker/config/dockerignore.star +152 -0
- package/engine/topologies/platform/docker/config/healthcheck.star +58 -0
- package/engine/topologies/platform/docker/constants.star +211 -0
- package/engine/topologies/platform/docker/dockerfile/dockerfile.star +56 -0
- package/engine/topologies/platform/docker/dockerfile/language_dockerfile.star +264 -0
- package/engine/topologies/platform/docker/generators/golden_docker_generator_v2.star +76 -0
- package/engine/topologies/platform/docker/index.star +40 -0
- package/engine/topologies/platform/docker/layers/bun_helpers.star +25 -0
- package/engine/topologies/platform/docker/layers/infisical/index.star +42 -0
- package/engine/topologies/platform/docker/layers/infisical/infisical_docker.star +264 -0
- package/engine/topologies/platform/docker/layers/l1_base_layers.star +89 -0
- package/engine/topologies/platform/docker/layers/l2_dependency_layers.star +147 -0
- package/engine/topologies/platform/docker/layers/l3_builder_layers.star +229 -0
- package/engine/topologies/platform/docker/layers/l4_runtime_layers.star +282 -0
- package/engine/topologies/platform/docker/layers/prisma/constants.star +138 -0
- package/engine/topologies/platform/docker/layers/prisma/db_readiness.star +98 -0
- package/engine/topologies/platform/docker/layers/prisma/filesystem_setup.star +131 -0
- package/engine/topologies/platform/docker/layers/prisma/migrate_script.star +100 -0
- package/engine/topologies/platform/docker/layers/prisma/prisma_build.star +128 -0
- package/engine/topologies/platform/docker/layers/prisma/prisma_runtime.star +205 -0
- package/engine/topologies/platform/docker/layers/prisma/secret_resolution.star +121 -0
- package/engine/topologies/platform/docker/networking/api_path_constants.star +206 -0
- package/engine/topologies/platform/docker/networking/sablier_container_cycle.star +31 -0
- package/engine/topologies/platform/docker/networking/traefik.star +266 -0
- package/engine/topologies/platform/docker/networking/traefik_constants.star +148 -0
- package/engine/topologies/platform/docker/networking/traefik_helpers.star +162 -0
- package/engine/topologies/platform/docker/networking/traefik_static_routes.star +165 -0
- package/engine/topologies/platform/docker/secrets/env_secrets.star +74 -0
- package/engine/topologies/platform/docker/secrets/infisical.star +109 -0
- package/engine/topologies/platform/net/AGENTS.md +64 -0
- package/engine/topologies/platform/net/proxy.star +6 -0
- package/engine/topologies/platform/registries/local.star +6 -0
- package/engine/topologies/platform/registries/verdaccio_loader.star +20 -0
- package/engine/topologies/platform/security/AGENTS.md +49 -0
- package/engine/topologies/platform/security/secrets.star +241 -0
- package/engine/topologies/platform/state/AGENTS.md +64 -0
- package/engine/topologies/platform/state/relational.star +6 -0
- package/engine/topologies/tilt/common/AGENTS.md +59 -0
- package/engine/topologies/tilt/common/utils.star +409 -0
- package/engine/topologies/tilt/common/utils_debug.star +71 -0
- package/engine/topologies/tilt/common/utils_deterministic.star +170 -0
- package/engine/topologies/tilt/common/utils_docker_networks.star +54 -0
- package/engine/topologies/tilt/common/utils_env.star +92 -0
- package/engine/topologies/tilt/common/utils_output.star +99 -0
- package/engine/topologies/tilt/config/AGENTS.md +68 -0
- package/engine/topologies/tilt/config/defaults.star +5 -0
- package/engine/topologies/tilt/config/feature_flags.star +12 -0
- package/engine/topologies/tilt/config/global.star +57 -0
- package/engine/topologies/tilt/config/profiles.star +398 -0
- package/engine/topologies/tilt/generators/agents_md.star +64 -0
- package/engine/topologies/tilt/generators/api_gateway.star +147 -0
- package/engine/topologies/tilt/generators/index.star +126 -0
- package/engine/topologies/tilt/generators/infisical/README.md +424 -0
- package/engine/topologies/tilt/generators/infisical/examples.star +314 -0
- package/engine/topologies/tilt/generators/infisical/index.star +59 -0
- package/engine/topologies/tilt/generators/infisical/machine_identity.star +422 -0
- package/engine/topologies/tilt/generators/infisical/organization.star +536 -0
- package/engine/topologies/tilt/generators/infisical/path_manager.star +478 -0
- package/engine/topologies/tilt/generators/infisical/secrets_generator.star +422 -0
- package/engine/topologies/tilt/generators/nginx_conf.star +145 -0
- package/engine/topologies/tilt/generators/npmrc.star +132 -0
- package/engine/topologies/tilt/generators/tsconfig.star +25 -0
- package/engine/topologies/tilt/generators/typescript/backend_library_tsconfig.star +73 -0
- package/engine/topologies/tilt/generators/typescript/backend_tsconfig.star +137 -0
- package/engine/topologies/tilt/generators/typescript/common.star +9 -0
- package/engine/topologies/tilt/generators/typescript/frontend_library_tsconfig.star +78 -0
- package/engine/topologies/tilt/generators/typescript/frontend_tsconfig.star +140 -0
- package/engine/topologies/tilt/generators/typescript/include.star +25 -0
- package/engine/topologies/tilt/generators/typescript/playwright_config.star +42 -0
- package/engine/topologies/tilt/generators/typescript/prisma_config.star +51 -0
- package/engine/topologies/tilt/generators/validators.star +868 -0
- package/engine/topologies/tilt/generators/vite/backend.star +80 -0
- package/engine/topologies/tilt/generators/vite/frameworks/lit.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/preact.star +94 -0
- package/engine/topologies/tilt/generators/vite/frameworks/qwik.star +94 -0
- package/engine/topologies/tilt/generators/vite/frameworks/react.star +128 -0
- package/engine/topologies/tilt/generators/vite/frameworks/solid.star +94 -0
- package/engine/topologies/tilt/generators/vite/frameworks/svelte.star +94 -0
- package/engine/topologies/tilt/generators/vite/frameworks/vanilla.star +92 -0
- package/engine/topologies/tilt/generators/vite/frameworks/vue.star +94 -0
- package/engine/topologies/tilt/generators/vite/frontend.star +153 -0
- package/engine/topologies/tilt/generators/vite/generators.star +45 -0
- package/engine/topologies/tilt/generators/vite/helpers.star +256 -0
- package/engine/topologies/tilt/generators/vite/library.star +67 -0
- package/engine/topologies/tilt/generators/vite/sdk.star +75 -0
- package/engine/topologies/tilt/generators/vite/templates.star +460 -0
- package/engine/topologies/tilt/generators/vite_config.star +24 -0
- package/engine/topologies/tilt/manifest/AGENTS.md +61 -0
- package/engine/topologies/tilt/manifest/README.md +679 -0
- package/engine/topologies/tilt/manifest/__init__.star +220 -0
- package/engine/topologies/tilt/manifest/constants.star +262 -0
- package/engine/topologies/tilt/manifest/errors.star +268 -0
- package/engine/topologies/tilt/manifest/integration.star +348 -0
- package/engine/topologies/tilt/manifest/json_to_yaml.py +61 -0
- package/engine/topologies/tilt/manifest/loader.star +239 -0
- package/engine/topologies/tilt/manifest/mapper.star +229 -0
- package/engine/topologies/tilt/manifest/parser.star +490 -0
- package/engine/topologies/tilt/manifest/schema.star +502 -0
- package/engine/topologies/tilt/manifest/tests/test_integration.star +278 -0
- package/engine/topologies/tilt/manifest/tests/test_loader_parser.star +475 -0
- package/engine/topologies/tilt/manifest/tests/test_manifest.star +319 -0
- package/engine/topologies/tilt/manifest/tests/test_validator.star +472 -0
- package/engine/topologies/tilt/manifest/validator.star +744 -0
- package/engine/topologies/tilt/manifest/yaml_to_json.py +20 -0
- package/engine/topologies/tilt/resources/AGENTS.md +71 -0
- package/engine/topologies/tilt/resources/build_concurrency.star +56 -0
- package/engine/topologies/tilt/resources/conditions.star +5 -0
- package/engine/topologies/tilt/resources/databases.star +246 -0
- package/engine/topologies/tilt/resources/declaration.star +5 -0
- package/engine/topologies/tilt/resources/deps.star +5 -0
- package/engine/topologies/tilt/resources/infra-loader.star +504 -0
- package/engine/topologies/tilt/resources/libs.star +32 -0
- package/engine/topologies/tilt/resources/libs_discovery.star +104 -0
- package/engine/topologies/tilt/resources/libs_paths.star +81 -0
- package/engine/topologies/tilt/resources/libs_resource_definition.star +153 -0
- package/engine/topologies/tilt/resources/libs_setup.star +166 -0
- package/engine/topologies/tilt/resources/libs_tsconfig.star +39 -0
- package/engine/topologies/tilt/resources/orchestrator/apply.star +79 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_compose_resource_registration.star +864 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_manifest_orchestration.star +90 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_migrator_orchestration.star +150 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_resource_validation.star +38 -0
- package/engine/topologies/tilt/resources/orchestrator/apply_runtime_flags.star +46 -0
- package/engine/topologies/tilt/resources/orchestrator/builders/typescript.star +193 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/AGENTS.md +75 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/index.star +23 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/dependencies/resolver.star +136 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/env.star +219 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/frontend.star +172 -0
- package/engine/topologies/tilt/resources/orchestrator/generators/manifest_resource.star +577 -0
- package/engine/topologies/tilt/resources/orchestrator/helpers.star +35 -0
- package/engine/topologies/tilt/resources/orchestrator.star +56 -0
- package/engine/topologies/tilt/resources/ordering.star +5 -0
- package/engine/topologies/tilt/resources/shared-platform-postgres.star +30 -0
- package/engine/topologies/tilt/resources/triggers.star +5 -0
- package/engine/topologies/tilt/resources/watchers.star +304 -0
- package/engine/where-things-live.star +719 -0
- package/examples/tdk-example/LICENSE +21 -0
- package/examples/tdk-example/README.md +23 -0
- package/examples/tdk-example/TILT_SERVICE_DEFAULTS.star +42 -0
- package/examples/tdk-example/TILT_TECH_STACK.star +67 -0
- package/examples/tdk-example/Tiltfile +25 -0
- package/examples/tdk-example/services/platform/messaging/docker-compose.yml +26 -0
- package/examples/tdk-example/services/shop/orders-api/package.json +20 -0
- package/examples/tdk-example/services/shop/orders-api/service.json +14 -0
- package/examples/tdk-example/services/shop/orders-api/src/index.ts +81 -0
- package/examples/tdk-example/services/shop/orders-app/index.html +12 -0
- package/examples/tdk-example/services/shop/orders-app/package.json +23 -0
- package/examples/tdk-example/services/shop/orders-app/public/.gitkeep +0 -0
- package/examples/tdk-example/services/shop/orders-app/service.json +9 -0
- package/examples/tdk-example/services/shop/orders-app/src/main.tsx +9 -0
- package/examples/tdk-example/services/shop/orders-app/src/orders.tsx +67 -0
- package/examples/tdk-example/services/shop/orders-app/src/style.css +15 -0
- package/examples/tdk-example/services/shop/orders-worker/package.json +18 -0
- package/examples/tdk-example/services/shop/orders-worker/service.json +13 -0
- package/examples/tdk-example/services/shop/orders-worker/src/index.ts +33 -0
- package/ext/Tiltfile +66 -0
- package/ext/ide-components/README.md +221 -0
- package/ext/ide-components/code_viewer/server.py +208 -0
- package/ext/ide-components/config_inspector/server.py +1052 -0
- package/ext/ide-components/file_browser/server.py +287 -0
- package/ext/ide-components/shared/config_service.py +471 -0
- package/ext/ide-components/shared/file_utils.py +300 -0
- package/ext/ide-components/shared/http_utils.py +234 -0
- package/ext/ide-components/shared/static/styles.css +1334 -0
- package/ext/ide-components/shared/syntax_highlighter.py +142 -0
- package/ext/ide-components/shared/template_engine.py +125 -0
- package/ext/ide-components/shared/templates/base.html +121 -0
- package/ext/ide-components/shared/test_config_service.py +328 -0
- package/ext/ide-components/shared/tilt_integration.py +160 -0
- package/ext/ui-enhancements/cron-status-server.sh +51 -0
- package/ext/ui-enhancements/cron-status-tracker.sh +148 -0
- package/ext/ui-enhancements/extension.yaml +36 -0
- package/ext/ui-enhancements/tiltfile.py +101 -0
- package/ext/ui-enhancements/ui/cron-jobs-tab.css +396 -0
- package/ext/ui-enhancements/ui/help-panel.css +279 -0
- package/ext/ui-enhancements/ui/icons.css +125 -0
- package/ext/ui-enhancements/ui/tooltips.css +114 -0
- package/package.json +94 -4
- package/shared-platform-engineering/docker-templates/bun-hoisted-symlink-fix.sh +25 -0
- package/shared-platform-engineering/docker-templates/infisical-entrypoint.sh +466 -0
- package/shared-platform-engineering/docker-templates/install-deps.sh +154 -0
- package/shared-platform-engineering/docker-templates/prisma-bun-client-link-fix.sh +14 -0
- package/shared-platform-engineering/docker-templates/prisma-normalize-client.sh +58 -0
- package/specs/specs/TILT_SERVICE_DEFAULTS.star +207 -0
- package/specs/specs/TILT_TECH_STACK.star +161 -0
|
@@ -0,0 +1,843 @@
|
|
|
1
|
+
// Copyright (c) 2026 Flisk Landscape contributors
|
|
2
|
+
// SPDX-License-Identifier: MIT
|
|
3
|
+
/**
|
|
4
|
+
* The shell completion scripts.
|
|
5
|
+
*
|
|
6
|
+
* The scripts are rendered from `commands/completion-candidates.ts`, which reads the registered
|
|
7
|
+
* commands, their flags and the framework, language and resource-type registries. A new command or
|
|
8
|
+
* a new registry entry therefore shows up in all four shells without editing a list here.
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { homedir } from "node:os";
|
|
12
|
+
import { basename, join } from "node:path";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
import { Command } from "commander";
|
|
15
|
+
import { showError } from "../utils/errors.js";
|
|
16
|
+
import { buildCompletionCandidates, } from "./completion-candidates.js";
|
|
17
|
+
const SUPPORTED_SHELLS = ["bash", "zsh", "fish", "powershell"];
|
|
18
|
+
function toEntries(commands, parent = "") {
|
|
19
|
+
return commands.map((command) => {
|
|
20
|
+
const path = parent ? `${parent} ${command.name}` : command.name;
|
|
21
|
+
return {
|
|
22
|
+
path,
|
|
23
|
+
name: command.name,
|
|
24
|
+
aliases: command.aliases,
|
|
25
|
+
description: command.description,
|
|
26
|
+
options: command.options,
|
|
27
|
+
subcommands: toEntries(command.subcommands, path),
|
|
28
|
+
parent,
|
|
29
|
+
...(command.positional ? { positional: command.positional } : {}),
|
|
30
|
+
...(command.argument ? { argument: command.argument } : {}),
|
|
31
|
+
...(command.variadic ? { variadic: true } : {}),
|
|
32
|
+
...(command.optionValues ? { optionValues: command.optionValues } : {}),
|
|
33
|
+
};
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/** Every command and sub-command, flattened. */
|
|
37
|
+
function flatten(entries) {
|
|
38
|
+
return entries.flatMap((entry) => [entry, ...flatten(entry.subcommands)]);
|
|
39
|
+
}
|
|
40
|
+
/** The words that start a command: the name and every alias. */
|
|
41
|
+
function commandWords(entries) {
|
|
42
|
+
return entries.flatMap((entry) => [entry.name, ...entry.aliases]);
|
|
43
|
+
}
|
|
44
|
+
/** A short description, without the characters the shell literals cannot hold. */
|
|
45
|
+
function shortDescription(description) {
|
|
46
|
+
const text = description.replace(/[[\]'":]/g, "").trim();
|
|
47
|
+
return text.length > 60 ? `${text.slice(0, 57)}...` : text;
|
|
48
|
+
}
|
|
49
|
+
function flagList(options) {
|
|
50
|
+
return options.map((option) => option.flag).join(" ");
|
|
51
|
+
}
|
|
52
|
+
/** The values of a flag, for the command that is being completed. */
|
|
53
|
+
function valuesOf(flag, candidates, entry) {
|
|
54
|
+
return entry?.optionValues?.[flag] ?? candidates.values[flag];
|
|
55
|
+
}
|
|
56
|
+
function typeValueArms(values) {
|
|
57
|
+
const arms = Object.entries(values.byType).map(([type, list]) => ({
|
|
58
|
+
types: [type],
|
|
59
|
+
values: [...list],
|
|
60
|
+
}));
|
|
61
|
+
if (values.fallback.length === 0)
|
|
62
|
+
return arms;
|
|
63
|
+
const same = arms.find((arm) => arm.values.join(" ") === values.fallback.join(" "));
|
|
64
|
+
if (same) {
|
|
65
|
+
same.types.push("");
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
arms.push({ types: [""], values: [...values.fallback] });
|
|
69
|
+
}
|
|
70
|
+
return arms;
|
|
71
|
+
}
|
|
72
|
+
/** The condition of one `--type` arm, in the syntax of bash and zsh. */
|
|
73
|
+
function shellTypeCondition(types) {
|
|
74
|
+
const parts = types
|
|
75
|
+
.filter((type) => type !== "")
|
|
76
|
+
.map((type) => `"$${TYPE_VARIABLE}" = "${type}"`);
|
|
77
|
+
if (types.includes(""))
|
|
78
|
+
parts.push(`-z "\${${TYPE_VARIABLE}}"`);
|
|
79
|
+
return parts.join(" || ");
|
|
80
|
+
}
|
|
81
|
+
/** The name of the variable that holds the `--type` of the command line. */
|
|
82
|
+
const TYPE_VARIABLE = "flisk_type";
|
|
83
|
+
/** The stacks of the current project, read from the machine-readable CLI output. */
|
|
84
|
+
const BASH_STACKS = `flisk stacks --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'`;
|
|
85
|
+
const BASH_RESOURCES = `flisk resources --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'`;
|
|
86
|
+
const FISH_STACKS = `flisk stacks --json 2>/dev/null | string match -a -r "\\"name\\":\\"[^\\"]*\\"" | string replace -r "\\"name\\":\\"([^\\"]*)\\"" "\\$1"`;
|
|
87
|
+
const FISH_RESOURCES = `flisk resources --json 2>/dev/null | string match -a -r "\\"name\\":\\"[^\\"]*\\"" | string replace -r "\\"name\\":\\"([^\\"]*)\\"" "\\$1"`;
|
|
88
|
+
/** The `--type` of the current command line, in bash. */
|
|
89
|
+
const BASH_TYPE = ` ${TYPE_VARIABLE}=""
|
|
90
|
+
local i
|
|
91
|
+
for (( i=1; i < COMP_CWORD; i++ )); do
|
|
92
|
+
if [[ "\${COMP_WORDS[i]}" = "--type" ]]; then
|
|
93
|
+
${TYPE_VARIABLE}="\${COMP_WORDS[i+1]}"
|
|
94
|
+
elif [[ "\${COMP_WORDS[i]}" = "--type="* ]]; then
|
|
95
|
+
${TYPE_VARIABLE}="\${COMP_WORDS[i]#--type=}"
|
|
96
|
+
fi
|
|
97
|
+
done`;
|
|
98
|
+
/** The `--type` of the current command line, in zsh. */
|
|
99
|
+
const ZSH_TYPE = ` local ${TYPE_VARIABLE}=""
|
|
100
|
+
local i
|
|
101
|
+
for (( i = 2; i < CURRENT; i++ )); do
|
|
102
|
+
if [[ "\${words[i]}" = "--type" ]]; then
|
|
103
|
+
${TYPE_VARIABLE}="\${words[i+1]}"
|
|
104
|
+
elif [[ "\${words[i]}" = "--type="* ]]; then
|
|
105
|
+
${TYPE_VARIABLE}="\${words[i]#--type=}"
|
|
106
|
+
fi
|
|
107
|
+
done`;
|
|
108
|
+
/** The `--type` of the current command line, in fish. */
|
|
109
|
+
const FISH_TYPE = `function __flisk_resource_type
|
|
110
|
+
set -l tokens (commandline -opc)
|
|
111
|
+
set -l ${TYPE_VARIABLE} ""
|
|
112
|
+
set -l token_count (count $tokens)
|
|
113
|
+
for i in (seq $token_count)
|
|
114
|
+
if test "$tokens[$i]" = "--type"
|
|
115
|
+
if test $i -lt $token_count
|
|
116
|
+
set next_index (math $i + 1)
|
|
117
|
+
set ${TYPE_VARIABLE} "$tokens[$next_index]"
|
|
118
|
+
end
|
|
119
|
+
else if string match -q -- "--type=*" "$tokens[$i]"
|
|
120
|
+
set ${TYPE_VARIABLE} (string replace -- "--type=" "" "$tokens[$i]")
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
echo $${TYPE_VARIABLE}
|
|
124
|
+
end`;
|
|
125
|
+
/** The `--type` of the current command line, in PowerShell. */
|
|
126
|
+
const POWERSHELL_TYPE = ` $${TYPE_VARIABLE} = ''
|
|
127
|
+
for ($i = 0; $i -lt $typed.Count; $i++) {
|
|
128
|
+
if ($typed[$i] -eq '--type' -and ($i + 1) -lt $typed.Count) { $${TYPE_VARIABLE} = $typed[$i + 1] }
|
|
129
|
+
elseif ($typed[$i] -like '--type=*') { $${TYPE_VARIABLE} = $typed[$i].Substring(7) }
|
|
130
|
+
}`;
|
|
131
|
+
/** The values of a flag that depend on the `--type`, in bash. */
|
|
132
|
+
function bashTypeValues(values) {
|
|
133
|
+
const lines = [` local ${TYPE_VARIABLE}_values=""`];
|
|
134
|
+
typeValueArms(values).forEach((arm, index) => {
|
|
135
|
+
lines.push(` ${index === 0 ? "if" : "elif"} [[ ${shellTypeCondition(arm.types)} ]]; then`);
|
|
136
|
+
lines.push(` ${TYPE_VARIABLE}_values="${arm.values.join(" ")}"`);
|
|
137
|
+
});
|
|
138
|
+
lines.push(" fi");
|
|
139
|
+
lines.push(` COMPREPLY=( $(compgen -W "\${${TYPE_VARIABLE}_values}" -- \${cur}) )`);
|
|
140
|
+
return lines.join("\n");
|
|
141
|
+
}
|
|
142
|
+
/** The values of a flag that depend on the `--type`, in zsh. */
|
|
143
|
+
function zshTypeValues(flag, values) {
|
|
144
|
+
const lines = [
|
|
145
|
+
` local -a ${TYPE_VARIABLE}_values`,
|
|
146
|
+
` if [[ ${shellTypeCondition(typeValueArms(values)[0].types)} ]]; then`,
|
|
147
|
+
` ${TYPE_VARIABLE}_values=(${typeValueArms(values)[0].values.join(" ")})`,
|
|
148
|
+
];
|
|
149
|
+
for (const arm of typeValueArms(values).slice(1)) {
|
|
150
|
+
lines.push(` elif [[ ${shellTypeCondition(arm.types)} ]]; then`);
|
|
151
|
+
lines.push(` ${TYPE_VARIABLE}_values=(${arm.values.join(" ")})`);
|
|
152
|
+
}
|
|
153
|
+
lines.push(" fi");
|
|
154
|
+
lines.push(` (( $#${TYPE_VARIABLE}_values )) && _describe -t values '${flag.slice(2)}' ${TYPE_VARIABLE}_values`);
|
|
155
|
+
return lines.join("\n");
|
|
156
|
+
}
|
|
157
|
+
/** The values of a flag that depend on the `--type`, in fish. */
|
|
158
|
+
function fishTypeValues(values) {
|
|
159
|
+
const lines = [" switch (__flisk_resource_type)"];
|
|
160
|
+
for (const arm of typeValueArms(values)) {
|
|
161
|
+
lines.push(` case ${arm.types.map((type) => (type === "" ? "''" : type)).join(" ")}`);
|
|
162
|
+
lines.push(` printf '%s\\n' ${arm.values.join(" ")}`);
|
|
163
|
+
}
|
|
164
|
+
lines.push(" end");
|
|
165
|
+
return lines.join("\n");
|
|
166
|
+
}
|
|
167
|
+
/** The values of a flag that depend on the `--type`, in PowerShell. */
|
|
168
|
+
function powershellTypeValues(flag, values) {
|
|
169
|
+
const arms = typeValueArms(values);
|
|
170
|
+
const lines = [` if ($previous -eq '${flag}') {`, " $values = @()"];
|
|
171
|
+
arms.forEach((arm, index) => {
|
|
172
|
+
const conditions = arm.types
|
|
173
|
+
.filter((type) => type !== "")
|
|
174
|
+
.map((type) => `$${TYPE_VARIABLE} -eq '${type}'`);
|
|
175
|
+
if (arm.types.includes(""))
|
|
176
|
+
conditions.push(`$${TYPE_VARIABLE} -eq ''`);
|
|
177
|
+
lines.push(` ${index === 0 ? "if" : "elseif"} (${conditions.join(" -or ")}) { $values = @(${arm.values.map((value) => `'${value}'`).join(", ")}) }`);
|
|
178
|
+
});
|
|
179
|
+
lines.push(' return $values | Where-Object { $_ -like "$wordToComplete*" }');
|
|
180
|
+
lines.push(" }");
|
|
181
|
+
return lines.join("\n");
|
|
182
|
+
}
|
|
183
|
+
function renderBash(candidates) {
|
|
184
|
+
const entries = toEntries(candidates.commands);
|
|
185
|
+
const words = commandWords(entries);
|
|
186
|
+
const globalFlags = flagList(candidates.globalOptions);
|
|
187
|
+
const aliasCases = entries
|
|
188
|
+
.flatMap((entry) => entry.aliases.map((alias) => ` ${alias}) cmd="${entry.name}" ;;`))
|
|
189
|
+
.join("\n");
|
|
190
|
+
const commandCases = entries
|
|
191
|
+
.filter((entry) => entry.options.length > 0)
|
|
192
|
+
.map((entry) => ` ${entry.name}) options="${flagList(entry.options)}" ;;`)
|
|
193
|
+
.join("\n");
|
|
194
|
+
const subCommandOptionCases = flatten(entries)
|
|
195
|
+
.filter((entry) => entry.parent !== "" && entry.options.length > 0)
|
|
196
|
+
.map((entry) => ` "${entry.path}") options="${flagList(entry.options)}" ;;`)
|
|
197
|
+
.join("\n");
|
|
198
|
+
// The values of the flags of the current command, when the command accepts its own set.
|
|
199
|
+
const commandValueCases = flatten(entries)
|
|
200
|
+
.flatMap((entry) => Object.entries(entry.optionValues ?? {}).map(([flag, values]) => ` "${entry.path} ${flag}")\n COMPREPLY=( $(compgen -W "${values.join(" ")}" -- \${cur}) )\n return 0\n ;;`))
|
|
201
|
+
.join("\n");
|
|
202
|
+
const valueCases = Object.entries(candidates.values)
|
|
203
|
+
.map(([flag, values]) => ` ${flag})\n COMPREPLY=( $(compgen -W "${values.join(" ")}" -- \${cur}) )\n return 0\n ;;`)
|
|
204
|
+
.join("\n");
|
|
205
|
+
// The values of the flags that depend on the `--type` of the command line.
|
|
206
|
+
const typeValueCases = Object.entries(candidates.typeValues)
|
|
207
|
+
.map(([flag, values]) => ` ${flag})\n${bashTypeValues(values)}\n return 0\n ;;`)
|
|
208
|
+
.join("\n");
|
|
209
|
+
const subCommandCases = entries
|
|
210
|
+
.filter((entry) => entry.subcommands.length > 0)
|
|
211
|
+
.map((entry) => ` ${entry.name}) words="${commandWords(entry.subcommands).join(" ")}" ;;`)
|
|
212
|
+
.join("\n");
|
|
213
|
+
const positionalCases = entries
|
|
214
|
+
.filter((entry) => entry.positional)
|
|
215
|
+
.map((entry) => {
|
|
216
|
+
switch (entry.positional) {
|
|
217
|
+
case "stacks":
|
|
218
|
+
return ` ${entry.name}) words="\${stacks}" ;;`;
|
|
219
|
+
case "resources":
|
|
220
|
+
return ` ${entry.name}) words="\${resources}" ;;`;
|
|
221
|
+
case "stacks-and-resources":
|
|
222
|
+
return ` ${entry.name}) words="\${stacks} \${resources}" ;;`;
|
|
223
|
+
case "commands":
|
|
224
|
+
return ` ${entry.name}) words="\${commands}" ;;`;
|
|
225
|
+
default:
|
|
226
|
+
return "";
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
.join("\n");
|
|
230
|
+
// The positional argument of a sub-command, for example the resource of `flisk agent sessions`.
|
|
231
|
+
const subCommandPositionalCases = flatten(entries)
|
|
232
|
+
.filter((entry) => entry.parent !== "" && entry.positional)
|
|
233
|
+
.map((entry) => {
|
|
234
|
+
switch (entry.positional) {
|
|
235
|
+
case "stacks":
|
|
236
|
+
return ` "${entry.path}") words="\${stacks}" ;;`;
|
|
237
|
+
case "resources":
|
|
238
|
+
return ` "${entry.path}") words="\${resources}" ;;`;
|
|
239
|
+
case "stacks-and-resources":
|
|
240
|
+
return ` "${entry.path}") words="\${stacks} \${resources}" ;;`;
|
|
241
|
+
case "commands":
|
|
242
|
+
return ` "${entry.path}") words="\${commands}" ;;`;
|
|
243
|
+
default:
|
|
244
|
+
return "";
|
|
245
|
+
}
|
|
246
|
+
})
|
|
247
|
+
.join("\n");
|
|
248
|
+
// The path of the command the cursor is in, for example "config verify".
|
|
249
|
+
const subCommandPathCases = flatten(entries)
|
|
250
|
+
.filter((entry) => entry.parent !== "")
|
|
251
|
+
.map((entry) => ` "${entry.path}") path="${entry.path}" ;;`)
|
|
252
|
+
.join("\n");
|
|
253
|
+
return `# Flisk CLI Bash Completion
|
|
254
|
+
# Generated by "flisk completion bash". The command and flag lists come from the CLI itself.
|
|
255
|
+
_flisk_completions() {
|
|
256
|
+
local cur prev cmd sub options words commands stacks resources path ${TYPE_VARIABLE} ${TYPE_VARIABLE}_values
|
|
257
|
+
COMPREPLY=()
|
|
258
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
259
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
260
|
+
cmd="\${COMP_WORDS[1]}"
|
|
261
|
+
sub="\${COMP_WORDS[2]}"
|
|
262
|
+
|
|
263
|
+
# The path of the command the cursor is in, for example "config verify".
|
|
264
|
+
path="\${cmd}"
|
|
265
|
+
case "\${cmd} \${sub}" in
|
|
266
|
+
${subCommandPathCases}
|
|
267
|
+
esac
|
|
268
|
+
|
|
269
|
+
commands="${words.join(" ")}"
|
|
270
|
+
|
|
271
|
+
# The stacks and the resources of the current project.
|
|
272
|
+
stacks="$(${BASH_STACKS})"
|
|
273
|
+
resources="$(${BASH_RESOURCES})"
|
|
274
|
+
|
|
275
|
+
${BASH_TYPE}
|
|
276
|
+
|
|
277
|
+
# The values of the flags of the current command, when the command accepts its own set.
|
|
278
|
+
case "\${path} \${prev}" in
|
|
279
|
+
${commandValueCases}
|
|
280
|
+
esac
|
|
281
|
+
|
|
282
|
+
# The values of the flags that take a fixed list.
|
|
283
|
+
case "\${prev}" in
|
|
284
|
+
${valueCases}
|
|
285
|
+
${typeValueCases}
|
|
286
|
+
--stack)
|
|
287
|
+
COMPREPLY=( $(compgen -W "\${stacks}" -- \${cur}) )
|
|
288
|
+
return 0
|
|
289
|
+
;;
|
|
290
|
+
--only)
|
|
291
|
+
COMPREPLY=( $(compgen -W "\${resources}" -- \${cur}) )
|
|
292
|
+
return 0
|
|
293
|
+
;;
|
|
294
|
+
esac
|
|
295
|
+
|
|
296
|
+
# The aliases are the same commands under a different name.
|
|
297
|
+
case "\${cmd}" in
|
|
298
|
+
${aliasCases}
|
|
299
|
+
esac
|
|
300
|
+
|
|
301
|
+
# The flags of the current command.
|
|
302
|
+
if [[ \${cur} == -* ]]; then
|
|
303
|
+
options="${globalFlags}"
|
|
304
|
+
case "\${cmd}" in
|
|
305
|
+
${commandCases}
|
|
306
|
+
esac
|
|
307
|
+
if [[ -n "\${sub}" ]]; then
|
|
308
|
+
case "\${cmd} \${sub}" in
|
|
309
|
+
${subCommandOptionCases}
|
|
310
|
+
esac
|
|
311
|
+
fi
|
|
312
|
+
COMPREPLY=( $(compgen -W "\${options}" -- \${cur}) )
|
|
313
|
+
return 0
|
|
314
|
+
fi
|
|
315
|
+
|
|
316
|
+
# Inside a sub-command the flags and the positional argument of the sub-command are left.
|
|
317
|
+
if [[ -n "\${sub}" ]]; then
|
|
318
|
+
words=""
|
|
319
|
+
case "\${cmd} \${sub}" in
|
|
320
|
+
${subCommandPositionalCases}
|
|
321
|
+
esac
|
|
322
|
+
if [[ -n "\${words}" ]]; then
|
|
323
|
+
COMPREPLY=( $(compgen -W "\${words}" -- \${cur}) )
|
|
324
|
+
fi
|
|
325
|
+
return 0
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
words="\${commands}"
|
|
329
|
+
case "\${cmd}" in
|
|
330
|
+
${subCommandCases}
|
|
331
|
+
${positionalCases}
|
|
332
|
+
esac
|
|
333
|
+
|
|
334
|
+
COMPREPLY=( $(compgen -W "\${words}" -- \${cur}) )
|
|
335
|
+
return 0
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
complete -F _flisk_completions flisk
|
|
339
|
+
`;
|
|
340
|
+
}
|
|
341
|
+
/** The `_arguments` spec of the positional argument of a command. */
|
|
342
|
+
function zshPositionalSpecs(entry) {
|
|
343
|
+
// A command with sub-commands completes the name of the sub-command, not a value.
|
|
344
|
+
if (entry.subcommands.length > 0) {
|
|
345
|
+
return [`'1: :_flisk_${entry.name}_subcommands'`];
|
|
346
|
+
}
|
|
347
|
+
switch (entry.positional) {
|
|
348
|
+
case "stacks":
|
|
349
|
+
return ["'1:stack:_flisk_stacks'"];
|
|
350
|
+
case "resources":
|
|
351
|
+
return ["'1:resource:_flisk_resources'"];
|
|
352
|
+
case "stacks-and-resources":
|
|
353
|
+
return ["'1:target:_flisk_stacks'"];
|
|
354
|
+
case "commands":
|
|
355
|
+
return ["'1:command:_flisk_commands'"];
|
|
356
|
+
default:
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
// A command with a positional argument still needs the spec, otherwise the value of a flag that
|
|
360
|
+
// follows the argument is not completed.
|
|
361
|
+
if (entry.argument) {
|
|
362
|
+
return [entry.variadic ? `'*:${entry.argument}:'` : `'1:${entry.argument}:'`];
|
|
363
|
+
}
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
function renderZsh(candidates) {
|
|
367
|
+
const entries = toEntries(candidates.commands);
|
|
368
|
+
const globalFlags = candidates.globalOptions
|
|
369
|
+
.map((option) => `'${option.flag}[${shortDescription(option.description)}]'`)
|
|
370
|
+
.join(" \\\n ");
|
|
371
|
+
const commandBranches = entries
|
|
372
|
+
.map((entry) => {
|
|
373
|
+
const specs = [
|
|
374
|
+
...entry.options.map((option) => zshOptionSpec(option, candidates, entry)),
|
|
375
|
+
...zshPositionalSpecs(entry),
|
|
376
|
+
];
|
|
377
|
+
if (entry.subcommands.length > 0) {
|
|
378
|
+
specs.push(`'*:: :->${entry.name}_args'`);
|
|
379
|
+
}
|
|
380
|
+
if (specs.length === 0)
|
|
381
|
+
return "";
|
|
382
|
+
// The aliases are the same command under a different name.
|
|
383
|
+
const words = [entry.name, ...entry.aliases].join("|");
|
|
384
|
+
return ` ${words})\n _arguments \\\n ${specs.join(" \\\n ")}\n ;;`;
|
|
385
|
+
})
|
|
386
|
+
.filter((branch) => branch !== "")
|
|
387
|
+
.join("\n");
|
|
388
|
+
const subCommandStates = entries
|
|
389
|
+
.filter((entry) => entry.subcommands.length > 0)
|
|
390
|
+
.map((entry) => {
|
|
391
|
+
const branches = entry.subcommands
|
|
392
|
+
.map((subcommand) => {
|
|
393
|
+
const specs = [
|
|
394
|
+
...subcommand.options.map((option) => zshOptionSpec(option, candidates, subcommand)),
|
|
395
|
+
...zshPositionalSpecs(subcommand),
|
|
396
|
+
];
|
|
397
|
+
if (specs.length === 0)
|
|
398
|
+
return "";
|
|
399
|
+
return ` ${subcommand.name})\n _arguments \\\n ${specs.join(" \\\n ")}\n ;;`;
|
|
400
|
+
})
|
|
401
|
+
.filter((branch) => branch !== "")
|
|
402
|
+
.join("\n");
|
|
403
|
+
return ` ${entry.name}_args)\n case "$line[1]" in\n${branches}\n esac\n ;;`;
|
|
404
|
+
})
|
|
405
|
+
.join("\n");
|
|
406
|
+
const commandList = entries
|
|
407
|
+
.flatMap((entry) => [
|
|
408
|
+
` '${entry.name}:${shortDescription(entry.description)}'`,
|
|
409
|
+
...entry.aliases.map((alias) => ` '${alias}:${shortDescription(entry.description)}'`),
|
|
410
|
+
])
|
|
411
|
+
.join("\n");
|
|
412
|
+
const subCommandLists = entries
|
|
413
|
+
.filter((entry) => entry.subcommands.length > 0)
|
|
414
|
+
.map((entry) => `_flisk_${entry.name}_subcommands() {\n local commands=(\n${entry.subcommands
|
|
415
|
+
.map((subcommand) => ` '${subcommand.name}:${shortDescription(subcommand.description)}'`)
|
|
416
|
+
.join("\n")}\n )\n _describe -t commands '${entry.name} command' commands\n}`)
|
|
417
|
+
.join("\n\n");
|
|
418
|
+
const typeValueFunctions = Object.entries(candidates.typeValues)
|
|
419
|
+
.map(([flag, values]) => `_flisk_${flag.slice(2)}_values() {\n${ZSH_TYPE}\n${zshTypeValues(flag, values)}\n}`)
|
|
420
|
+
.join("\n\n");
|
|
421
|
+
return `#compdef flisk
|
|
422
|
+
|
|
423
|
+
# Flisk CLI Zsh Completion
|
|
424
|
+
# Generated by "flisk completion zsh". The command and flag lists come from the CLI itself.
|
|
425
|
+
|
|
426
|
+
_flisk() {
|
|
427
|
+
local curcontext="$curcontext" state line
|
|
428
|
+
typeset -A opt_args
|
|
429
|
+
|
|
430
|
+
_arguments -C \\
|
|
431
|
+
${globalFlags} \\
|
|
432
|
+
'1: :_flisk_commands' \\
|
|
433
|
+
'*:: :->args'
|
|
434
|
+
|
|
435
|
+
case "$line[1]" in
|
|
436
|
+
${commandBranches}
|
|
437
|
+
esac
|
|
438
|
+
|
|
439
|
+
case "$state" in
|
|
440
|
+
${subCommandStates}
|
|
441
|
+
esac
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
_flisk_commands() {
|
|
445
|
+
local commands=(
|
|
446
|
+
${commandList}
|
|
447
|
+
)
|
|
448
|
+
_describe -t commands 'flisk command' commands
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
_flisk_stacks() {
|
|
452
|
+
local stacks
|
|
453
|
+
stacks=($(flisk stacks --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'))
|
|
454
|
+
_describe -t stacks 'stack' stacks
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
_flisk_resources() {
|
|
458
|
+
local resources
|
|
459
|
+
resources=($(flisk resources --json 2>/dev/null | grep -o '"name":"[^"]*"' | sed 's/"name":"//;s/"$//'))
|
|
460
|
+
_describe -t resources 'resource' resources
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
${subCommandLists}
|
|
464
|
+
|
|
465
|
+
${typeValueFunctions}
|
|
466
|
+
compdef _flisk flisk
|
|
467
|
+
`;
|
|
468
|
+
}
|
|
469
|
+
/** The `_arguments` spec of one flag, with the values it completes when it has them. */
|
|
470
|
+
function zshOptionSpec(option, candidates, entry) {
|
|
471
|
+
const description = shortDescription(option.description);
|
|
472
|
+
if (candidates.typeValues[option.flag]) {
|
|
473
|
+
return `'${option.flag}[${description}]:${option.flag.slice(2)}:_flisk_${option.flag.slice(2)}_values'`;
|
|
474
|
+
}
|
|
475
|
+
const values = valuesOf(option.flag, candidates, entry);
|
|
476
|
+
if (values) {
|
|
477
|
+
return `'${option.flag}[${description}]:${option.flag.slice(2)}:(${values.join(" ")})'`;
|
|
478
|
+
}
|
|
479
|
+
if (option.flag === "--stack") {
|
|
480
|
+
return `'${option.flag}[${description}]:stack:_flisk_stacks'`;
|
|
481
|
+
}
|
|
482
|
+
if (option.flag === "--only") {
|
|
483
|
+
return `'${option.flag}[${description}]:service:_flisk_resources'`;
|
|
484
|
+
}
|
|
485
|
+
return option.takesValue
|
|
486
|
+
? `'${option.flag}[${description}]:${option.flag.slice(2)}:'`
|
|
487
|
+
: `'${option.flag}[${description}]'`;
|
|
488
|
+
}
|
|
489
|
+
function renderFish(candidates) {
|
|
490
|
+
const entries = toEntries(candidates.commands);
|
|
491
|
+
const commandLines = entries.map((entry) => `complete -c flisk -f -n '__fish_use_subcommand' -a '${entry.name}' -d '${shortDescription(entry.description)}'`);
|
|
492
|
+
const aliasLines = entries.flatMap((entry) => entry.aliases.map((alias) => `complete -c flisk -f -n '__fish_use_subcommand' -a '${alias}' -d '${shortDescription(entry.description)}'`));
|
|
493
|
+
const subCommandLines = entries.flatMap((entry) => entry.subcommands.map((subcommand) => `complete -c flisk -f -n '__fish_seen_subcommand_from ${entry.name}' -a '${subcommand.name}' -d '${shortDescription(subcommand.description)}'`));
|
|
494
|
+
const optionLines = flatten(entries)
|
|
495
|
+
.map((entry) => {
|
|
496
|
+
const condition = fishCondition(entry);
|
|
497
|
+
return entry.options
|
|
498
|
+
.filter((option) => option.flag !== "--stack" && option.flag !== "--only")
|
|
499
|
+
.map((option) => {
|
|
500
|
+
// `-r` tells fish that the flag takes a value, so it offers the values after it.
|
|
501
|
+
const args = fishValueArgument(option, candidates, entry);
|
|
502
|
+
return `complete -c flisk -f -n '${condition}' -l ${option.flag.slice(2)} -d '${shortDescription(option.description)}'${args}`;
|
|
503
|
+
})
|
|
504
|
+
.join("\n");
|
|
505
|
+
})
|
|
506
|
+
.filter((line) => line !== "");
|
|
507
|
+
// The flags whose values come from the current project.
|
|
508
|
+
const projectFlagLines = flatten(entries).flatMap((entry) => {
|
|
509
|
+
const condition = fishCondition(entry);
|
|
510
|
+
return entry.options
|
|
511
|
+
.filter((option) => option.flag === "--stack" || option.flag === "--only")
|
|
512
|
+
.map((option) => {
|
|
513
|
+
const values = option.flag === "--stack" ? `(${FISH_STACKS})` : `(${FISH_RESOURCES})`;
|
|
514
|
+
return `complete -c flisk -f -n '${condition}' -l ${option.flag.slice(2)} -r -d '${shortDescription(option.description)}' -a '${values}'`;
|
|
515
|
+
});
|
|
516
|
+
});
|
|
517
|
+
const globalLines = candidates.globalOptions.map((option) => `complete -c flisk -f -l ${option.flag.slice(2)} -d '${shortDescription(option.description)}'`);
|
|
518
|
+
const stackLines = flatten(entries)
|
|
519
|
+
.filter((entry) => entry.positional === "stacks" || entry.positional === "stacks-and-resources")
|
|
520
|
+
.map((entry) => `complete -c flisk -f -n '${fishCondition(entry)}' -a '(${FISH_STACKS})'`);
|
|
521
|
+
const resourceLines = flatten(entries)
|
|
522
|
+
.filter((entry) => entry.positional === "resources" || entry.positional === "stacks-and-resources")
|
|
523
|
+
.map((entry) => `complete -c flisk -f -n '${fishCondition(entry)}' -a '(${FISH_RESOURCES})'`);
|
|
524
|
+
// The names of the other commands, for `flisk help <command>`.
|
|
525
|
+
const commandNameLines = flatten(entries)
|
|
526
|
+
.filter((entry) => entry.positional === "commands")
|
|
527
|
+
.map((entry) => `complete -c flisk -f -n '${fishCondition(entry)}' -a '${commandWords(entries).join(" ")}'`);
|
|
528
|
+
const typeValueFunctions = Object.entries(candidates.typeValues)
|
|
529
|
+
.map(([flag, values]) => `function __flisk_${flag.slice(2)}_values\n${fishTypeValues(values)}\nend`)
|
|
530
|
+
.join("\n\n");
|
|
531
|
+
return `# Flisk CLI Fish Completion
|
|
532
|
+
# Generated by "flisk completion fish". The command and flag lists come from the CLI itself.
|
|
533
|
+
|
|
534
|
+
# Disable file completions for most commands
|
|
535
|
+
complete -c flisk -f
|
|
536
|
+
|
|
537
|
+
# Commands
|
|
538
|
+
${commandLines.join("\n")}
|
|
539
|
+
|
|
540
|
+
# Command aliases
|
|
541
|
+
${aliasLines.join("\n")}
|
|
542
|
+
|
|
543
|
+
# Sub-commands
|
|
544
|
+
${subCommandLines.join("\n")}
|
|
545
|
+
|
|
546
|
+
# Global options
|
|
547
|
+
${globalLines.join("\n")}
|
|
548
|
+
|
|
549
|
+
# Command options
|
|
550
|
+
${optionLines.join("\n")}
|
|
551
|
+
|
|
552
|
+
# Flags whose values come from the current project
|
|
553
|
+
${projectFlagLines.join("\n")}
|
|
554
|
+
|
|
555
|
+
# Project values
|
|
556
|
+
${[...stackLines, ...resourceLines, ...commandNameLines].join("\n")}
|
|
557
|
+
|
|
558
|
+
# The type of the current command line, for the flags whose values depend on it
|
|
559
|
+
${FISH_TYPE}
|
|
560
|
+
|
|
561
|
+
# The values of the flags that depend on the type
|
|
562
|
+
${typeValueFunctions}
|
|
563
|
+
`;
|
|
564
|
+
}
|
|
565
|
+
/** The fish condition that holds while the user is in a command. */
|
|
566
|
+
function fishCondition(entry) {
|
|
567
|
+
return entry.parent === ""
|
|
568
|
+
? `__fish_seen_subcommand_from ${entry.name}`
|
|
569
|
+
: `__fish_seen_subcommand_from ${entry.parent}; and __fish_seen_subcommand_from ${entry.name}`;
|
|
570
|
+
}
|
|
571
|
+
/** The fish argument that lists the values of a flag. */
|
|
572
|
+
function fishValueArgument(option, candidates, entry) {
|
|
573
|
+
if (candidates.typeValues[option.flag]) {
|
|
574
|
+
return ` -r -a '(__flisk_${option.flag.slice(2)}_values)'`;
|
|
575
|
+
}
|
|
576
|
+
const values = valuesOf(option.flag, candidates, entry);
|
|
577
|
+
return values ? ` -r -a '${values.join(" ")}'` : "";
|
|
578
|
+
}
|
|
579
|
+
function renderPowerShell(candidates) {
|
|
580
|
+
const entries = toEntries(candidates.commands);
|
|
581
|
+
const commandLines = entries.map((entry) => ` '${entry.name}' = '${shortDescription(entry.description)}'`);
|
|
582
|
+
const aliasDescriptionLines = entries.flatMap((entry) => entry.aliases.map((alias) => ` '${alias}' = '${shortDescription(entry.description)}'`));
|
|
583
|
+
const subCommandLines = entries.flatMap((entry) => entry.subcommands.map((subcommand) => ` '${entry.name} ${subcommand.name}' = '${shortDescription(subcommand.description)}'`));
|
|
584
|
+
const optionLines = flatten(entries).map((entry) => {
|
|
585
|
+
const flags = entry.options.map((option) => `'${option.flag}'`).join(", ");
|
|
586
|
+
return ` '${entry.path}' = @(${flags})`;
|
|
587
|
+
});
|
|
588
|
+
const valueLines = Object.entries(candidates.values).map(([flag, values]) => ` '${flag}' = @(${values.map((value) => `'${value}'`).join(", ")})`);
|
|
589
|
+
// The values of the flags of a command, when the command accepts its own set.
|
|
590
|
+
const commandValueLines = flatten(entries).flatMap((entry) => Object.entries(entry.optionValues ?? {}).map(([flag, values]) => ` '${entry.path} ${flag}' = @(${values.map((value) => `'${value}'`).join(", ")})`));
|
|
591
|
+
const globalLines = candidates.globalOptions.map((option) => `'${option.flag}'`).join(", ");
|
|
592
|
+
const positionalLines = flatten(entries)
|
|
593
|
+
.filter((entry) => entry.positional)
|
|
594
|
+
.map((entry) => ` '${entry.path}' = '${entry.positional}'`);
|
|
595
|
+
const aliasLines = entries.flatMap((entry) => entry.aliases.map((alias) => ` '${alias}' = '${entry.name}'`));
|
|
596
|
+
const typeValueBlocks = Object.entries(candidates.typeValues)
|
|
597
|
+
.map(([flag, values]) => powershellTypeValues(flag, values))
|
|
598
|
+
.join("\n");
|
|
599
|
+
return `Register-ArgumentCompleter -Native -CommandName flisk -ScriptBlock {
|
|
600
|
+
param($wordToComplete, $commandAst, $cursorPosition)
|
|
601
|
+
|
|
602
|
+
# Generated by "flisk completion powershell". The command and flag lists come from the CLI itself.
|
|
603
|
+
$commands = [ordered]@{
|
|
604
|
+
${commandLines.join("\n")}
|
|
605
|
+
${aliasDescriptionLines.join("\n")}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
$aliases = [ordered]@{
|
|
609
|
+
${aliasLines.join("\n")}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
$subcommands = [ordered]@{
|
|
613
|
+
${subCommandLines.join("\n")}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
$commandOptions = [ordered]@{
|
|
617
|
+
${optionLines.join("\n")}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
$optionValues = [ordered]@{
|
|
621
|
+
${valueLines.join("\n")}
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
$commandOptionValues = [ordered]@{
|
|
625
|
+
${commandValueLines.join("\n")}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
$positional = [ordered]@{
|
|
629
|
+
${positionalLines.join("\n")}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
$globalOptions = @(${globalLines})
|
|
633
|
+
|
|
634
|
+
$tokens = @()
|
|
635
|
+
foreach ($element in $commandAst.CommandElements) { $tokens += $element.Extent.Text }
|
|
636
|
+
|
|
637
|
+
# The words the user already typed, without the command name.
|
|
638
|
+
$typed = @()
|
|
639
|
+
if ($tokens.Count -gt 1) { $typed = $tokens[1..($tokens.Count - 1)] }
|
|
640
|
+
|
|
641
|
+
$previous = ''
|
|
642
|
+
if ($typed.Count -ge 2 -and $wordToComplete -ne '') { $previous = $typed[$typed.Count - 2] }
|
|
643
|
+
elseif ($typed.Count -ge 1) { $previous = $typed[$typed.Count - 1] }
|
|
644
|
+
|
|
645
|
+
# The command path the cursor is in, for example "config verify".
|
|
646
|
+
$path = @()
|
|
647
|
+
foreach ($token in $typed) {
|
|
648
|
+
if ($token -like '-*') { continue }
|
|
649
|
+
$name = $token
|
|
650
|
+
if ($aliases.Contains($name)) { $name = $aliases[$name] }
|
|
651
|
+
if ($path.Count -eq 0 -and $commands.Contains($name)) { $path += $name; continue }
|
|
652
|
+
if ($path.Count -eq 1 -and $subcommands.Contains(($path[0] + ' ' + $name))) { $path += $name }
|
|
653
|
+
}
|
|
654
|
+
$commandPath = $path -join ' '
|
|
655
|
+
|
|
656
|
+
${POWERSHELL_TYPE}
|
|
657
|
+
|
|
658
|
+
# The value of the flag before the cursor.
|
|
659
|
+
$valueKey = $commandPath + ' ' + $previous
|
|
660
|
+
if ($commandOptionValues.Contains($valueKey)) {
|
|
661
|
+
return $commandOptionValues[$valueKey] | Where-Object { $_ -like "$wordToComplete*" }
|
|
662
|
+
}
|
|
663
|
+
if ($optionValues.Contains($previous)) {
|
|
664
|
+
return $optionValues[$previous] | Where-Object { $_ -like "$wordToComplete*" }
|
|
665
|
+
}
|
|
666
|
+
|
|
667
|
+
${typeValueBlocks}
|
|
668
|
+
|
|
669
|
+
# The stacks and the resources of the current project.
|
|
670
|
+
$stacks = @()
|
|
671
|
+
$resources = @()
|
|
672
|
+
if ($previous -eq '--stack' -or $previous -eq '--only' -or $positional.Contains($commandPath)) {
|
|
673
|
+
try { $stacks = (flisk stacks --json | ConvertFrom-Json).data.stacks.name } catch { }
|
|
674
|
+
try { $resources = (flisk resources --json | ConvertFrom-Json).data.resources.name } catch { }
|
|
675
|
+
}
|
|
676
|
+
|
|
677
|
+
# The stacks and the resources behind the flags of the current project.
|
|
678
|
+
if ($previous -eq '--stack') {
|
|
679
|
+
return $stacks | Where-Object { $_ -like "$wordToComplete*" }
|
|
680
|
+
}
|
|
681
|
+
if ($previous -eq '--only') {
|
|
682
|
+
return $resources | Where-Object { $_ -like "$wordToComplete*" }
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
# The flags of the current command.
|
|
686
|
+
if ($wordToComplete -like '-*') {
|
|
687
|
+
$flags = $globalOptions
|
|
688
|
+
if ($commandPath -ne '' -and $commandOptions.Contains($commandPath)) {
|
|
689
|
+
$flags = $flags + $commandOptions[$commandPath]
|
|
690
|
+
}
|
|
691
|
+
return $flags | Where-Object { $_ -like "$wordToComplete*" } | Sort-Object -Unique
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
# The sub-command names of the current command.
|
|
695
|
+
if ($commandPath -ne '') {
|
|
696
|
+
$names = @()
|
|
697
|
+
foreach ($key in $subcommands.Keys) {
|
|
698
|
+
if ($key.StartsWith($commandPath + ' ')) { $names += $key.Split(' ')[-1] }
|
|
699
|
+
}
|
|
700
|
+
if ($names.Count -gt 0) { return $names | Where-Object { $_ -like "$wordToComplete*" } }
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
# The project values of the positional argument.
|
|
704
|
+
if ($positional.Contains($commandPath)) {
|
|
705
|
+
switch ($positional[$commandPath]) {
|
|
706
|
+
'stacks' { return $stacks | Where-Object { $_ -like "$wordToComplete*" } }
|
|
707
|
+
'resources' { return $resources | Where-Object { $_ -like "$wordToComplete*" } }
|
|
708
|
+
'stacks-and-resources' { return ($stacks + $resources) | Where-Object { $_ -like "$wordToComplete*" } }
|
|
709
|
+
'commands' { return $commands.Keys | Where-Object { $_ -like "$wordToComplete*" } }
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
# The command names.
|
|
714
|
+
return $commands.Keys | Where-Object { $_ -like "$wordToComplete*" }
|
|
715
|
+
}`;
|
|
716
|
+
}
|
|
717
|
+
/** Renders the completion script of one shell. */
|
|
718
|
+
export function renderCompletionScript(shell, candidates) {
|
|
719
|
+
switch (shell) {
|
|
720
|
+
case "bash":
|
|
721
|
+
return renderBash(candidates);
|
|
722
|
+
case "zsh":
|
|
723
|
+
return renderZsh(candidates);
|
|
724
|
+
case "fish":
|
|
725
|
+
return renderFish(candidates);
|
|
726
|
+
case "powershell":
|
|
727
|
+
return renderPowerShell(candidates);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
const POWERSHELL_START = "# FLISK-CLI-COMPLETION-START";
|
|
731
|
+
const POWERSHELL_END = "# FLISK-CLI-COMPLETION-END";
|
|
732
|
+
export const completionCommand = new Command("completion")
|
|
733
|
+
.argument("[shell]", "Target shell (bash, zsh, fish, powershell)")
|
|
734
|
+
.description("Generate shell completion scripts")
|
|
735
|
+
.option("-s, --shell <shell>", "Target shell (bash, zsh, fish, powershell)")
|
|
736
|
+
.option("-o, --output <path>", "Output file path (default: stdout)")
|
|
737
|
+
.option("--install", "Install to shell config automatically")
|
|
738
|
+
.action((shellArgument, options, command) => {
|
|
739
|
+
const requestedShell = options.shell ?? shellArgument;
|
|
740
|
+
const environmentShell = basename(process.env.SHELL ?? "")
|
|
741
|
+
.replace(/\.exe$/i, "")
|
|
742
|
+
.toLowerCase();
|
|
743
|
+
const defaultShell = SUPPORTED_SHELLS.includes(environmentShell)
|
|
744
|
+
? environmentShell
|
|
745
|
+
: "bash";
|
|
746
|
+
const shell = (requestedShell ?? defaultShell).toLowerCase();
|
|
747
|
+
if (requestedShell === undefined) {
|
|
748
|
+
console.error(chalk.gray(`Using ${shell} completion`));
|
|
749
|
+
}
|
|
750
|
+
if (!SUPPORTED_SHELLS.includes(shell)) {
|
|
751
|
+
showError(`Unsupported shell: ${shell}`, "Supported shells: bash, zsh, fish, powershell");
|
|
752
|
+
process.exit(1);
|
|
753
|
+
}
|
|
754
|
+
// The candidates come from the program this command is registered on, so the completions and
|
|
755
|
+
// the CLI always offer the same commands and flags.
|
|
756
|
+
const program = command.parent;
|
|
757
|
+
if (!program) {
|
|
758
|
+
console.error(chalk.red("❌ The completion command must be registered on the flisk program."));
|
|
759
|
+
process.exit(1);
|
|
760
|
+
}
|
|
761
|
+
const candidates = buildCompletionCandidates(program);
|
|
762
|
+
const completionScript = renderCompletionScript(shell, candidates);
|
|
763
|
+
const filename = shell === "bash"
|
|
764
|
+
? "flisk-completion.bash"
|
|
765
|
+
: shell === "zsh"
|
|
766
|
+
? "_flisk"
|
|
767
|
+
: shell === "fish"
|
|
768
|
+
? "flisk.fish"
|
|
769
|
+
: "Microsoft.PowerShell_profile.ps1";
|
|
770
|
+
if (options.install) {
|
|
771
|
+
const home = homedir();
|
|
772
|
+
let installPath;
|
|
773
|
+
let installInstructions;
|
|
774
|
+
switch (shell) {
|
|
775
|
+
case "powershell": {
|
|
776
|
+
const docs = join(home, "Documents");
|
|
777
|
+
const ps7 = process.env.PSModulePath?.includes(join("Documents", "PowerShell", "Modules"));
|
|
778
|
+
const profileDir = join(docs, ps7 ? "PowerShell" : "WindowsPowerShell");
|
|
779
|
+
installPath = join(profileDir, filename);
|
|
780
|
+
mkdirSync(profileDir, { recursive: true });
|
|
781
|
+
const existing = existsSync(installPath) ? readFileSync(installPath, "utf-8") : "";
|
|
782
|
+
const block = `${POWERSHELL_START}\n${completionScript}\n${POWERSHELL_END}`;
|
|
783
|
+
// The marked block is replaced with the new script, without a regular expression.
|
|
784
|
+
const blockStart = existing.indexOf(POWERSHELL_START);
|
|
785
|
+
const blockEnd = existing.indexOf(POWERSHELL_END, blockStart);
|
|
786
|
+
const updated = blockStart >= 0 && blockEnd > blockStart
|
|
787
|
+
? existing.slice(0, blockStart) +
|
|
788
|
+
block +
|
|
789
|
+
existing.slice(blockEnd + POWERSHELL_END.length)
|
|
790
|
+
: `${existing}${existing && !existing.endsWith("\n") ? "\n" : ""}${block}\n`;
|
|
791
|
+
writeFileSync(installPath, updated, "utf-8");
|
|
792
|
+
installInstructions = "\n# Close and reopen PowerShell to load the completion.";
|
|
793
|
+
break;
|
|
794
|
+
}
|
|
795
|
+
case "bash": {
|
|
796
|
+
installPath = join(home, ".bash_completion.d", filename);
|
|
797
|
+
const bashDir = join(home, ".bash_completion.d");
|
|
798
|
+
if (!existsSync(bashDir)) {
|
|
799
|
+
mkdirSync(bashDir, { recursive: true });
|
|
800
|
+
}
|
|
801
|
+
installInstructions = `\n# Add to ~/.bashrc:\nsource ~/.bash_completion.d/${filename}`;
|
|
802
|
+
break;
|
|
803
|
+
}
|
|
804
|
+
case "zsh": {
|
|
805
|
+
installPath = join(home, ".zsh", "completions", filename);
|
|
806
|
+
const zshDir = join(home, ".zsh", "completions");
|
|
807
|
+
if (!existsSync(zshDir)) {
|
|
808
|
+
mkdirSync(zshDir, { recursive: true });
|
|
809
|
+
}
|
|
810
|
+
installInstructions =
|
|
811
|
+
"\n# Add to ~/.zshrc:\nfpath+=(~/.zsh/completions)\nautoload -U compinit && compinit";
|
|
812
|
+
break;
|
|
813
|
+
}
|
|
814
|
+
case "fish": {
|
|
815
|
+
installPath = join(home, ".config", "fish", "completions", filename);
|
|
816
|
+
const fishDir = join(home, ".config", "fish", "completions");
|
|
817
|
+
if (!existsSync(fishDir)) {
|
|
818
|
+
mkdirSync(fishDir, { recursive: true });
|
|
819
|
+
}
|
|
820
|
+
installInstructions = "Fish completions loaded automatically";
|
|
821
|
+
break;
|
|
822
|
+
}
|
|
823
|
+
default:
|
|
824
|
+
installPath = "";
|
|
825
|
+
installInstructions = "";
|
|
826
|
+
}
|
|
827
|
+
// PowerShell already wrote the merged profile above; a plain write here would drop the user's other profile lines.
|
|
828
|
+
if (shell !== "powershell") {
|
|
829
|
+
writeFileSync(installPath, completionScript, "utf-8");
|
|
830
|
+
}
|
|
831
|
+
console.log(chalk.green(`✅ Installed ${shell} completion to:`));
|
|
832
|
+
console.log(chalk.cyan(` ${installPath}`));
|
|
833
|
+
console.log(chalk.yellow(installInstructions));
|
|
834
|
+
}
|
|
835
|
+
else if (options.output) {
|
|
836
|
+
writeFileSync(options.output, completionScript, "utf-8");
|
|
837
|
+
console.log(chalk.green(`✅ Written ${shell} completion to:`));
|
|
838
|
+
console.log(chalk.cyan(` ${options.output}`));
|
|
839
|
+
}
|
|
840
|
+
else {
|
|
841
|
+
console.log(completionScript);
|
|
842
|
+
}
|
|
843
|
+
});
|