@happier-dev/stack 0.1.0-preview.17.1 → 0.1.0-preview.21.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/docs/server-flavors.md +6 -6
- package/node_modules/@happier-dev/cli-common/dist/index.d.ts +2 -0
- package/node_modules/@happier-dev/cli-common/dist/index.d.ts.map +1 -1
- package/node_modules/@happier-dev/cli-common/dist/index.js +2 -0
- package/node_modules/@happier-dev/cli-common/dist/index.js.map +1 -1
- package/node_modules/@happier-dev/cli-common/dist/providers/index.d.ts +51 -0
- package/node_modules/@happier-dev/cli-common/dist/providers/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/providers/index.js +129 -0
- package/node_modules/@happier-dev/cli-common/dist/providers/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/index.d.ts +5 -0
- package/node_modules/@happier-dev/cli-common/dist/service/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/index.js +5 -0
- package/node_modules/@happier-dev/cli-common/dist/service/index.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/launchd.d.ts +19 -0
- package/node_modules/@happier-dev/cli-common/dist/service/launchd.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/launchd.js +117 -0
- package/node_modules/@happier-dev/cli-common/dist/service/launchd.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/manager.d.ts +55 -0
- package/node_modules/@happier-dev/cli-common/dist/service/manager.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/manager.js +302 -0
- package/node_modules/@happier-dev/cli-common/dist/service/manager.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/systemd.d.ts +12 -0
- package/node_modules/@happier-dev/cli-common/dist/service/systemd.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/systemd.js +75 -0
- package/node_modules/@happier-dev/cli-common/dist/service/systemd.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/windows.d.ts +8 -0
- package/node_modules/@happier-dev/cli-common/dist/service/windows.d.ts.map +1 -0
- package/node_modules/@happier-dev/cli-common/dist/service/windows.js +29 -0
- package/node_modules/@happier-dev/cli-common/dist/service/windows.js.map +1 -0
- package/node_modules/@happier-dev/cli-common/package.json +11 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.d.ts +22 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.js +44 -0
- package/node_modules/@happier-dev/release-runtime/dist/assets.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.d.ts +5 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.js +21 -0
- package/node_modules/@happier-dev/release-runtime/dist/checksums.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.d.ts +14 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.js +39 -0
- package/node_modules/@happier-dev/release-runtime/dist/extractPlan.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.d.ts +20 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.js +60 -0
- package/node_modules/@happier-dev/release-runtime/dist/github.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.d.ts +7 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.js +7 -0
- package/node_modules/@happier-dev/release-runtime/dist/index.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.d.ts +7 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.js +92 -0
- package/node_modules/@happier-dev/release-runtime/dist/minisign.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.d.ts +26 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.d.ts.map +1 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.js +53 -0
- package/node_modules/@happier-dev/release-runtime/dist/verifiedDownload.js.map +1 -0
- package/node_modules/@happier-dev/release-runtime/package.json +38 -0
- package/package.json +4 -2
- package/scripts/auth.mjs +3 -2
- package/scripts/auth_copy_from_pglite_lock_in_use.integration.test.mjs +1 -0
- package/scripts/auth_copy_from_runCapture.integration.test.mjs +8 -1
- package/scripts/auth_login_guided_server_no_expo.test.mjs +2 -0
- package/scripts/build.mjs +3 -18
- package/scripts/bundleWorkspaceDeps.mjs +5 -1
- package/scripts/bundleWorkspaceDeps.test.mjs +42 -1
- package/scripts/mobile.mjs +30 -2
- package/scripts/mobile_dev_client.mjs +7 -32
- package/scripts/mobile_dev_client_help_smoke.test.mjs +24 -0
- package/scripts/mobile_prebuild_happyDir_defined.test.mjs +47 -0
- package/scripts/mobile_prebuild_sets_rct_metro_port.test.mjs +81 -0
- package/scripts/mobile_run_ios_passes_port.integration.test.mjs +103 -0
- package/scripts/mobile_run_ios_uses_long_port_flag.test.mjs +106 -0
- package/scripts/providers_cmd.mjs +262 -0
- package/scripts/release_binary_smoke.integration.test.mjs +45 -37
- package/scripts/remote_cmd.mjs +352 -0
- package/scripts/self_host_daemon.real.integration.test.mjs +296 -0
- package/scripts/self_host_launchd.real.integration.test.mjs +211 -0
- package/scripts/self_host_runtime.mjs +1829 -327
- package/scripts/self_host_runtime.test.mjs +523 -1
- package/scripts/self_host_schtasks.real.integration.test.mjs +217 -0
- package/scripts/self_host_service_e2e_harness.mjs +93 -0
- package/scripts/self_host_systemd.real.integration.test.mjs +8 -86
- package/scripts/service.mjs +156 -26
- package/scripts/stack/command_arguments.mjs +1 -0
- package/scripts/stack/help_text.mjs +3 -1
- package/scripts/stack.mjs +2 -1
- package/scripts/stack_daemon_cmd.integration.test.mjs +37 -0
- package/scripts/stack_happy_cmd.integration.test.mjs +36 -0
- package/scripts/stack_pr_help_cmd.test.mjs +38 -0
- package/scripts/stop.mjs +2 -3
- package/scripts/utils/auth/credentials_paths.mjs +9 -9
- package/scripts/utils/auth/credentials_paths.test.mjs +8 -0
- package/scripts/utils/auth/orchestrated_stack_auth_flow.mjs +64 -3
- package/scripts/utils/auth/stable_scope_id.mjs +1 -1
- package/scripts/utils/cli/cli_registry.mjs +21 -0
- package/scripts/utils/cli/progress.mjs +8 -1
- package/scripts/utils/cli/progress.test.mjs +43 -0
- package/scripts/utils/dev/expo_dev.buildEnv.test.mjs +17 -0
- package/scripts/utils/dev/expo_dev.mjs +35 -5
- package/scripts/utils/dev/expo_dev_restart_port_reservation.test.mjs +180 -1
- package/scripts/utils/dev/expo_dev_runtime_metadata.test.mjs +126 -0
- package/scripts/utils/dev/expo_dev_verbose_logs.test.mjs +9 -2
- package/scripts/utils/mobile/dev_client_install_invocation.mjs +68 -0
- package/scripts/utils/mobile/dev_client_install_invocation.test.mjs +27 -0
- package/scripts/utils/server/port.mjs +20 -2
- package/scripts/utils/service/service_manager.definition.test.mjs +66 -0
- package/scripts/utils/service/service_manager.mjs +96 -0
- package/scripts/utils/service/service_manager.plan.test.mjs +37 -0
- package/scripts/utils/service/service_manager.test.mjs +20 -0
- package/scripts/utils/service/systemd_service_unit.mjs +1 -0
- package/scripts/utils/service/systemd_service_unit.test.mjs +42 -0
- package/scripts/utils/service/windows_schtasks_wrapper.mjs +1 -0
- package/scripts/utils/service/windows_schtasks_wrapper.test.mjs +25 -0
- package/scripts/utils/ui/ui_export_env.mjs +29 -0
- package/scripts/utils/ui/ui_export_env.test.mjs +25 -0
- package/scripts/worktrees.mjs +3 -0
- package/scripts/worktrees_status_default_target.test.mjs +56 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import assert from 'node:assert/strict';
|
|
2
|
+
import { chmod, cp, mkdir, mkdtemp, rm } from 'node:fs/promises';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join, resolve } from 'node:path';
|
|
5
|
+
import test from 'node:test';
|
|
6
|
+
import { fileURLToPath } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const SELF_HOST_INSTALL_TIMEOUT_MS = 420_000;
|
|
9
|
+
|
|
10
|
+
import { commandExists, extractBinaryFromArtifact, reserveLocalhostPort, run, waitForHealth } from './self_host_service_e2e_harness.mjs';
|
|
11
|
+
|
|
12
|
+
function currentTarget() {
|
|
13
|
+
if (process.platform !== 'darwin') return '';
|
|
14
|
+
if (process.arch === 'x64') return 'darwin-x64';
|
|
15
|
+
if (process.arch === 'arm64') return 'darwin-arm64';
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function launchctlPrintTarget(label) {
|
|
20
|
+
const uid = typeof process.getuid === 'function' ? process.getuid() : null;
|
|
21
|
+
return uid != null ? `gui/${uid}/${label}` : label;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
test(
|
|
25
|
+
'compiled hstack self-host install/uninstall works on macOS launchd host without repo checkout',
|
|
26
|
+
{ timeout: 15 * 60_000 },
|
|
27
|
+
async (t) => {
|
|
28
|
+
if (process.platform !== 'darwin') {
|
|
29
|
+
t.skip(`macos-only test (current: ${process.platform})`);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const target = currentTarget();
|
|
33
|
+
if (!target) {
|
|
34
|
+
t.skip(`unsupported macOS runner architecture: ${process.arch}`);
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
if (!commandExists('launchctl')) {
|
|
38
|
+
t.skip('launchctl is required');
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
if (!commandExists('bun')) {
|
|
42
|
+
t.skip('bun is required to build compiled binaries');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const repoRoot = resolve(fileURLToPath(new URL('../../..', import.meta.url)));
|
|
47
|
+
const version = `0.0.0-launchd.${Date.now()}`;
|
|
48
|
+
|
|
49
|
+
run(
|
|
50
|
+
process.execPath,
|
|
51
|
+
[
|
|
52
|
+
'scripts/release/build-hstack-binaries.mjs',
|
|
53
|
+
'--channel=preview',
|
|
54
|
+
`--version=${version}`,
|
|
55
|
+
`--targets=${target}`,
|
|
56
|
+
],
|
|
57
|
+
{
|
|
58
|
+
label: 'self-host-launchd',
|
|
59
|
+
cwd: repoRoot,
|
|
60
|
+
env: { ...process.env },
|
|
61
|
+
timeoutMs: 8 * 60_000,
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
run(
|
|
65
|
+
process.execPath,
|
|
66
|
+
[
|
|
67
|
+
'scripts/release/build-server-binaries.mjs',
|
|
68
|
+
'--channel=preview',
|
|
69
|
+
`--version=${version}`,
|
|
70
|
+
`--targets=${target}`,
|
|
71
|
+
],
|
|
72
|
+
{
|
|
73
|
+
label: 'self-host-launchd',
|
|
74
|
+
cwd: repoRoot,
|
|
75
|
+
env: { ...process.env },
|
|
76
|
+
timeoutMs: 8 * 60_000,
|
|
77
|
+
}
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
const hstackArtifact = join(repoRoot, 'dist', 'release-assets', 'stack', `hstack-v${version}-${target}.tar.gz`);
|
|
81
|
+
const serverArtifact = join(repoRoot, 'dist', 'release-assets', 'server', `happier-server-v${version}-${target}.tar.gz`);
|
|
82
|
+
|
|
83
|
+
const extractedHstack = await extractBinaryFromArtifact({ label: 'self-host-launchd', artifactPath: hstackArtifact, binaryName: 'hstack' });
|
|
84
|
+
const extractedServer = await extractBinaryFromArtifact({ label: 'self-host-launchd', artifactPath: serverArtifact, binaryName: 'happier-server' });
|
|
85
|
+
|
|
86
|
+
t.after(async () => {
|
|
87
|
+
await rm(extractedHstack.extractDir, { recursive: true, force: true });
|
|
88
|
+
await rm(extractedServer.extractDir, { recursive: true, force: true });
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
const sandboxDir = await mkdtemp(join(tmpdir(), 'happier-self-host-launchd-'));
|
|
92
|
+
t.after(async () => {
|
|
93
|
+
await rm(sandboxDir, { recursive: true, force: true });
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
const installRoot = join(sandboxDir, 'self-host');
|
|
97
|
+
const binDir = join(sandboxDir, 'bin');
|
|
98
|
+
const configDir = join(sandboxDir, 'config');
|
|
99
|
+
const dataDir = join(sandboxDir, 'data');
|
|
100
|
+
const logDir = join(sandboxDir, 'logs');
|
|
101
|
+
await mkdir(binDir, { recursive: true });
|
|
102
|
+
|
|
103
|
+
const hstackPath = join(binDir, 'hstack');
|
|
104
|
+
await cp(extractedHstack.binaryPath, hstackPath);
|
|
105
|
+
await chmod(hstackPath, 0o755);
|
|
106
|
+
|
|
107
|
+
const serviceName = `happier-server-e2e-${Date.now().toString(36).slice(-6)}`;
|
|
108
|
+
const serverPort = await reserveLocalhostPort();
|
|
109
|
+
const commonEnv = {
|
|
110
|
+
PATH: process.env.PATH ?? '',
|
|
111
|
+
HAPPIER_SELF_HOST_INSTALL_ROOT: installRoot,
|
|
112
|
+
HAPPIER_SELF_HOST_BIN_DIR: binDir,
|
|
113
|
+
HAPPIER_SELF_HOST_CONFIG_DIR: configDir,
|
|
114
|
+
HAPPIER_SELF_HOST_DATA_DIR: dataDir,
|
|
115
|
+
HAPPIER_SELF_HOST_LOG_DIR: logDir,
|
|
116
|
+
HAPPIER_SELF_HOST_SERVICE_NAME: serviceName,
|
|
117
|
+
HAPPIER_SELF_HOST_SERVER_BINARY: extractedServer.binaryPath,
|
|
118
|
+
HAPPIER_SELF_HOST_AUTO_UPDATE: '0',
|
|
119
|
+
HAPPIER_SELF_HOST_HEALTH_TIMEOUT_MS: '240000',
|
|
120
|
+
HAPPIER_NONINTERACTIVE: '1',
|
|
121
|
+
HAPPIER_WITH_CLI: '0',
|
|
122
|
+
HAPPIER_SERVER_PORT: String(serverPort),
|
|
123
|
+
HAPPIER_SERVER_HOST: '127.0.0.1',
|
|
124
|
+
};
|
|
125
|
+
const serverOutLog = join(logDir, 'server.out.log');
|
|
126
|
+
const serverErrLog = join(logDir, 'server.err.log');
|
|
127
|
+
|
|
128
|
+
let installSucceeded = false;
|
|
129
|
+
t.after(() => {
|
|
130
|
+
if (!installSucceeded) return;
|
|
131
|
+
run(
|
|
132
|
+
hstackPath,
|
|
133
|
+
['self-host', 'uninstall', '--channel=preview', '--mode=user', '--yes', '--purge-data', '--json'],
|
|
134
|
+
{
|
|
135
|
+
env: commonEnv,
|
|
136
|
+
allowFail: true,
|
|
137
|
+
timeoutMs: 120_000,
|
|
138
|
+
stdio: 'ignore',
|
|
139
|
+
cwd: sandboxDir,
|
|
140
|
+
}
|
|
141
|
+
);
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
const installResult = run(
|
|
145
|
+
hstackPath,
|
|
146
|
+
['self-host', 'install', '--channel=preview', '--mode=user', '--no-auto-update', '--non-interactive', '--without-cli', '--json'],
|
|
147
|
+
{
|
|
148
|
+
label: 'self-host-launchd',
|
|
149
|
+
env: commonEnv,
|
|
150
|
+
timeoutMs: SELF_HOST_INSTALL_TIMEOUT_MS,
|
|
151
|
+
allowFail: true,
|
|
152
|
+
cwd: sandboxDir,
|
|
153
|
+
}
|
|
154
|
+
);
|
|
155
|
+
if ((installResult.status ?? 1) !== 0) {
|
|
156
|
+
const recoveredHealth = await waitForHealth(`http://127.0.0.1:${serverPort}/v1/version`, 120_000);
|
|
157
|
+
if (!recoveredHealth) {
|
|
158
|
+
const statusResult = run(
|
|
159
|
+
hstackPath,
|
|
160
|
+
['self-host', 'status', '--channel=preview', '--mode=user', '--json'],
|
|
161
|
+
{ label: 'self-host-launchd', env: commonEnv, allowFail: true, timeoutMs: 45_000, cwd: sandboxDir }
|
|
162
|
+
);
|
|
163
|
+
const launchctlList = run('launchctl', ['list'], { label: 'self-host-launchd', allowFail: true, timeoutMs: 20_000 });
|
|
164
|
+
const launchctlPrint = run('launchctl', ['print', launchctlPrintTarget(serviceName)], { label: 'self-host-launchd', allowFail: true, timeoutMs: 20_000 });
|
|
165
|
+
const outTail = run('tail', ['-n', '200', serverOutLog], { label: 'self-host-launchd', allowFail: true, timeoutMs: 10_000 });
|
|
166
|
+
const errTail = run('tail', ['-n', '200', serverErrLog], { label: 'self-host-launchd', allowFail: true, timeoutMs: 10_000 });
|
|
167
|
+
throw new Error(
|
|
168
|
+
[
|
|
169
|
+
'[self-host-launchd] self-host install failed and service never became healthy',
|
|
170
|
+
`install status: ${String(installResult.status ?? 'null')}`,
|
|
171
|
+
`install stdout:\n${String(installResult.stdout ?? '').trim()}`,
|
|
172
|
+
`install stderr:\n${String(installResult.stderr ?? '').trim()}`,
|
|
173
|
+
`self-host status:\n${String(statusResult.stdout ?? '').trim()}\n${String(statusResult.stderr ?? '').trim()}`,
|
|
174
|
+
`launchctl list:\n${String(launchctlList.stdout ?? '').trim()}\n${String(launchctlList.stderr ?? '').trim()}`,
|
|
175
|
+
`launchctl print:\n${String(launchctlPrint.stdout ?? '').trim()}\n${String(launchctlPrint.stderr ?? '').trim()}`,
|
|
176
|
+
`server out tail (${serverOutLog}):\n${String(outTail.stdout ?? '').trim()}\n${String(outTail.stderr ?? '').trim()}`,
|
|
177
|
+
`server err tail (${serverErrLog}):\n${String(errTail.stdout ?? '').trim()}\n${String(errTail.stderr ?? '').trim()}`,
|
|
178
|
+
].join('\n\n')
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
installSucceeded = true;
|
|
183
|
+
|
|
184
|
+
const healthOk = await waitForHealth(`http://127.0.0.1:${serverPort}/v1/version`, 90_000);
|
|
185
|
+
assert.equal(healthOk, true, 'self-host service health endpoint did not become ready');
|
|
186
|
+
|
|
187
|
+
const status = run(
|
|
188
|
+
hstackPath,
|
|
189
|
+
['self-host', 'status', '--channel=preview', '--mode=user', '--json'],
|
|
190
|
+
{ label: 'self-host-launchd', env: commonEnv, timeoutMs: 60_000, cwd: sandboxDir }
|
|
191
|
+
);
|
|
192
|
+
const statusPayload = JSON.parse(String(status.stdout ?? '').trim());
|
|
193
|
+
assert.equal(statusPayload?.ok, true);
|
|
194
|
+
assert.equal(statusPayload?.service?.name, serviceName);
|
|
195
|
+
assert.equal(statusPayload?.service?.active, true);
|
|
196
|
+
assert.equal(statusPayload?.healthy, true);
|
|
197
|
+
|
|
198
|
+
const launchctlPrintAfter = run('launchctl', ['print', launchctlPrintTarget(serviceName)], { label: 'self-host-launchd', allowFail: true, timeoutMs: 20_000 });
|
|
199
|
+
assert.equal(launchctlPrintAfter.status, 0, 'launchctl print should succeed after install');
|
|
200
|
+
|
|
201
|
+
run(
|
|
202
|
+
hstackPath,
|
|
203
|
+
['self-host', 'uninstall', '--channel=preview', '--mode=user', '--yes', '--purge-data', '--json'],
|
|
204
|
+
{ label: 'self-host-launchd', env: commonEnv, timeoutMs: 120_000, cwd: sandboxDir }
|
|
205
|
+
);
|
|
206
|
+
installSucceeded = false;
|
|
207
|
+
|
|
208
|
+
const launchctlPrintAfterUninstall = run('launchctl', ['print', launchctlPrintTarget(serviceName)], { label: 'self-host-launchd', allowFail: true, timeoutMs: 20_000 });
|
|
209
|
+
assert.notEqual(launchctlPrintAfterUninstall.status, 0, 'service should not remain registered after uninstall');
|
|
210
|
+
}
|
|
211
|
+
);
|