@happier-dev/stack 0.1.0-preview.5.1
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/README.md +501 -0
- package/bin/hstack.mjs +348 -0
- package/docs/codex-mcp-resume.md +129 -0
- package/docs/edison.md +74 -0
- package/docs/forking-and-branding.md +189 -0
- package/docs/happy-development.md +22 -0
- package/docs/isolated-linux-vm.md +243 -0
- package/docs/menubar.md +244 -0
- package/docs/mobile-ios.md +322 -0
- package/docs/monorepo-migration.md +20 -0
- package/docs/paths-and-env.md +154 -0
- package/docs/remote-access.md +43 -0
- package/docs/server-flavors.md +147 -0
- package/docs/stacks.md +330 -0
- package/docs/tauri.md +60 -0
- package/docs/worktrees-and-forks.md +133 -0
- package/extras/swiftbar/auth-login.sh +29 -0
- package/extras/swiftbar/git-cache-refresh.sh +122 -0
- package/extras/swiftbar/hstack-term.sh +133 -0
- package/extras/swiftbar/hstack.5s.sh +296 -0
- package/extras/swiftbar/hstack.sh +35 -0
- package/extras/swiftbar/icons/happy-green.png +0 -0
- package/extras/swiftbar/icons/happy-orange.png +0 -0
- package/extras/swiftbar/icons/happy-red.png +0 -0
- package/extras/swiftbar/icons/logo-white.png +0 -0
- package/extras/swiftbar/install.sh +265 -0
- package/extras/swiftbar/lib/git.sh +629 -0
- package/extras/swiftbar/lib/icons.sh +92 -0
- package/extras/swiftbar/lib/render.sh +999 -0
- package/extras/swiftbar/lib/system.sh +244 -0
- package/extras/swiftbar/lib/utils.sh +717 -0
- package/extras/swiftbar/set-interval.sh +65 -0
- package/extras/swiftbar/set-server-flavor.sh +61 -0
- package/extras/swiftbar/wt-pr.sh +140 -0
- package/node_modules/@happier-dev/cli-common/README.md +6 -0
- package/node_modules/@happier-dev/cli-common/dist/index.d.ts +4 -0
- package/node_modules/@happier-dev/cli-common/dist/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/index.js +4 -0
- package/node_modules/@happier-dev/cli-common/dist/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts +18 -0
- package/node_modules/@happier-dev/cli-common/dist/links/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/links/index.js +25 -0
- package/node_modules/@happier-dev/cli-common/dist/links/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/links.d.ts +2 -0
- package/node_modules/@happier-dev/cli-common/dist/links.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/links.js +2 -0
- package/node_modules/@happier-dev/cli-common/dist/links.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts +67 -0
- package/node_modules/@happier-dev/cli-common/dist/update/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/update/index.js +259 -0
- package/node_modules/@happier-dev/cli-common/dist/update/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts +17 -0
- package/node_modules/@happier-dev/cli-common/dist/workspaces/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js +80 -0
- package/node_modules/@happier-dev/cli-common/dist/workspaces/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/package.json +26 -0
- package/package.json +77 -0
- package/scripts/auth.mjs +1829 -0
- package/scripts/auth_copy_from_pglite_lock_in_use.integration.test.mjs +90 -0
- package/scripts/auth_copy_from_runCapture.integration.test.mjs +447 -0
- package/scripts/auth_help_cmd.test.mjs +28 -0
- package/scripts/auth_login_flow_in_tty.test.mjs +100 -0
- package/scripts/auth_login_force_default.test.mjs +66 -0
- package/scripts/auth_login_guided_server_no_expo.test.mjs +126 -0
- package/scripts/auth_login_method_override.test.mjs +67 -0
- package/scripts/auth_login_print_includes_configure_links.test.mjs +99 -0
- package/scripts/auth_status_server_validation.integration.test.mjs +140 -0
- package/scripts/build.mjs +266 -0
- package/scripts/bundleWorkspaceDeps.mjs +38 -0
- package/scripts/bundleWorkspaceDeps.test.mjs +77 -0
- package/scripts/ci.mjs +135 -0
- package/scripts/ci.test.mjs +50 -0
- package/scripts/cli-link.mjs +57 -0
- package/scripts/completion.mjs +395 -0
- package/scripts/contrib.mjs +333 -0
- package/scripts/daemon.mjs +1160 -0
- package/scripts/daemon.status_scope.test.mjs +51 -0
- package/scripts/daemon_cmd.mjs +26 -0
- package/scripts/daemon_dist_guard.test.mjs +171 -0
- package/scripts/daemon_invalid_auth_reseed_stack_name.integration.test.mjs +608 -0
- package/scripts/daemon_server_scoped_state.test.mjs +49 -0
- package/scripts/daemon_start_verification.integration.test.mjs +296 -0
- package/scripts/dev.mjs +545 -0
- package/scripts/doctor.mjs +340 -0
- package/scripts/doctor_cmd.test.mjs +22 -0
- package/scripts/doctor_ui_index_missing.test.mjs +37 -0
- package/scripts/eas.mjs +367 -0
- package/scripts/eas_platform_parsing.test.mjs +63 -0
- package/scripts/edison.mjs +1848 -0
- package/scripts/env.mjs +149 -0
- package/scripts/env_cmd.test.mjs +118 -0
- package/scripts/exit_cleanup_kills_detached_children_on_crash.integration.test.mjs +80 -0
- package/scripts/happier.mjs +82 -0
- package/scripts/import.mjs +1327 -0
- package/scripts/init.mjs +464 -0
- package/scripts/install.mjs +550 -0
- package/scripts/lint.mjs +177 -0
- package/scripts/menubar.mjs +202 -0
- package/scripts/migrate.mjs +318 -0
- package/scripts/mobile.mjs +353 -0
- package/scripts/mobile_dev_client.mjs +87 -0
- package/scripts/monorepo.mjs +2234 -0
- package/scripts/monorepo_port.apply.integration.test.mjs +680 -0
- package/scripts/monorepo_port.conflicts.integration.test.mjs +454 -0
- package/scripts/monorepo_port.validation.integration.test.mjs +486 -0
- package/scripts/orchestrated_stack_auth_flow.test.mjs +134 -0
- package/scripts/orchestrated_stack_auth_flow_resolve_port.test.mjs +98 -0
- package/scripts/orchestrated_stack_auth_flow_webapp_url.test.mjs +119 -0
- package/scripts/pack.mjs +257 -0
- package/scripts/pack.test.mjs +68 -0
- package/scripts/pglite_lock.integration.test.mjs +152 -0
- package/scripts/provision/linux-ubuntu-e2e.sh +132 -0
- package/scripts/provision/linux-ubuntu-review-pr.sh +66 -0
- package/scripts/provision/macos-lima-happy-vm.sh +192 -0
- package/scripts/provision/macos-lima-hstack-e2e.sh +100 -0
- package/scripts/release.mjs +53 -0
- package/scripts/release_binary_smoke.integration.test.mjs +159 -0
- package/scripts/review.mjs +1752 -0
- package/scripts/review_pr.mjs +435 -0
- package/scripts/run.mjs +561 -0
- package/scripts/run_script_with_stack_env.restart_port_reuse.test.mjs +30 -0
- package/scripts/self.mjs +465 -0
- package/scripts/self_host.mjs +9 -0
- package/scripts/self_host_binary_smoke.integration.test.mjs +94 -0
- package/scripts/self_host_runtime.mjs +883 -0
- package/scripts/self_host_runtime.test.mjs +82 -0
- package/scripts/self_host_systemd.real.integration.test.mjs +367 -0
- package/scripts/server_flavor.mjs +148 -0
- package/scripts/service.mjs +868 -0
- package/scripts/service_mode_help.test.mjs +27 -0
- package/scripts/setup.mjs +1324 -0
- package/scripts/setup_non_interactive_flag.test.mjs +60 -0
- package/scripts/setup_pr.mjs +605 -0
- package/scripts/setup_pr_orchestrated_auth_flow_util_import.test.mjs +117 -0
- package/scripts/stack/command_arguments.mjs +91 -0
- package/scripts/stack/copy_auth_from_stack.mjs +111 -0
- package/scripts/stack/delegated_script_commands.mjs +92 -0
- package/scripts/stack/help_text.mjs +110 -0
- package/scripts/stack/port_reservation.mjs +74 -0
- package/scripts/stack/repo_checkout_resolution.mjs +31 -0
- package/scripts/stack/run_script_with_stack_env.mjs +634 -0
- package/scripts/stack/stack_daemon_command.mjs +219 -0
- package/scripts/stack/stack_delegated_help.mjs +81 -0
- package/scripts/stack/stack_environment.mjs +151 -0
- package/scripts/stack/stack_environment.sanitization.test.mjs +75 -0
- package/scripts/stack/stack_happier_passthrough_command.mjs +63 -0
- package/scripts/stack/stack_info_snapshot.mjs +167 -0
- package/scripts/stack/stack_mobile_install_command.mjs +61 -0
- package/scripts/stack/stack_resume_command.mjs +76 -0
- package/scripts/stack/stack_stop_command.mjs +34 -0
- package/scripts/stack/stack_workspace_command.mjs +83 -0
- package/scripts/stack/transient_repo_overrides.mjs +29 -0
- package/scripts/stack.mjs +2388 -0
- package/scripts/stack_archive_cmd.integration.test.mjs +31 -0
- package/scripts/stack_audit_fix_light_env.test.mjs +129 -0
- package/scripts/stack_background_pinned_stack_json.test.mjs +81 -0
- package/scripts/stack_copy_auth_server_scoped.test.mjs +243 -0
- package/scripts/stack_daemon_cmd.integration.test.mjs +484 -0
- package/scripts/stack_eas_help.test.mjs +72 -0
- package/scripts/stack_editor_workspace_monorepo_root.test.mjs +102 -0
- package/scripts/stack_env_cmd.test.mjs +107 -0
- package/scripts/stack_guided_login_bundle_error_parse.test.mjs +20 -0
- package/scripts/stack_guided_login_inner_invocation.test.mjs +46 -0
- package/scripts/stack_happy_cmd.integration.test.mjs +263 -0
- package/scripts/stack_info_snapshot_running_status.test.mjs +186 -0
- package/scripts/stack_interactive_monorepo_group.test.mjs +128 -0
- package/scripts/stack_monorepo_defaults.test.mjs +31 -0
- package/scripts/stack_monorepo_repo_dev_token.test.mjs +32 -0
- package/scripts/stack_monorepo_server_light_from_happy_spec.test.mjs +37 -0
- package/scripts/stack_new_name_normalize_cmd.test.mjs +38 -0
- package/scripts/stack_pr_name_normalize_cmd.test.mjs +84 -0
- package/scripts/stack_resume_cmd.integration.test.mjs +134 -0
- package/scripts/stack_server_flavors_defaults.test.mjs +64 -0
- package/scripts/stack_shorthand_cmd.integration.test.mjs +74 -0
- package/scripts/stack_stop_sweeps_legacy_infra_without_kind.integration.test.mjs +44 -0
- package/scripts/stack_stop_sweeps_when_runtime_missing.integration.test.mjs +42 -0
- package/scripts/stack_stop_sweeps_when_runtime_stale.integration.test.mjs +50 -0
- package/scripts/stack_wt_list.test.mjs +117 -0
- package/scripts/start_ui_required_default.test.mjs +63 -0
- package/scripts/stop.mjs +190 -0
- package/scripts/stopStackWithEnv_no_autosweep_when_runtime_missing.integration.test.mjs +95 -0
- package/scripts/swiftbar_git_monorepo_cmd.test.mjs +75 -0
- package/scripts/swiftbar_render_monorepo_wt_actions.integration.test.mjs +116 -0
- package/scripts/swiftbar_utils_cmd.test.mjs +92 -0
- package/scripts/swiftbar_wt_pr_backcompat.test.mjs +162 -0
- package/scripts/systemd_unit_info.test.mjs +24 -0
- package/scripts/tailscale.mjs +490 -0
- package/scripts/test_ci.mjs +36 -0
- package/scripts/test_cmd.mjs +274 -0
- package/scripts/test_cmd.test.mjs +133 -0
- package/scripts/test_integration.mjs +33 -0
- package/scripts/testkit/auth_testkit.mjs +121 -0
- package/scripts/testkit/doctor_testkit.mjs +68 -0
- package/scripts/testkit/monorepo_port_testkit.mjs +157 -0
- package/scripts/testkit/stack_archive_command_testkit.mjs +55 -0
- package/scripts/testkit/stack_new_monorepo_testkit.mjs +83 -0
- package/scripts/testkit/stack_script_command_testkit.mjs +27 -0
- package/scripts/testkit/stack_stop_sweeps_testkit.mjs +172 -0
- package/scripts/testkit/worktrees_monorepo_testkit.mjs +53 -0
- package/scripts/tools.mjs +70 -0
- package/scripts/tui.mjs +914 -0
- package/scripts/tui_stopStackForTuiExit_no_autosweep.integration.test.mjs +95 -0
- package/scripts/typecheck.mjs +178 -0
- package/scripts/ui_gateway.mjs +247 -0
- package/scripts/uninstall.mjs +179 -0
- package/scripts/utils/auth/credentials_paths.mjs +181 -0
- package/scripts/utils/auth/credentials_paths.test.mjs +187 -0
- package/scripts/utils/auth/daemon_gate.mjs +66 -0
- package/scripts/utils/auth/daemon_gate.test.mjs +116 -0
- package/scripts/utils/auth/decode_jwt_payload_unsafe.mjs +16 -0
- package/scripts/utils/auth/dev_key.mjs +163 -0
- package/scripts/utils/auth/files.mjs +56 -0
- package/scripts/utils/auth/guided_pr_auth.mjs +86 -0
- package/scripts/utils/auth/guided_stack_web_login.mjs +56 -0
- package/scripts/utils/auth/handy_master_secret.mjs +42 -0
- package/scripts/utils/auth/interactive_stack_auth.mjs +70 -0
- package/scripts/utils/auth/login_ux.mjs +105 -0
- package/scripts/utils/auth/orchestrated_stack_auth_flow.mjs +291 -0
- package/scripts/utils/auth/sources.mjs +28 -0
- package/scripts/utils/auth/stable_scope_id.mjs +91 -0
- package/scripts/utils/auth/stable_scope_id.test.mjs +51 -0
- package/scripts/utils/auth/stack_guided_login.mjs +438 -0
- package/scripts/utils/cli/arg_values.mjs +23 -0
- package/scripts/utils/cli/arg_values.test.mjs +43 -0
- package/scripts/utils/cli/args.mjs +17 -0
- package/scripts/utils/cli/cli.mjs +24 -0
- package/scripts/utils/cli/cli_registry.mjs +440 -0
- package/scripts/utils/cli/cwd_scope.mjs +158 -0
- package/scripts/utils/cli/cwd_scope.test.mjs +154 -0
- package/scripts/utils/cli/flags.mjs +17 -0
- package/scripts/utils/cli/log_forwarder.mjs +157 -0
- package/scripts/utils/cli/normalize.mjs +16 -0
- package/scripts/utils/cli/prereqs.mjs +103 -0
- package/scripts/utils/cli/prereqs.test.mjs +33 -0
- package/scripts/utils/cli/progress.mjs +141 -0
- package/scripts/utils/cli/smoke_help.mjs +44 -0
- package/scripts/utils/cli/verbosity.mjs +11 -0
- package/scripts/utils/cli/wizard.mjs +139 -0
- package/scripts/utils/cli/wizard_promptSelect.test.mjs +44 -0
- package/scripts/utils/cli/wizard_prompt_worktree_source_lazy.test.mjs +132 -0
- package/scripts/utils/cli/wizard_worktree_slug.test.mjs +33 -0
- package/scripts/utils/crypto/tokens.mjs +14 -0
- package/scripts/utils/dev/daemon.mjs +232 -0
- package/scripts/utils/dev/daemon_watch_resilience.test.mjs +224 -0
- package/scripts/utils/dev/expo_dev.buildEnv.test.mjs +35 -0
- package/scripts/utils/dev/expo_dev.mjs +478 -0
- package/scripts/utils/dev/expo_dev.test.mjs +89 -0
- package/scripts/utils/dev/expo_dev_restart_port_reservation.test.mjs +120 -0
- package/scripts/utils/dev/expo_dev_verbose_logs.test.mjs +60 -0
- package/scripts/utils/dev/server.mjs +180 -0
- package/scripts/utils/dev_auth_key.mjs +7 -0
- package/scripts/utils/edison/git_roots.mjs +30 -0
- package/scripts/utils/edison/git_roots.test.mjs +49 -0
- package/scripts/utils/env/config.mjs +52 -0
- package/scripts/utils/env/dotenv.mjs +32 -0
- package/scripts/utils/env/dotenv.test.mjs +32 -0
- package/scripts/utils/env/env.mjs +130 -0
- package/scripts/utils/env/env_file.mjs +98 -0
- package/scripts/utils/env/env_file.test.mjs +49 -0
- package/scripts/utils/env/env_local.mjs +25 -0
- package/scripts/utils/env/load_env_file.mjs +34 -0
- package/scripts/utils/env/read.mjs +30 -0
- package/scripts/utils/env/sandbox.mjs +13 -0
- package/scripts/utils/env/scrub_env.mjs +69 -0
- package/scripts/utils/env/scrub_env.test.mjs +102 -0
- package/scripts/utils/env/values.mjs +13 -0
- package/scripts/utils/expo/command.mjs +65 -0
- package/scripts/utils/expo/expo.mjs +139 -0
- package/scripts/utils/expo/expo_state_running.test.mjs +48 -0
- package/scripts/utils/expo/metro_ports.mjs +101 -0
- package/scripts/utils/expo/metro_ports.test.mjs +35 -0
- package/scripts/utils/fs/atomic_dir_swap.mjs +55 -0
- package/scripts/utils/fs/atomic_dir_swap.test.mjs +54 -0
- package/scripts/utils/fs/file_has_content.mjs +10 -0
- package/scripts/utils/fs/fs.mjs +11 -0
- package/scripts/utils/fs/json.mjs +25 -0
- package/scripts/utils/fs/ops.mjs +29 -0
- package/scripts/utils/fs/package_json.mjs +8 -0
- package/scripts/utils/fs/tail.mjs +12 -0
- package/scripts/utils/git/dev_checkout.mjs +127 -0
- package/scripts/utils/git/dev_checkout.test.mjs +115 -0
- package/scripts/utils/git/git.mjs +67 -0
- package/scripts/utils/git/parse_name_status_z.mjs +21 -0
- package/scripts/utils/git/refs.mjs +26 -0
- package/scripts/utils/git/worktrees.mjs +323 -0
- package/scripts/utils/git/worktrees_monorepo.test.mjs +60 -0
- package/scripts/utils/git/worktrees_pathstyle.test.mjs +53 -0
- package/scripts/utils/llm/assist.mjs +260 -0
- package/scripts/utils/llm/codex_exec.mjs +61 -0
- package/scripts/utils/llm/codex_exec.test.mjs +46 -0
- package/scripts/utils/llm/hstack_runner.mjs +59 -0
- package/scripts/utils/llm/tools.mjs +56 -0
- package/scripts/utils/llm/tools.test.mjs +67 -0
- package/scripts/utils/menubar/swiftbar.mjs +121 -0
- package/scripts/utils/menubar/swiftbar.test.mjs +85 -0
- package/scripts/utils/mobile/config.mjs +35 -0
- package/scripts/utils/mobile/dev_client_links.mjs +59 -0
- package/scripts/utils/mobile/identifiers.mjs +46 -0
- package/scripts/utils/mobile/identifiers.test.mjs +41 -0
- package/scripts/utils/mobile/ios_xcodeproj_patch.mjs +128 -0
- package/scripts/utils/mobile/ios_xcodeproj_patch.test.mjs +131 -0
- package/scripts/utils/net/bind_mode.mjs +39 -0
- package/scripts/utils/net/dns.mjs +10 -0
- package/scripts/utils/net/lan_ip.mjs +24 -0
- package/scripts/utils/net/ports.mjs +110 -0
- package/scripts/utils/net/tcp_forward.mjs +162 -0
- package/scripts/utils/net/url.mjs +30 -0
- package/scripts/utils/net/url.test.mjs +29 -0
- package/scripts/utils/paths/canonical_home.mjs +15 -0
- package/scripts/utils/paths/canonical_home.test.mjs +28 -0
- package/scripts/utils/paths/localhost_host.mjs +112 -0
- package/scripts/utils/paths/localhost_host.test.mjs +58 -0
- package/scripts/utils/paths/paths.mjs +302 -0
- package/scripts/utils/paths/paths_env_win32.test.mjs +36 -0
- package/scripts/utils/paths/paths_monorepo.test.mjs +58 -0
- package/scripts/utils/paths/paths_server_flavors.test.mjs +50 -0
- package/scripts/utils/paths/runtime.mjs +41 -0
- package/scripts/utils/pglite_lock.mjs +107 -0
- package/scripts/utils/proc/commands.mjs +33 -0
- package/scripts/utils/proc/exit_cleanup.mjs +57 -0
- package/scripts/utils/proc/happy_monorepo_deps.mjs +37 -0
- package/scripts/utils/proc/happy_monorepo_deps.test.mjs +89 -0
- package/scripts/utils/proc/ownership.mjs +217 -0
- package/scripts/utils/proc/ownership_killProcessGroupOwnedByStack.test.mjs +216 -0
- package/scripts/utils/proc/ownership_listPidsWithEnvNeedles.test.mjs +88 -0
- package/scripts/utils/proc/package_scripts.mjs +38 -0
- package/scripts/utils/proc/package_scripts.test.mjs +58 -0
- package/scripts/utils/proc/parallel.mjs +25 -0
- package/scripts/utils/proc/pids.mjs +11 -0
- package/scripts/utils/proc/pm.mjs +478 -0
- package/scripts/utils/proc/pm_spawn.integration.test.mjs +131 -0
- package/scripts/utils/proc/pm_stack_cache_env.test.mjs +313 -0
- package/scripts/utils/proc/proc.mjs +331 -0
- package/scripts/utils/proc/proc.test.mjs +85 -0
- package/scripts/utils/proc/terminate.mjs +69 -0
- package/scripts/utils/proc/terminate.test.mjs +54 -0
- package/scripts/utils/proc/watch.mjs +63 -0
- package/scripts/utils/review/augment_runner_integration.test.mjs +105 -0
- package/scripts/utils/review/base_ref.mjs +82 -0
- package/scripts/utils/review/base_ref.test.mjs +89 -0
- package/scripts/utils/review/chunks.mjs +55 -0
- package/scripts/utils/review/chunks.test.mjs +107 -0
- package/scripts/utils/review/detached_worktree.mjs +61 -0
- package/scripts/utils/review/detached_worktree.test.mjs +61 -0
- package/scripts/utils/review/findings.mjs +278 -0
- package/scripts/utils/review/findings.test.mjs +203 -0
- package/scripts/utils/review/head_slice.mjs +132 -0
- package/scripts/utils/review/head_slice.test.mjs +117 -0
- package/scripts/utils/review/instructions/deep.md +20 -0
- package/scripts/utils/review/prompts.mjs +279 -0
- package/scripts/utils/review/prompts.test.mjs +77 -0
- package/scripts/utils/review/run_reviewers_safe.mjs +12 -0
- package/scripts/utils/review/run_reviewers_safe.test.mjs +45 -0
- package/scripts/utils/review/runners/augment.mjs +91 -0
- package/scripts/utils/review/runners/augment.test.mjs +64 -0
- package/scripts/utils/review/runners/claude.mjs +92 -0
- package/scripts/utils/review/runners/claude.test.mjs +47 -0
- package/scripts/utils/review/runners/coderabbit.mjs +105 -0
- package/scripts/utils/review/runners/coderabbit.test.mjs +32 -0
- package/scripts/utils/review/runners/codex.mjs +129 -0
- package/scripts/utils/review/runners/codex.test.mjs +115 -0
- package/scripts/utils/review/slice_mode.mjs +20 -0
- package/scripts/utils/review/slice_mode.test.mjs +69 -0
- package/scripts/utils/review/sliced_runner.mjs +39 -0
- package/scripts/utils/review/sliced_runner.test.mjs +57 -0
- package/scripts/utils/review/slices.mjs +140 -0
- package/scripts/utils/review/slices.test.mjs +41 -0
- package/scripts/utils/review/targets.mjs +23 -0
- package/scripts/utils/review/targets.test.mjs +31 -0
- package/scripts/utils/review/tool_home_seed.mjs +106 -0
- package/scripts/utils/review/tool_home_seed.test.mjs +124 -0
- package/scripts/utils/review/uncommitted_ops.mjs +77 -0
- package/scripts/utils/review/uncommitted_ops.test.mjs +117 -0
- package/scripts/utils/sandbox/review_pr_sandbox.mjs +105 -0
- package/scripts/utils/server/apply_server_light_env_defaults.mjs +14 -0
- package/scripts/utils/server/flavor_scripts.mjs +138 -0
- package/scripts/utils/server/flavor_scripts.test.mjs +115 -0
- package/scripts/utils/server/infra/happy_server_infra.mjs +444 -0
- package/scripts/utils/server/mobile_api_url.mjs +60 -0
- package/scripts/utils/server/mobile_api_url.test.mjs +58 -0
- package/scripts/utils/server/port.mjs +55 -0
- package/scripts/utils/server/prisma_import.mjs +36 -0
- package/scripts/utils/server/prisma_import.test.mjs +78 -0
- package/scripts/utils/server/server.mjs +109 -0
- package/scripts/utils/server/ui_build_check.mjs +37 -0
- package/scripts/utils/server/ui_build_check.test.mjs +70 -0
- package/scripts/utils/server/ui_env.mjs +13 -0
- package/scripts/utils/server/ui_env.test.mjs +57 -0
- package/scripts/utils/server/urls.mjs +100 -0
- package/scripts/utils/server/validate.mjs +60 -0
- package/scripts/utils/server/validate.test.mjs +76 -0
- package/scripts/utils/service/autostart_darwin.mjs +198 -0
- package/scripts/utils/service/autostart_darwin.test.mjs +49 -0
- package/scripts/utils/service/autostart_darwin_keepalive.test.mjs +19 -0
- package/scripts/utils/stack/cli_identities.mjs +29 -0
- package/scripts/utils/stack/context.mjs +19 -0
- package/scripts/utils/stack/dirs.mjs +26 -0
- package/scripts/utils/stack/editor_workspace.mjs +126 -0
- package/scripts/utils/stack/interactive_stack_config.mjs +266 -0
- package/scripts/utils/stack/interactive_stack_config.port_validation.test.mjs +93 -0
- package/scripts/utils/stack/interactive_stack_config.remote_validation.test.mjs +122 -0
- package/scripts/utils/stack/interactive_stack_config.stack_name_validation.test.mjs +76 -0
- package/scripts/utils/stack/interactive_stack_config_testkit.mjs +18 -0
- package/scripts/utils/stack/names.mjs +27 -0
- package/scripts/utils/stack/names.test.mjs +26 -0
- package/scripts/utils/stack/pr_stack_name.mjs +16 -0
- package/scripts/utils/stack/runtime_state.mjs +88 -0
- package/scripts/utils/stack/stacks.mjs +40 -0
- package/scripts/utils/stack/startup.mjs +370 -0
- package/scripts/utils/stack/startup_server_light_dirs.test.mjs +119 -0
- package/scripts/utils/stack/startup_server_light_generate.test.mjs +20 -0
- package/scripts/utils/stack/startup_server_light_legacy.test.mjs +79 -0
- package/scripts/utils/stack/startup_server_light_testkit.mjs +106 -0
- package/scripts/utils/stack/stop.mjs +284 -0
- package/scripts/utils/stack_context.mjs +1 -0
- package/scripts/utils/stack_runtime_state.mjs +1 -0
- package/scripts/utils/stacks.mjs +1 -0
- package/scripts/utils/tailscale/ip.mjs +116 -0
- package/scripts/utils/tauri/stack_overrides.mjs +22 -0
- package/scripts/utils/test/collect_test_files.mjs +29 -0
- package/scripts/utils/time/get_today_ymd.mjs +7 -0
- package/scripts/utils/tui/cleanup.mjs +38 -0
- package/scripts/utils/ui/ansi.mjs +47 -0
- package/scripts/utils/ui/browser.mjs +31 -0
- package/scripts/utils/ui/browser.test.mjs +56 -0
- package/scripts/utils/ui/clipboard.mjs +38 -0
- package/scripts/utils/ui/layout.mjs +44 -0
- package/scripts/utils/ui/qr.mjs +17 -0
- package/scripts/utils/ui/terminal_launcher.mjs +129 -0
- package/scripts/utils/ui/text.mjs +16 -0
- package/scripts/utils/update/auto_update_notice.mjs +93 -0
- package/scripts/utils/validate.mjs +5 -0
- package/scripts/where.mjs +138 -0
- package/scripts/worktrees.mjs +2174 -0
- package/scripts/worktrees_archive_cmd.integration.test.mjs +228 -0
- package/scripts/worktrees_cursor_monorepo_root.test.mjs +23 -0
- package/scripts/worktrees_list_specs_no_recurse.test.mjs +32 -0
- package/scripts/worktrees_monorepo_testkit.test.mjs +29 -0
- package/scripts/worktrees_monorepo_use_group.test.mjs +41 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { chmod, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { pmSpawnBin, pmSpawnScript } from './pm.mjs';
|
|
8
|
+
|
|
9
|
+
async function writeJson(path, obj) {
|
|
10
|
+
await writeFile(path, JSON.stringify(obj, null, 2) + '\n', 'utf-8');
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async function waitExit(child) {
|
|
14
|
+
return await new Promise((resolve) => {
|
|
15
|
+
child.on('exit', (code, signal) => resolve({ code, signal }));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function writeStubYarn({ binDir }) {
|
|
20
|
+
await mkdir(binDir, { recursive: true });
|
|
21
|
+
const yarnPath = join(binDir, 'yarn');
|
|
22
|
+
await writeFile(
|
|
23
|
+
yarnPath,
|
|
24
|
+
[
|
|
25
|
+
'#!/usr/bin/env node',
|
|
26
|
+
'const args = process.argv.slice(2);',
|
|
27
|
+
// ensureYarnReady calls: yarn --version
|
|
28
|
+
"if (args.includes('--version')) { console.log('1.22.22'); process.exit(0); }",
|
|
29
|
+
// pmSpawn* calls: yarn run <script/bin> ...
|
|
30
|
+
'if (args[0] === "run") process.exit(0);',
|
|
31
|
+
'process.exit(0);',
|
|
32
|
+
].join('\n') + '\n',
|
|
33
|
+
'utf-8'
|
|
34
|
+
);
|
|
35
|
+
await chmod(yarnPath, 0o755);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function writeStubYarnCaptureKind({ binDir }) {
|
|
39
|
+
await mkdir(binDir, { recursive: true });
|
|
40
|
+
const yarnPath = join(binDir, 'yarn');
|
|
41
|
+
await writeFile(
|
|
42
|
+
yarnPath,
|
|
43
|
+
[
|
|
44
|
+
'#!/usr/bin/env node',
|
|
45
|
+
'const fs = require("fs");',
|
|
46
|
+
'const args = process.argv.slice(2);',
|
|
47
|
+
// ensureYarnReady calls: yarn --version
|
|
48
|
+
"if (args.includes('--version')) { console.log('1.22.22'); process.exit(0); }",
|
|
49
|
+
// pmSpawn* calls: yarn run <script/bin> ...
|
|
50
|
+
'if (args[0] === "run") {',
|
|
51
|
+
' const out = process.env.TEST_OUT_FILE || "";',
|
|
52
|
+
' if (out) fs.writeFileSync(out, String(process.env.HAPPIER_STACK_PROCESS_KIND || ""), "utf-8");',
|
|
53
|
+
' process.exit(0);',
|
|
54
|
+
'}',
|
|
55
|
+
'process.exit(0);',
|
|
56
|
+
].join('\n') + '\n',
|
|
57
|
+
'utf-8'
|
|
58
|
+
);
|
|
59
|
+
await chmod(yarnPath, 0o755);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
test('pmSpawnScript does not reference effectiveEnv before initialization', async (t) => {
|
|
63
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-spawn-script-'));
|
|
64
|
+
t.after(async () => {
|
|
65
|
+
await rm(root, { recursive: true, force: true });
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const componentDir = join(root, 'component');
|
|
69
|
+
await mkdir(componentDir, { recursive: true });
|
|
70
|
+
await writeJson(join(componentDir, 'package.json'), { name: 'component', version: '0.0.0' });
|
|
71
|
+
await writeFile(join(componentDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
72
|
+
|
|
73
|
+
const binDir = join(root, 'bin');
|
|
74
|
+
await writeStubYarn({ binDir });
|
|
75
|
+
|
|
76
|
+
const env = { ...process.env, PATH: `${binDir}:${process.env.PATH ?? ''}` };
|
|
77
|
+
const child = await pmSpawnScript({ dir: componentDir, label: 'spawn-test', script: 'noop', env, quiet: true, options: { silent: true } });
|
|
78
|
+
const res = await waitExit(child);
|
|
79
|
+
assert.equal(res.code, 0);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('pmSpawnBin does not reference effectiveEnv before initialization', async (t) => {
|
|
83
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-spawn-bin-'));
|
|
84
|
+
t.after(async () => {
|
|
85
|
+
await rm(root, { recursive: true, force: true });
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
const componentDir = join(root, 'component');
|
|
89
|
+
await mkdir(componentDir, { recursive: true });
|
|
90
|
+
await writeJson(join(componentDir, 'package.json'), { name: 'component', version: '0.0.0' });
|
|
91
|
+
await writeFile(join(componentDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
92
|
+
|
|
93
|
+
const binDir = join(root, 'bin');
|
|
94
|
+
await writeStubYarn({ binDir });
|
|
95
|
+
|
|
96
|
+
const env = { ...process.env, PATH: `${binDir}:${process.env.PATH ?? ''}` };
|
|
97
|
+
const child = await pmSpawnBin({ dir: componentDir, label: 'spawn-test', bin: 'prisma', args: ['generate'], env, quiet: true, options: { silent: true } });
|
|
98
|
+
const res = await waitExit(child);
|
|
99
|
+
assert.equal(res.code, 0);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test('pmSpawnScript marks stack-owned infra processes with HAPPIER_STACK_PROCESS_KIND=infra', async (t) => {
|
|
103
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-spawn-kind-'));
|
|
104
|
+
t.after(async () => {
|
|
105
|
+
await rm(root, { recursive: true, force: true });
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
const componentDir = join(root, 'component');
|
|
109
|
+
await mkdir(componentDir, { recursive: true });
|
|
110
|
+
await writeJson(join(componentDir, 'package.json'), { name: 'component', version: '0.0.0' });
|
|
111
|
+
await writeFile(join(componentDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
112
|
+
|
|
113
|
+
const outFile = join(root, 'kind.txt');
|
|
114
|
+
|
|
115
|
+
const binDir = join(root, 'bin');
|
|
116
|
+
await writeStubYarnCaptureKind({ binDir });
|
|
117
|
+
|
|
118
|
+
const env = {
|
|
119
|
+
...process.env,
|
|
120
|
+
PATH: `${binDir}:${process.env.PATH ?? ''}`,
|
|
121
|
+
TEST_OUT_FILE: outFile,
|
|
122
|
+
HAPPIER_STACK_STACK: 'k',
|
|
123
|
+
HAPPIER_STACK_ENV_FILE: join(root, 'stack-env'),
|
|
124
|
+
};
|
|
125
|
+
const child = await pmSpawnScript({ dir: componentDir, label: 'spawn-test', script: 'noop', env, quiet: true, options: { silent: true } });
|
|
126
|
+
const res = await waitExit(child);
|
|
127
|
+
assert.equal(res.code, 0);
|
|
128
|
+
|
|
129
|
+
const kind = (await readFile(outFile, 'utf-8')).trim();
|
|
130
|
+
assert.equal(kind, 'infra');
|
|
131
|
+
});
|
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { chmod, mkdtemp, mkdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
4
|
+
import { tmpdir } from 'node:os';
|
|
5
|
+
import { dirname, join } from 'node:path';
|
|
6
|
+
|
|
7
|
+
import { ensureCliBuilt, ensureDepsInstalled, pmExecBin } from './pm.mjs';
|
|
8
|
+
|
|
9
|
+
async function writeYarnEnvDumpStub({ binDir, outputPath }) {
|
|
10
|
+
await mkdir(binDir, { recursive: true });
|
|
11
|
+
const yarnPath = join(binDir, 'yarn');
|
|
12
|
+
await writeFile(
|
|
13
|
+
yarnPath,
|
|
14
|
+
[
|
|
15
|
+
'#!/usr/bin/env node',
|
|
16
|
+
"const { writeFileSync } = require('node:fs');",
|
|
17
|
+
"const out = {",
|
|
18
|
+
' XDG_CACHE_HOME: process.env.XDG_CACHE_HOME ?? null,',
|
|
19
|
+
' YARN_CACHE_FOLDER: process.env.YARN_CACHE_FOLDER ?? null,',
|
|
20
|
+
' npm_config_cache: process.env.npm_config_cache ?? null,',
|
|
21
|
+
'};',
|
|
22
|
+
"writeFileSync(process.env.OUTPUT_PATH, JSON.stringify(out, null, 2) + '\\n');",
|
|
23
|
+
'process.exit(0);',
|
|
24
|
+
].join('\n') + '\n',
|
|
25
|
+
'utf-8'
|
|
26
|
+
);
|
|
27
|
+
await chmod(yarnPath, 0o755);
|
|
28
|
+
await writeFile(outputPath, '', 'utf-8');
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async function writeYarnArgDumpStub({ binDir, outputPath }) {
|
|
32
|
+
await mkdir(binDir, { recursive: true });
|
|
33
|
+
const yarnPath = join(binDir, 'yarn');
|
|
34
|
+
await writeFile(
|
|
35
|
+
yarnPath,
|
|
36
|
+
[
|
|
37
|
+
'#!/usr/bin/env bash',
|
|
38
|
+
'set -euo pipefail',
|
|
39
|
+
'echo "$*" >> "${OUTPUT_PATH:?}"',
|
|
40
|
+
].join('\n') + '\n',
|
|
41
|
+
'utf-8'
|
|
42
|
+
);
|
|
43
|
+
await chmod(yarnPath, 0o755);
|
|
44
|
+
await writeFile(outputPath, '', 'utf-8');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function writeNpmArgDumpStub({ binDir, outputPath }) {
|
|
48
|
+
await mkdir(binDir, { recursive: true });
|
|
49
|
+
const npmPath = join(binDir, 'npm');
|
|
50
|
+
await writeFile(
|
|
51
|
+
npmPath,
|
|
52
|
+
[
|
|
53
|
+
'#!/usr/bin/env bash',
|
|
54
|
+
'set -euo pipefail',
|
|
55
|
+
'echo "$*" >> "${OUTPUT_PATH:?}"',
|
|
56
|
+
].join('\n') + '\n',
|
|
57
|
+
'utf-8'
|
|
58
|
+
);
|
|
59
|
+
await chmod(npmPath, 0o755);
|
|
60
|
+
await writeFile(outputPath, '', 'utf-8');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
async function writeYarnBuildFailAfterDeletingDistStub({ binDir, outputPath }) {
|
|
64
|
+
await mkdir(binDir, { recursive: true });
|
|
65
|
+
const yarnPath = join(binDir, 'yarn');
|
|
66
|
+
await writeFile(
|
|
67
|
+
yarnPath,
|
|
68
|
+
[
|
|
69
|
+
'#!/usr/bin/env bash',
|
|
70
|
+
'set -euo pipefail',
|
|
71
|
+
'echo "$*" >> "${OUTPUT_PATH:?}"',
|
|
72
|
+
'if [ "${1:-}" = "--version" ]; then',
|
|
73
|
+
' echo "1.22.22"',
|
|
74
|
+
' exit 0',
|
|
75
|
+
'fi',
|
|
76
|
+
'if [ "${1:-}" = "build" ]; then',
|
|
77
|
+
' rm -rf dist',
|
|
78
|
+
' echo "simulated build failure" >&2',
|
|
79
|
+
' exit 2',
|
|
80
|
+
'fi',
|
|
81
|
+
'exit 0',
|
|
82
|
+
].join('\n') + '\n',
|
|
83
|
+
'utf-8'
|
|
84
|
+
);
|
|
85
|
+
await chmod(yarnPath, 0o755);
|
|
86
|
+
await writeFile(outputPath, '', 'utf-8');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function expectedCacheEnv({ envPath }) {
|
|
90
|
+
const base = join(dirname(envPath), 'cache');
|
|
91
|
+
return {
|
|
92
|
+
xdg: join(base, 'xdg'),
|
|
93
|
+
yarn: join(base, 'yarn'),
|
|
94
|
+
npm: join(base, 'npm'),
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function applyEnvOverrides(t, vars) {
|
|
99
|
+
const previous = {};
|
|
100
|
+
for (const key of Object.keys(vars)) {
|
|
101
|
+
previous[key] = process.env[key];
|
|
102
|
+
}
|
|
103
|
+
t.after(() => {
|
|
104
|
+
for (const [key, value] of Object.entries(previous)) {
|
|
105
|
+
if (value == null) delete process.env[key];
|
|
106
|
+
else process.env[key] = value;
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
110
|
+
if (value == null) delete process.env[key];
|
|
111
|
+
else process.env[key] = String(value);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function createStackCacheFixture(t, prefix) {
|
|
116
|
+
const root = await mkdtemp(join(tmpdir(), prefix));
|
|
117
|
+
t.after(async () => {
|
|
118
|
+
await rm(root, { recursive: true, force: true });
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
const stackDir = join(root, 'stacks', 'exp1');
|
|
122
|
+
const envPath = join(stackDir, 'env');
|
|
123
|
+
await mkdir(dirname(envPath), { recursive: true });
|
|
124
|
+
await writeFile(envPath, 'HAPPIER_STACK_STACK=exp1\n', 'utf-8');
|
|
125
|
+
|
|
126
|
+
const componentDir = join(root, 'component');
|
|
127
|
+
await mkdir(componentDir, { recursive: true });
|
|
128
|
+
await writeFile(join(componentDir, 'package.json'), '{}\n', 'utf-8');
|
|
129
|
+
await writeFile(join(componentDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
130
|
+
|
|
131
|
+
const binDir = join(root, 'bin');
|
|
132
|
+
return { root, envPath, componentDir, binDir };
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
test('ensureDepsInstalled sets stack-scoped cache env vars for yarn installs', async (t) => {
|
|
136
|
+
const fixture = await createStackCacheFixture(t, 'hs-pm-stack-cache-install-');
|
|
137
|
+
const { root, envPath, componentDir, binDir } = fixture;
|
|
138
|
+
const outputPath = join(root, 'env.json');
|
|
139
|
+
await writeYarnEnvDumpStub({ binDir, outputPath });
|
|
140
|
+
|
|
141
|
+
const exp = expectedCacheEnv({ envPath });
|
|
142
|
+
applyEnvOverrides(t, {
|
|
143
|
+
PATH: `${binDir}:${process.env.PATH ?? ''}`,
|
|
144
|
+
OUTPUT_PATH: outputPath,
|
|
145
|
+
HAPPIER_STACK_ENV_FILE: envPath,
|
|
146
|
+
XDG_CACHE_HOME: null,
|
|
147
|
+
YARN_CACHE_FOLDER: null,
|
|
148
|
+
npm_config_cache: null,
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
await ensureDepsInstalled(componentDir, 'test-component', { quiet: true });
|
|
152
|
+
const parsed = JSON.parse(await readFile(outputPath, 'utf-8'));
|
|
153
|
+
assert.equal(parsed.XDG_CACHE_HOME, exp.xdg);
|
|
154
|
+
assert.equal(parsed.YARN_CACHE_FOLDER, exp.yarn);
|
|
155
|
+
assert.equal(parsed.npm_config_cache, exp.npm);
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
test('ensureDepsInstalled prefers yarn when component is inside the Happy monorepo (packages/ layout)', async (t) => {
|
|
159
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-happy-monorepo-yarn-'));
|
|
160
|
+
t.after(async () => {
|
|
161
|
+
await rm(root, { recursive: true, force: true });
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
// Create the minimum monorepo markers (packages/ layout) + root yarn.lock.
|
|
165
|
+
await mkdir(join(root, 'apps', 'ui'), { recursive: true });
|
|
166
|
+
await mkdir(join(root, 'apps', 'cli'), { recursive: true });
|
|
167
|
+
await mkdir(join(root, 'apps', 'server'), { recursive: true });
|
|
168
|
+
await writeFile(join(root, 'apps', 'ui', 'package.json'), '{}\n', 'utf-8');
|
|
169
|
+
await writeFile(join(root, 'apps', 'cli', 'package.json'), '{}\n', 'utf-8');
|
|
170
|
+
await writeFile(join(root, 'apps', 'server', 'package.json'), '{}\n', 'utf-8');
|
|
171
|
+
await writeFile(join(root, 'package.json'), '{ "name": "monorepo", "private": true }\n', 'utf-8');
|
|
172
|
+
await writeFile(join(root, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
173
|
+
|
|
174
|
+
const componentDir = join(root, 'apps', 'server');
|
|
175
|
+
|
|
176
|
+
const binDir = join(root, 'bin');
|
|
177
|
+
const outputPath = join(root, 'argv.txt');
|
|
178
|
+
await writeYarnArgDumpStub({ binDir, outputPath });
|
|
179
|
+
|
|
180
|
+
applyEnvOverrides(t, {
|
|
181
|
+
// Avoid leaking other package managers into PATH so the test fails loudly when a non-yarn fallback is attempted.
|
|
182
|
+
PATH: `${binDir}:/usr/bin:/bin`,
|
|
183
|
+
OUTPUT_PATH: outputPath,
|
|
184
|
+
HAPPIER_STACK_ENV_FILE: null,
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
await ensureDepsInstalled(componentDir, 'happier-server', { quiet: true });
|
|
188
|
+
const out = await readFile(outputPath, 'utf-8');
|
|
189
|
+
assert.ok(out.includes('install') || out.includes('--version'));
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test('ensureDepsInstalled falls back to npm in binary mode when yarn is unavailable', async (t) => {
|
|
193
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-binary-mode-npm-'));
|
|
194
|
+
t.after(async () => {
|
|
195
|
+
await rm(root, { recursive: true, force: true });
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const componentDir = join(root, 'component');
|
|
199
|
+
await mkdir(componentDir, { recursive: true });
|
|
200
|
+
await writeFile(join(componentDir, 'package.json'), '{}\n', 'utf-8');
|
|
201
|
+
|
|
202
|
+
const binDir = join(root, 'bin');
|
|
203
|
+
const outputPath = join(root, 'argv.txt');
|
|
204
|
+
await writeNpmArgDumpStub({ binDir, outputPath });
|
|
205
|
+
|
|
206
|
+
applyEnvOverrides(t, {
|
|
207
|
+
PATH: `${binDir}:/usr/bin:/bin`,
|
|
208
|
+
OUTPUT_PATH: outputPath,
|
|
209
|
+
HAPPIER_STACK_BINARY_MODE: '1',
|
|
210
|
+
HAPPIER_STACK_ENV_FILE: null,
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
await ensureDepsInstalled(componentDir, 'binary-mode-component', { quiet: true });
|
|
214
|
+
const out = await readFile(outputPath, 'utf-8');
|
|
215
|
+
assert.match(out, /install/);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
test('pmExecBin sets stack-scoped cache env vars for yarn runs', async (t) => {
|
|
219
|
+
const fixture = await createStackCacheFixture(t, 'hs-pm-stack-cache-exec-');
|
|
220
|
+
const { root, envPath, componentDir, binDir } = fixture;
|
|
221
|
+
const outputPath = join(root, 'env.json');
|
|
222
|
+
await writeYarnEnvDumpStub({ binDir, outputPath });
|
|
223
|
+
|
|
224
|
+
const exp = expectedCacheEnv({ envPath });
|
|
225
|
+
applyEnvOverrides(t, {
|
|
226
|
+
PATH: `${binDir}:${process.env.PATH ?? ''}`,
|
|
227
|
+
OUTPUT_PATH: outputPath,
|
|
228
|
+
HAPPIER_STACK_ENV_FILE: envPath,
|
|
229
|
+
XDG_CACHE_HOME: null,
|
|
230
|
+
YARN_CACHE_FOLDER: null,
|
|
231
|
+
npm_config_cache: null,
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
await pmExecBin({ dir: componentDir, bin: 'prisma', args: ['generate'], env: process.env, quiet: true });
|
|
235
|
+
const parsed = JSON.parse(await readFile(outputPath, 'utf-8'));
|
|
236
|
+
assert.equal(parsed.XDG_CACHE_HOME, exp.xdg);
|
|
237
|
+
assert.equal(parsed.YARN_CACHE_FOLDER, exp.yarn);
|
|
238
|
+
assert.equal(parsed.npm_config_cache, exp.npm);
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test('ensureCliBuilt restores previous dist output when build fails', async (t) => {
|
|
242
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-cli-build-restore-'));
|
|
243
|
+
t.after(async () => {
|
|
244
|
+
await rm(root, { recursive: true, force: true });
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const cliDir = join(root, 'apps', 'cli');
|
|
248
|
+
await mkdir(cliDir, { recursive: true });
|
|
249
|
+
await writeFile(join(cliDir, 'package.json'), '{ "name": "cli-test" }\n', 'utf-8');
|
|
250
|
+
await writeFile(join(cliDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
251
|
+
await mkdir(join(cliDir, 'node_modules'), { recursive: true });
|
|
252
|
+
await writeFile(join(cliDir, 'node_modules', '.yarn-integrity'), 'ok\n', 'utf-8');
|
|
253
|
+
|
|
254
|
+
const distIndex = join(cliDir, 'dist', 'index.mjs');
|
|
255
|
+
await mkdir(dirname(distIndex), { recursive: true });
|
|
256
|
+
await writeFile(distIndex, 'export const stable = true;\n', 'utf-8');
|
|
257
|
+
|
|
258
|
+
const binDir = join(root, 'bin');
|
|
259
|
+
const outputPath = join(root, 'argv.txt');
|
|
260
|
+
await writeYarnBuildFailAfterDeletingDistStub({ binDir, outputPath });
|
|
261
|
+
|
|
262
|
+
applyEnvOverrides(t, {
|
|
263
|
+
PATH: `${binDir}:/usr/bin:/bin`,
|
|
264
|
+
OUTPUT_PATH: outputPath,
|
|
265
|
+
HAPPIER_STACK_CLI_BUILD_MODE: 'always',
|
|
266
|
+
HAPPIER_STACK_ENV_FILE: null,
|
|
267
|
+
});
|
|
268
|
+
await assert.rejects(
|
|
269
|
+
() => ensureCliBuilt(cliDir, { buildCli: true, quiet: true }),
|
|
270
|
+
);
|
|
271
|
+
const restored = await readFile(distIndex, 'utf-8');
|
|
272
|
+
assert.equal(restored, 'export const stable = true;\n');
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
test('ensureCliBuilt restores dist from .dist.hstack-backup when previous build was interrupted', async (t) => {
|
|
276
|
+
const root = await mkdtemp(join(tmpdir(), 'hs-pm-cli-build-interrupted-'));
|
|
277
|
+
t.after(async () => {
|
|
278
|
+
await rm(root, { recursive: true, force: true });
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
const cliDir = join(root, 'apps', 'cli');
|
|
282
|
+
await mkdir(cliDir, { recursive: true });
|
|
283
|
+
await writeFile(join(cliDir, 'package.json'), '{ "name": "cli-test" }\n', 'utf-8');
|
|
284
|
+
await writeFile(join(cliDir, 'yarn.lock'), '# yarn\n', 'utf-8');
|
|
285
|
+
await mkdir(join(cliDir, 'node_modules'), { recursive: true });
|
|
286
|
+
await writeFile(join(cliDir, 'node_modules', '.yarn-integrity'), 'ok\n', 'utf-8');
|
|
287
|
+
|
|
288
|
+
// Simulate: dist/ was moved out of the way to .dist.hstack-backup/, then the build process
|
|
289
|
+
// was killed before it restored dist/. Next run should recover without invoking `yarn build`.
|
|
290
|
+
const distBackupDir = join(cliDir, '.dist.hstack-backup');
|
|
291
|
+
const backupIndex = join(distBackupDir, 'index.mjs');
|
|
292
|
+
await mkdir(dirname(backupIndex), { recursive: true });
|
|
293
|
+
await writeFile(backupIndex, 'export const stable = true;\n', 'utf-8');
|
|
294
|
+
|
|
295
|
+
const binDir = join(root, 'bin');
|
|
296
|
+
const outputPath = join(root, 'argv.txt');
|
|
297
|
+
await writeYarnArgDumpStub({ binDir, outputPath });
|
|
298
|
+
|
|
299
|
+
applyEnvOverrides(t, {
|
|
300
|
+
PATH: `${binDir}:/usr/bin:/bin`,
|
|
301
|
+
OUTPUT_PATH: outputPath,
|
|
302
|
+
HAPPIER_STACK_CLI_BUILD_MODE: 'auto',
|
|
303
|
+
HAPPIER_STACK_ENV_FILE: null,
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
await ensureCliBuilt(cliDir, { buildCli: true, quiet: true });
|
|
307
|
+
|
|
308
|
+
const distIndex = join(cliDir, 'dist', 'index.mjs');
|
|
309
|
+
const recovered = await readFile(distIndex, 'utf-8');
|
|
310
|
+
assert.equal(recovered, 'export const stable = true;\n');
|
|
311
|
+
const argv = await readFile(outputPath, 'utf-8');
|
|
312
|
+
assert.ok(!argv.includes('build'), `expected no build invocation, got: ${argv}`);
|
|
313
|
+
});
|