@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
package/scripts/eas.mjs
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import './utils/env/env.mjs';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { parseArgs } from './utils/cli/args.mjs';
|
|
5
|
+
import { printResult, wantsHelp, wantsJson } from './utils/cli/cli.mjs';
|
|
6
|
+
import { getFlagValue } from './utils/cli/arg_values.mjs';
|
|
7
|
+
import { getComponentDir, getComponentRepoDir, getRootDir } from './utils/paths/paths.mjs';
|
|
8
|
+
import { ensureDepsInstalled, requireDir } from './utils/proc/pm.mjs';
|
|
9
|
+
import { run, runCaptureResult } from './utils/proc/proc.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Thin wrapper around EAS CLI that:
|
|
13
|
+
* - runs under stack env (stack wrapper sets HAPPIER_STACK_ENV_FILE)
|
|
14
|
+
* - ensures the Happy monorepo deps are installed (so app.config.js can be evaluated)
|
|
15
|
+
* - runs EAS from apps/ui (the mobile app)
|
|
16
|
+
*
|
|
17
|
+
* Notes:
|
|
18
|
+
* - We intentionally use `npx --yes eas-cli@latest` to avoid interactive "Ok to proceed? (y)" prompts.
|
|
19
|
+
* - Cloud builds will only see env vars that EAS knows about (eas.json env, EAS project vars).
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
function normalizePlatform(raw) {
|
|
23
|
+
const v = String(raw ?? '').trim().toLowerCase();
|
|
24
|
+
if (!v) return 'ios';
|
|
25
|
+
if (v === 'ios' || v === 'android' || v === 'all') return v;
|
|
26
|
+
return 'ios';
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getNpxRunner() {
|
|
30
|
+
// In stack mode, the environment may not include the user's interactive shell PATH,
|
|
31
|
+
// so spawning "npx" by name can fail with ENOENT even though Node is present.
|
|
32
|
+
//
|
|
33
|
+
// Additionally, the nvm "npx" shim is a script with a shebang (#!/usr/bin/env node).
|
|
34
|
+
// Some sanitized environments can cause that to fail at exec time. To make this robust,
|
|
35
|
+
// prefer invoking the npx CLI JS file directly via the current Node executable.
|
|
36
|
+
const binDir = dirname(process.execPath);
|
|
37
|
+
|
|
38
|
+
// Typical nvm/npm layout:
|
|
39
|
+
// <prefix>/bin/node
|
|
40
|
+
// <prefix>/lib/node_modules/npm/bin/npx-cli.js
|
|
41
|
+
const npxCliPath = join(binDir, '..', 'lib', 'node_modules', 'npm', 'bin', 'npx-cli.js');
|
|
42
|
+
if (existsSync(npxCliPath)) {
|
|
43
|
+
return { cmd: process.execPath, prefixArgs: [npxCliPath] };
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Fallbacks (best-effort).
|
|
47
|
+
const npxBins = [join(binDir, 'npx'), join(binDir, 'npx.cmd'), join(binDir, 'npx.ps1')];
|
|
48
|
+
for (const p of npxBins) {
|
|
49
|
+
if (existsSync(p)) return { cmd: p, prefixArgs: [] };
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return { cmd: 'npx', prefixArgs: [] };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function normalizeEasEnvironment(raw) {
|
|
56
|
+
const v = String(raw ?? '').trim();
|
|
57
|
+
return v || 'production';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function normalizeCsvList(raw) {
|
|
61
|
+
const v = String(raw ?? '').trim();
|
|
62
|
+
if (!v) return [];
|
|
63
|
+
return v
|
|
64
|
+
.split(',')
|
|
65
|
+
.map((s) => s.trim())
|
|
66
|
+
.filter(Boolean);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function buildExpoEnvSyncValues(env) {
|
|
70
|
+
const out = new Map();
|
|
71
|
+
|
|
72
|
+
const keys = [
|
|
73
|
+
'EXPO_EAS_PROJECT_ID',
|
|
74
|
+
'EXPO_UPDATES_URL',
|
|
75
|
+
'EXPO_UPDATES_CHANNEL',
|
|
76
|
+
'EXPO_APP_OWNER',
|
|
77
|
+
'EXPO_APP_SLUG',
|
|
78
|
+
'EXPO_APP_NAME',
|
|
79
|
+
'EXPO_APP_BUNDLE_ID',
|
|
80
|
+
'EXPO_APP_SCHEME',
|
|
81
|
+
'EXPO_APP_LINK_HOST',
|
|
82
|
+
'EXPO_IOS_ASSOCIATED_DOMAINS',
|
|
83
|
+
'EXPO_ANDROID_GOOGLE_SERVICES_FILE',
|
|
84
|
+
'EXPO_IOS_GOOGLE_SERVICES_FILE',
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
for (const k of keys) {
|
|
88
|
+
const v = String(env?.[k] ?? '').trim();
|
|
89
|
+
if (v) out.set(k, v);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Small convenience: if the user set EXPO_EAS_PROJECT_ID but not EXPO_UPDATES_URL,
|
|
93
|
+
// default updates URL to u.expo.dev/<projectId>.
|
|
94
|
+
const pid = String(env?.EXPO_EAS_PROJECT_ID ?? '').trim();
|
|
95
|
+
const url = String(env?.EXPO_UPDATES_URL ?? '').trim();
|
|
96
|
+
if (pid && !url) {
|
|
97
|
+
out.set('EXPO_UPDATES_URL', `https://u.expo.dev/${pid}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Normalize CSV vars to the format expected by app.config.js (comma-separated).
|
|
101
|
+
if (out.has('EXPO_IOS_ASSOCIATED_DOMAINS')) {
|
|
102
|
+
out.set('EXPO_IOS_ASSOCIATED_DOMAINS', normalizeCsvList(out.get('EXPO_IOS_ASSOCIATED_DOMAINS')).join(','));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function truncateValueForDisplay(raw, { maxLen = 160 } = {}) {
|
|
109
|
+
const v = String(raw ?? '');
|
|
110
|
+
if (v.length <= maxLen) return v;
|
|
111
|
+
return `${v.slice(0, maxLen)}…`;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
async function main() {
|
|
115
|
+
const argv = process.argv.slice(2);
|
|
116
|
+
const { flags, kv } = parseArgs(argv);
|
|
117
|
+
const json = wantsJson(argv, { flags });
|
|
118
|
+
const testStub = String(process.env.HSTACK_EAS_TEST_STUB ?? '').trim() === '1';
|
|
119
|
+
|
|
120
|
+
const helpText = [
|
|
121
|
+
'[eas] usage:',
|
|
122
|
+
' hstack eas <subcommand> [--json] [-- <args...>]',
|
|
123
|
+
' hstack eas build [--platform=ios|android|all] [--profile=production] [--local] [--wait|--no-wait] [--non-interactive|--interactive] [--json] [-- <extra eas args...>]',
|
|
124
|
+
' hstack eas ios [--profile=production] [--local] [--wait|--no-wait] [--non-interactive|--interactive] [--json] [-- <extra eas build args...>]',
|
|
125
|
+
' hstack eas android [--profile=production] [--local] [--wait|--no-wait] [--non-interactive|--interactive] [--json] [-- <extra eas build args...>]',
|
|
126
|
+
' hstack eas env:sync [--environment=production|preview|development] [--dry-run] [--hide-values] [--visibility=plaintext|sensitive|secret] [--scope=project|account] [--json]',
|
|
127
|
+
'',
|
|
128
|
+
'examples:',
|
|
129
|
+
' hstack stack eas happier build --platform ios --profile production',
|
|
130
|
+
' hstack stack eas happier build --platform ios --profile production --local',
|
|
131
|
+
' hstack stack eas happier ios --profile production',
|
|
132
|
+
' hstack stack eas happier whoami',
|
|
133
|
+
' hstack stack eas happier login',
|
|
134
|
+
' hstack stack eas happier project:init',
|
|
135
|
+
' hstack stack eas happier project:info -- --json',
|
|
136
|
+
' hstack stack eas happier env:sync --environment production',
|
|
137
|
+
'',
|
|
138
|
+
'notes:',
|
|
139
|
+
'- `hstack stack eas <name> ...` automatically loads that stack env.',
|
|
140
|
+
'- For cloud builds, consider setting EXPO_EAS_PROJECT_ID / EXPO_UPDATES_URL in EAS project env too.',
|
|
141
|
+
].join('\n');
|
|
142
|
+
|
|
143
|
+
if (wantsHelp(argv, { flags })) {
|
|
144
|
+
printResult({
|
|
145
|
+
json,
|
|
146
|
+
data: {
|
|
147
|
+
usage:
|
|
148
|
+
'hstack eas <subcommand> [--json] [-- <args...>]',
|
|
149
|
+
},
|
|
150
|
+
text: helpText,
|
|
151
|
+
});
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
const positionals = argv.filter((a) => !a.startsWith('--'));
|
|
156
|
+
const subcmd = (positionals[0] ?? '').trim() || 'help';
|
|
157
|
+
|
|
158
|
+
if (subcmd === 'help') {
|
|
159
|
+
printResult({ json, data: { usage: 'hstack eas build|help' }, text: helpText });
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// Passthrough args after "--" (for any subcommand).
|
|
164
|
+
const sepIdx = argv.indexOf('--');
|
|
165
|
+
const extra = sepIdx === -1 ? [] : argv.slice(sepIdx + 1);
|
|
166
|
+
|
|
167
|
+
// Convenience aliases.
|
|
168
|
+
const isBuildAlias = subcmd === 'ios' || subcmd === 'android';
|
|
169
|
+
const effectiveSubcmd = isBuildAlias ? 'build' : subcmd;
|
|
170
|
+
const aliasPlatform = subcmd === 'ios' ? 'ios' : subcmd === 'android' ? 'android' : '';
|
|
171
|
+
|
|
172
|
+
// Test-only mode: allow exercising argument wiring without invoking npx/eas.
|
|
173
|
+
// This avoids network access + interactive prompts during unit tests.
|
|
174
|
+
if (testStub) {
|
|
175
|
+
if (effectiveSubcmd !== 'build') {
|
|
176
|
+
// For non-build commands, print the forwarded args shape and exit.
|
|
177
|
+
const afterSubcmd = argv.slice(argv.indexOf(subcmd) + 1);
|
|
178
|
+
const trimmed = sepIdx === -1 ? afterSubcmd : afterSubcmd.slice(0, afterSubcmd.indexOf('--'));
|
|
179
|
+
console.log([subcmd, ...trimmed, ...extra].join(' '));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const platform = isBuildAlias ? aliasPlatform : normalizePlatform(getFlagValue({ argv, kv, flag: '--platform' }));
|
|
184
|
+
const profile = String(getFlagValue({ argv, kv, flag: '--profile' }) ?? 'production').trim() || 'production';
|
|
185
|
+
const local = flags.has('--local');
|
|
186
|
+
const wait = flags.has('--wait');
|
|
187
|
+
const noWait = flags.has('--no-wait') || !wait;
|
|
188
|
+
const nonInteractive =
|
|
189
|
+
flags.has('--non-interactive') ? true : flags.has('--interactive') ? false : !Boolean(process.stdin.isTTY);
|
|
190
|
+
|
|
191
|
+
const baseArgs = ['build', '--profile', profile];
|
|
192
|
+
if (platform) baseArgs.push('--platform', platform);
|
|
193
|
+
if (local) baseArgs.push('--local');
|
|
194
|
+
if (noWait) baseArgs.push('--no-wait');
|
|
195
|
+
if (nonInteractive) baseArgs.push('--non-interactive');
|
|
196
|
+
baseArgs.push(...extra);
|
|
197
|
+
|
|
198
|
+
console.log(baseArgs.join(' '));
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
const rootDir = getRootDir(import.meta.url);
|
|
203
|
+
const happyAppDir = getComponentDir(rootDir, 'happier-ui');
|
|
204
|
+
const happyRepoDir = getComponentRepoDir(rootDir, 'happier-ui');
|
|
205
|
+
await requireDir('happier-ui', happyRepoDir);
|
|
206
|
+
|
|
207
|
+
// Ensure repo deps exist so app.config.js can be evaluated (plugins import @expo/config-plugins, etc).
|
|
208
|
+
await ensureDepsInstalled(happyRepoDir, 'happier-ui');
|
|
209
|
+
|
|
210
|
+
const { cmd: npxCmd, prefixArgs: npxPrefixArgs } = getNpxRunner();
|
|
211
|
+
|
|
212
|
+
async function easCapture(args, { cwd } = {}) {
|
|
213
|
+
return await runCaptureResult(
|
|
214
|
+
npxCmd,
|
|
215
|
+
[...npxPrefixArgs, '--yes', 'eas-cli@latest', ...args],
|
|
216
|
+
{ cwd: cwd ?? happyAppDir, env: process.env }
|
|
217
|
+
);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
async function easRun(args, { cwd } = {}) {
|
|
221
|
+
await run(npxCmd, [...npxPrefixArgs, '--yes', 'eas-cli@latest', ...args], {
|
|
222
|
+
cwd: cwd ?? happyAppDir,
|
|
223
|
+
env: process.env,
|
|
224
|
+
stdio: 'inherit',
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
if (effectiveSubcmd === 'env:sync') {
|
|
229
|
+
const environment = normalizeEasEnvironment(
|
|
230
|
+
getFlagValue({ argv, kv, flag: '--environment' }) ?? getFlagValue({ argv, kv, flag: '--env' })
|
|
231
|
+
);
|
|
232
|
+
const visibilityRaw = String(getFlagValue({ argv, kv, flag: '--visibility' }) ?? '').trim();
|
|
233
|
+
const visibility = visibilityRaw || 'plaintext';
|
|
234
|
+
const scopeRaw = String(getFlagValue({ argv, kv, flag: '--scope' }) ?? '').trim();
|
|
235
|
+
const scope = scopeRaw || 'project';
|
|
236
|
+
const dryRun = flags.has('--dry-run');
|
|
237
|
+
const showValues = !flags.has('--hide-values');
|
|
238
|
+
|
|
239
|
+
const values = buildExpoEnvSyncValues(process.env);
|
|
240
|
+
if (values.size === 0) {
|
|
241
|
+
const msg =
|
|
242
|
+
`[eas] env:sync: no EXPO_* values found in the current environment.\n` +
|
|
243
|
+
`Set EXPO_EAS_PROJECT_ID / EXPO_UPDATES_URL / EXPO_APP_* in your stack env, then re-run.`;
|
|
244
|
+
printResult({ json, data: { ok: false, reason: 'no_values' }, text: msg });
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
const results = [];
|
|
249
|
+
for (const [name, value] of values.entries()) {
|
|
250
|
+
if (dryRun) {
|
|
251
|
+
results.push({
|
|
252
|
+
name,
|
|
253
|
+
action: 'dry-run',
|
|
254
|
+
ok: true,
|
|
255
|
+
...(showValues ? { value: truncateValueForDisplay(value) } : {}),
|
|
256
|
+
});
|
|
257
|
+
continue;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
// Prefer update (idempotent-ish), then fall back to create.
|
|
261
|
+
const update = await easCapture([
|
|
262
|
+
'env:update',
|
|
263
|
+
'--environment',
|
|
264
|
+
environment,
|
|
265
|
+
'--variable-name',
|
|
266
|
+
name,
|
|
267
|
+
'--value',
|
|
268
|
+
value,
|
|
269
|
+
'--visibility',
|
|
270
|
+
visibility,
|
|
271
|
+
'--scope',
|
|
272
|
+
scope,
|
|
273
|
+
'--non-interactive',
|
|
274
|
+
]);
|
|
275
|
+
if (update.ok) {
|
|
276
|
+
results.push({ name, action: 'updated', ok: true });
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
const create = await easCapture([
|
|
281
|
+
'env:create',
|
|
282
|
+
'--environment',
|
|
283
|
+
environment,
|
|
284
|
+
'--name',
|
|
285
|
+
name,
|
|
286
|
+
'--value',
|
|
287
|
+
value,
|
|
288
|
+
'--type',
|
|
289
|
+
'string',
|
|
290
|
+
'--visibility',
|
|
291
|
+
visibility,
|
|
292
|
+
'--scope',
|
|
293
|
+
scope,
|
|
294
|
+
'--non-interactive',
|
|
295
|
+
]);
|
|
296
|
+
if (create.ok) {
|
|
297
|
+
results.push({ name, action: 'created', ok: true });
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
results.push({
|
|
302
|
+
name,
|
|
303
|
+
action: 'failed',
|
|
304
|
+
ok: false,
|
|
305
|
+
updateErr: update.err?.trim?.() ?? String(update.err ?? ''),
|
|
306
|
+
createErr: create.err?.trim?.() ?? String(create.err ?? ''),
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Fail fast on the first failure (likely auth/permissions).
|
|
310
|
+
const details = [
|
|
311
|
+
`[eas] env:sync failed for ${name} (environment=${environment})`,
|
|
312
|
+
update.err ? `- env:update: ${String(update.err).trim()}` : '- env:update: (no stderr captured)',
|
|
313
|
+
create.err ? `- env:create: ${String(create.err).trim()}` : '- env:create: (no stderr captured)',
|
|
314
|
+
].join('\n');
|
|
315
|
+
throw new Error(details);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const ok = results.every((r) => r.ok);
|
|
319
|
+
printResult({
|
|
320
|
+
json,
|
|
321
|
+
data: { ok, environment, results },
|
|
322
|
+
text:
|
|
323
|
+
`[eas] env:sync ${ok ? 'ok' : 'failed'} (environment=${environment})\n` +
|
|
324
|
+
results
|
|
325
|
+
.map((r) => {
|
|
326
|
+
const suffix =
|
|
327
|
+
r.action === 'dry-run' && showValues && typeof r.value === 'string' ? ` = ${r.value}` : '';
|
|
328
|
+
return `- ${r.name}: ${r.action}${suffix}`;
|
|
329
|
+
})
|
|
330
|
+
.join('\n'),
|
|
331
|
+
});
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Non-build subcommands (login/whoami/project:init/etc): forward directly.
|
|
336
|
+
if (effectiveSubcmd !== 'build') {
|
|
337
|
+
// Forward everything after the first positional token, excluding "--" and its args (we append those as `extra`).
|
|
338
|
+
const afterSubcmd = argv.slice(argv.indexOf(subcmd) + 1);
|
|
339
|
+
const trimmed = sepIdx === -1 ? afterSubcmd : afterSubcmd.slice(0, afterSubcmd.indexOf('--'));
|
|
340
|
+
await easRun([subcmd, ...trimmed, ...extra]);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
const platform = isBuildAlias ? aliasPlatform : normalizePlatform(getFlagValue({ argv, kv, flag: '--platform' }));
|
|
345
|
+
const profile = String(getFlagValue({ argv, kv, flag: '--profile' }) ?? 'production').trim() || 'production';
|
|
346
|
+
const local = flags.has('--local');
|
|
347
|
+
const wait = flags.has('--wait');
|
|
348
|
+
const noWait = flags.has('--no-wait') || !wait;
|
|
349
|
+
// Default to interactive when we have a TTY (so first-time credentials setup works),
|
|
350
|
+
// but allow forcing either mode explicitly.
|
|
351
|
+
const nonInteractive =
|
|
352
|
+
flags.has('--non-interactive') ? true : flags.has('--interactive') ? false : !Boolean(process.stdin.isTTY);
|
|
353
|
+
|
|
354
|
+
const baseArgs = ['build', '--profile', profile];
|
|
355
|
+
if (platform) baseArgs.push('--platform', platform);
|
|
356
|
+
if (local) baseArgs.push('--local');
|
|
357
|
+
if (noWait) baseArgs.push('--no-wait');
|
|
358
|
+
if (nonInteractive) baseArgs.push('--non-interactive');
|
|
359
|
+
baseArgs.push(...extra);
|
|
360
|
+
|
|
361
|
+
await easRun(baseArgs);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
main().catch((err) => {
|
|
365
|
+
console.error('[eas] failed:', err?.message ?? err);
|
|
366
|
+
process.exit(1);
|
|
367
|
+
});
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
|
|
7
|
+
function runNode(args, { cwd, env } = {}) {
|
|
8
|
+
return new Promise((resolve, reject) => {
|
|
9
|
+
const proc = spawn(process.execPath, args, { cwd, env, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
10
|
+
let stdout = '';
|
|
11
|
+
let stderr = '';
|
|
12
|
+
proc.stdout.on('data', (d) => (stdout += String(d)));
|
|
13
|
+
proc.stderr.on('data', (d) => (stderr += String(d)));
|
|
14
|
+
proc.on('error', reject);
|
|
15
|
+
proc.on('exit', (code, signal) => resolve({ code: code ?? (signal ? 1 : 0), signal: signal ?? null, stdout, stderr }));
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
test('hstack eas build honors space-separated --platform android', async () => {
|
|
20
|
+
const scriptsDir = dirname(fileURLToPath(import.meta.url));
|
|
21
|
+
const rootDir = dirname(scriptsDir);
|
|
22
|
+
|
|
23
|
+
const env = {
|
|
24
|
+
...process.env,
|
|
25
|
+
// Avoid cloning/bootstrapping/stack assumptions; we only want argument wiring.
|
|
26
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_UI: join(rootDir, '..', 'ui'),
|
|
27
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_CLI: join(rootDir, '..', 'cli'),
|
|
28
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_SERVER: join(rootDir, '..', 'server'),
|
|
29
|
+
// Prevent npx/eas from running: use our test stub instead.
|
|
30
|
+
HSTACK_EAS_TEST_STUB: '1',
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const res = await runNode(
|
|
34
|
+
[join(rootDir, 'scripts', 'eas.mjs'), 'build', '--platform', 'android', '--profile', 'production', '--non-interactive'],
|
|
35
|
+
{ cwd: rootDir, env }
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
assert.equal(res.code, 0, `expected exit 0, got ${res.code}\nstdout:\n${res.stdout}\nstderr:\n${res.stderr}`);
|
|
39
|
+
assert.match(res.stdout, /--platform android\b/, `expected forwarded args to include "--platform android"\nstdout:\n${res.stdout}`);
|
|
40
|
+
assert.ok(!res.stdout.includes('--platform ios'), `expected not to default to ios when platform is explicitly set\nstdout:\n${res.stdout}`);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
test('hstack eas build falls back to ios for invalid --platform value', async () => {
|
|
44
|
+
const scriptsDir = dirname(fileURLToPath(import.meta.url));
|
|
45
|
+
const rootDir = dirname(scriptsDir);
|
|
46
|
+
|
|
47
|
+
const env = {
|
|
48
|
+
...process.env,
|
|
49
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_UI: join(rootDir, '..', 'ui'),
|
|
50
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_CLI: join(rootDir, '..', 'cli'),
|
|
51
|
+
HAPPIER_STACKS_COMPONENT_DIR_HAPPIER_SERVER: join(rootDir, '..', 'server'),
|
|
52
|
+
HSTACK_EAS_TEST_STUB: '1',
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const res = await runNode(
|
|
56
|
+
[join(rootDir, 'scripts', 'eas.mjs'), 'build', '--platform', 'invalid-platform', '--profile', 'production'],
|
|
57
|
+
{ cwd: rootDir, env }
|
|
58
|
+
);
|
|
59
|
+
|
|
60
|
+
assert.equal(res.code, 0, `expected exit 0, got ${res.code}\nstdout:\n${res.stdout}\nstderr:\n${res.stderr}`);
|
|
61
|
+
assert.match(res.stdout, /--platform ios\b/, `expected invalid platform to normalize to ios\nstdout:\n${res.stdout}`);
|
|
62
|
+
assert.ok(!res.stdout.includes('--platform invalid-platform'), `expected invalid platform not to be forwarded\nstdout:\n${res.stdout}`);
|
|
63
|
+
});
|