happy-stacks 0.4.0 → 0.5.0
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 +64 -33
- package/bin/happys.mjs +44 -1
- package/docs/codex-mcp-resume.md +130 -0
- package/docs/commit-audits/happy/leeroy-wip.commit-analysis.md +17640 -0
- package/docs/commit-audits/happy/leeroy-wip.commit-export.fuller-stat.md +3845 -0
- package/docs/commit-audits/happy/leeroy-wip.commit-inventory.md +102 -0
- package/docs/commit-audits/happy/leeroy-wip.commit-manual-review.md +1452 -0
- package/docs/commit-audits/happy/leeroy-wip.manual-review-queue.md +116 -0
- package/docs/happy-development.md +1 -2
- package/docs/monorepo-migration.md +286 -0
- package/docs/server-flavors.md +19 -3
- package/docs/stacks.md +35 -0
- package/package.json +1 -1
- package/scripts/auth.mjs +21 -3
- package/scripts/build.mjs +1 -1
- package/scripts/dev.mjs +20 -7
- package/scripts/doctor.mjs +0 -4
- package/scripts/edison.mjs +2 -2
- package/scripts/env.mjs +150 -0
- package/scripts/env_cmd.test.mjs +128 -0
- package/scripts/init.mjs +5 -2
- package/scripts/install.mjs +99 -57
- package/scripts/migrate.mjs +3 -12
- package/scripts/monorepo.mjs +1096 -0
- package/scripts/monorepo_port.test.mjs +1470 -0
- package/scripts/review.mjs +715 -24
- package/scripts/review_pr.mjs +5 -20
- package/scripts/run.mjs +21 -15
- package/scripts/setup.mjs +147 -25
- package/scripts/setup_pr.mjs +19 -28
- package/scripts/stack.mjs +493 -157
- package/scripts/stack_archive_cmd.test.mjs +91 -0
- package/scripts/stack_editor_workspace_monorepo_root.test.mjs +65 -0
- package/scripts/stack_env_cmd.test.mjs +87 -0
- package/scripts/stack_happy_cmd.test.mjs +126 -0
- package/scripts/stack_interactive_monorepo_group.test.mjs +71 -0
- package/scripts/stack_monorepo_defaults.test.mjs +62 -0
- package/scripts/stack_monorepo_server_light_from_happy_spec.test.mjs +66 -0
- package/scripts/stack_server_flavors_defaults.test.mjs +55 -0
- package/scripts/stack_shorthand_cmd.test.mjs +55 -0
- package/scripts/stack_wt_list.test.mjs +128 -0
- package/scripts/tui.mjs +88 -2
- package/scripts/utils/cli/cli_registry.mjs +20 -5
- package/scripts/utils/cli/cwd_scope.mjs +56 -2
- package/scripts/utils/cli/cwd_scope.test.mjs +40 -7
- package/scripts/utils/cli/prereqs.mjs +8 -5
- package/scripts/utils/cli/prereqs.test.mjs +34 -0
- package/scripts/utils/cli/wizard.mjs +17 -9
- package/scripts/utils/cli/wizard_prompt_worktree_source_lazy.test.mjs +60 -0
- package/scripts/utils/dev/daemon.mjs +14 -1
- package/scripts/utils/dev/expo_dev.mjs +188 -4
- package/scripts/utils/dev/server.mjs +21 -17
- package/scripts/utils/edison/git_roots.mjs +29 -0
- package/scripts/utils/edison/git_roots.test.mjs +36 -0
- package/scripts/utils/env/env.mjs +7 -3
- package/scripts/utils/env/env_file.mjs +4 -2
- package/scripts/utils/env/env_file.test.mjs +44 -0
- package/scripts/utils/git/worktrees.mjs +63 -12
- package/scripts/utils/git/worktrees_monorepo.test.mjs +54 -0
- package/scripts/utils/net/tcp_forward.mjs +162 -0
- package/scripts/utils/paths/paths.mjs +118 -3
- package/scripts/utils/paths/paths_monorepo.test.mjs +58 -0
- package/scripts/utils/paths/paths_server_flavors.test.mjs +45 -0
- package/scripts/utils/proc/commands.mjs +2 -3
- package/scripts/utils/proc/pm.mjs +113 -16
- package/scripts/utils/proc/pm_spawn.test.mjs +76 -0
- package/scripts/utils/proc/pm_stack_cache_env.test.mjs +142 -0
- package/scripts/utils/proc/proc.mjs +68 -10
- package/scripts/utils/proc/proc.test.mjs +77 -0
- package/scripts/utils/review/chunks.mjs +55 -0
- package/scripts/utils/review/chunks.test.mjs +51 -0
- package/scripts/utils/review/findings.mjs +165 -0
- package/scripts/utils/review/findings.test.mjs +85 -0
- package/scripts/utils/review/head_slice.mjs +153 -0
- package/scripts/utils/review/head_slice.test.mjs +91 -0
- package/scripts/utils/review/instructions/deep.md +20 -0
- package/scripts/utils/review/runners/coderabbit.mjs +56 -14
- package/scripts/utils/review/runners/coderabbit.test.mjs +59 -0
- package/scripts/utils/review/runners/codex.mjs +32 -22
- package/scripts/utils/review/runners/codex.test.mjs +35 -0
- package/scripts/utils/review/slices.mjs +140 -0
- package/scripts/utils/review/slices.test.mjs +32 -0
- package/scripts/utils/server/flavor_scripts.mjs +98 -0
- package/scripts/utils/server/flavor_scripts.test.mjs +146 -0
- package/scripts/utils/server/prisma_import.mjs +37 -0
- package/scripts/utils/server/prisma_import.test.mjs +70 -0
- package/scripts/utils/server/ui_env.mjs +14 -0
- package/scripts/utils/server/ui_env.test.mjs +46 -0
- package/scripts/utils/server/validate.mjs +53 -16
- package/scripts/utils/server/validate.test.mjs +89 -0
- package/scripts/utils/stack/editor_workspace.mjs +4 -4
- package/scripts/utils/stack/interactive_stack_config.mjs +185 -0
- package/scripts/utils/stack/startup.mjs +113 -13
- package/scripts/utils/stack/startup_server_light_dirs.test.mjs +64 -0
- package/scripts/utils/stack/startup_server_light_generate.test.mjs +70 -0
- package/scripts/utils/stack/startup_server_light_legacy.test.mjs +88 -0
- package/scripts/utils/tailscale/ip.mjs +116 -0
- package/scripts/utils/ui/ansi.mjs +39 -0
- package/scripts/where.mjs +2 -2
- package/scripts/worktrees.mjs +627 -137
- package/scripts/worktrees_archive_cmd.test.mjs +245 -0
- package/scripts/worktrees_cursor_monorepo_root.test.mjs +63 -0
- package/scripts/worktrees_list_specs_no_recurse.test.mjs +33 -0
- package/scripts/worktrees_monorepo_use_group.test.mjs +67 -0
package/scripts/install.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import './utils/env/env.mjs';
|
|
|
2
2
|
import { parseArgs } from './utils/cli/args.mjs';
|
|
3
3
|
import { pathExists } from './utils/fs/fs.mjs';
|
|
4
4
|
import { run, runCapture } from './utils/proc/proc.mjs';
|
|
5
|
-
import { getComponentDir, getRootDir } from './utils/paths/paths.mjs';
|
|
5
|
+
import { getComponentDir, getComponentRepoDir, getRootDir, isHappyMonorepoRoot } from './utils/paths/paths.mjs';
|
|
6
6
|
import { getServerComponentName } from './utils/server/server.mjs';
|
|
7
7
|
import { ensureCliBuilt, ensureDepsInstalled, ensureHappyCliLocalNpmLinked } from './utils/proc/pm.mjs';
|
|
8
8
|
import { dirname, join } from 'node:path';
|
|
@@ -12,6 +12,7 @@ import { printResult, wantsHelp, wantsJson } from './utils/cli/cli.mjs';
|
|
|
12
12
|
import { ensureEnvLocalUpdated } from './utils/env/env_local.mjs';
|
|
13
13
|
import { isTty, prompt, promptSelect, withRl } from './utils/cli/wizard.mjs';
|
|
14
14
|
import { isSandboxed, sandboxAllowsGlobalSideEffects } from './utils/env/sandbox.mjs';
|
|
15
|
+
import { bold, cyan, dim } from './utils/ui/ansi.mjs';
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
18
|
* Install/setup the local stack:
|
|
@@ -35,8 +36,12 @@ const DEFAULT_FORK_REPOS = {
|
|
|
35
36
|
const DEFAULT_UPSTREAM_REPOS = {
|
|
36
37
|
// Upstream for server-light lives in the main happy-server repo.
|
|
37
38
|
serverLight: 'https://github.com/slopus/happy-server.git',
|
|
38
|
-
serverFull: 'https://github.com/slopus/happy
|
|
39
|
-
|
|
39
|
+
serverFull: 'https://github.com/slopus/happy.git',
|
|
40
|
+
// slopus/happy is now a monorepo that contains:
|
|
41
|
+
// - expo-app/ (UI)
|
|
42
|
+
// - cli/ (happy-cli)
|
|
43
|
+
// - server/ (happy-server)
|
|
44
|
+
cli: 'https://github.com/slopus/happy.git',
|
|
40
45
|
ui: 'https://github.com/slopus/happy.git',
|
|
41
46
|
};
|
|
42
47
|
|
|
@@ -54,8 +59,8 @@ function repoUrlsFromOwners({ forkOwner, upstreamOwner }) {
|
|
|
54
59
|
upstream: {
|
|
55
60
|
// server-light upstream lives in happy-server
|
|
56
61
|
serverLight: up('happy-server'),
|
|
57
|
-
serverFull: up('happy
|
|
58
|
-
cli: up('happy
|
|
62
|
+
serverFull: up('happy'),
|
|
63
|
+
cli: up('happy'),
|
|
59
64
|
ui: up('happy'),
|
|
60
65
|
},
|
|
61
66
|
};
|
|
@@ -80,12 +85,14 @@ function resolveRepoSource({ flags }) {
|
|
|
80
85
|
|
|
81
86
|
function getRepoUrls({ repoSource }) {
|
|
82
87
|
const defaults = repoSource === 'upstream' ? DEFAULT_UPSTREAM_REPOS : DEFAULT_FORK_REPOS;
|
|
88
|
+
const ui = process.env.HAPPY_LOCAL_UI_REPO_URL?.trim() || defaults.ui;
|
|
83
89
|
return {
|
|
84
90
|
// Backwards compatible: HAPPY_LOCAL_SERVER_REPO_URL historically referred to the server-light component.
|
|
85
91
|
serverLight: process.env.HAPPY_LOCAL_SERVER_LIGHT_REPO_URL?.trim() || process.env.HAPPY_LOCAL_SERVER_REPO_URL?.trim() || defaults.serverLight,
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
92
|
+
// Default to the UI repo when using a monorepo (override to keep split repos).
|
|
93
|
+
serverFull: process.env.HAPPY_LOCAL_SERVER_FULL_REPO_URL?.trim() || defaults.serverFull || ui,
|
|
94
|
+
cli: process.env.HAPPY_LOCAL_CLI_REPO_URL?.trim() || defaults.cli || ui,
|
|
95
|
+
ui,
|
|
89
96
|
};
|
|
90
97
|
}
|
|
91
98
|
|
|
@@ -168,31 +175,33 @@ async function ensureUpstreamRemote({ repoDir, upstreamUrl }) {
|
|
|
168
175
|
async function interactiveWizard({ rootDir, defaults }) {
|
|
169
176
|
return await withRl(async (rl) => {
|
|
170
177
|
const repoSource = await promptSelect(rl, {
|
|
171
|
-
title: '
|
|
178
|
+
title: `${bold('Repo source')}\n${dim('Where should Happy Stacks clone the component repos from?')}`,
|
|
172
179
|
options: [
|
|
173
|
-
{ label:
|
|
174
|
-
{ label:
|
|
180
|
+
{ label: `${cyan('forks')} (default, recommended)`, value: 'forks' },
|
|
181
|
+
{ label: `${cyan('upstream')} (slopus/*)`, value: 'upstream' },
|
|
175
182
|
],
|
|
176
183
|
defaultIndex: defaults.repoSource === 'upstream' ? 1 : 0,
|
|
177
184
|
});
|
|
178
185
|
|
|
186
|
+
// eslint-disable-next-line no-console
|
|
187
|
+
console.log(dim('Tip: keep the defaults unless you maintain your own forks.'));
|
|
179
188
|
const forkOwner = await prompt(rl, `GitHub fork owner (default: ${defaults.forkOwner}): `, { defaultValue: defaults.forkOwner });
|
|
180
189
|
const upstreamOwner = await prompt(rl, `GitHub upstream owner (default: ${defaults.upstreamOwner}): `, {
|
|
181
190
|
defaultValue: defaults.upstreamOwner,
|
|
182
191
|
});
|
|
183
192
|
|
|
184
193
|
const serverMode = await promptSelect(rl, {
|
|
185
|
-
title: '
|
|
194
|
+
title: `${bold('Server components')}\n${dim('Choose which server repo(s) to clone and install deps for.')}`,
|
|
186
195
|
options: [
|
|
187
|
-
{ label: 'happy-server-light only (default)
|
|
188
|
-
{ label: 'happy-server only (full server)
|
|
189
|
-
{ label:
|
|
196
|
+
{ label: `${cyan('happy-server-light')} only (default)`, value: 'happy-server-light' },
|
|
197
|
+
{ label: `${cyan('happy-server')} only (full server)`, value: 'happy-server' },
|
|
198
|
+
{ label: `both (${cyan('server-light')} + ${cyan('full server')})`, value: 'both' },
|
|
190
199
|
],
|
|
191
200
|
defaultIndex: defaults.serverComponentName === 'both' ? 2 : defaults.serverComponentName === 'happy-server' ? 1 : 0,
|
|
192
201
|
});
|
|
193
202
|
|
|
194
203
|
const allowClone = await promptSelect(rl, {
|
|
195
|
-
title: '
|
|
204
|
+
title: `${bold('Cloning')}\n${dim('If repos are missing under components/, should we clone them automatically?')}`,
|
|
196
205
|
options: [
|
|
197
206
|
{ label: 'yes (default)', value: true },
|
|
198
207
|
{ label: 'no', value: false },
|
|
@@ -202,8 +211,8 @@ async function interactiveWizard({ rootDir, defaults }) {
|
|
|
202
211
|
|
|
203
212
|
const enableAutostart = await promptSelect(rl, {
|
|
204
213
|
title: isSandboxed()
|
|
205
|
-
? '
|
|
206
|
-
: '
|
|
214
|
+
? `${bold('Autostart (macOS)')}\n${dim('Sandbox mode: this is global OS state; normally disabled in sandbox.')}`
|
|
215
|
+
: `${bold('Autostart (macOS)')}\n${dim('Install a LaunchAgent so Happy starts at login?')}`,
|
|
207
216
|
options: [
|
|
208
217
|
{ label: 'no (default)', value: false },
|
|
209
218
|
{ label: 'yes', value: true },
|
|
@@ -212,7 +221,7 @@ async function interactiveWizard({ rootDir, defaults }) {
|
|
|
212
221
|
});
|
|
213
222
|
|
|
214
223
|
const buildTauri = await promptSelect(rl, {
|
|
215
|
-
title: 'Build Tauri desktop app as part of setup?'
|
|
224
|
+
title: `${bold('Desktop app (optional)')}\n${dim('Build the Tauri desktop app as part of setup? (slow; requires extra toolchain)')}`,
|
|
216
225
|
options: [
|
|
217
226
|
{ label: 'no (default)', value: false },
|
|
218
227
|
{ label: 'yes', value: true },
|
|
@@ -221,7 +230,7 @@ async function interactiveWizard({ rootDir, defaults }) {
|
|
|
221
230
|
});
|
|
222
231
|
|
|
223
232
|
const configureGit = await promptSelect(rl, {
|
|
224
|
-
title: 'Configure upstream
|
|
233
|
+
title: `${bold('Git remotes')}\n${dim('Configure upstream remotes and create/update mirror branches (e.g. slopus/main)?')}`,
|
|
225
234
|
options: [
|
|
226
235
|
{ label: 'yes (default)', value: true },
|
|
227
236
|
{ label: 'no', value: false },
|
|
@@ -344,49 +353,71 @@ async function main() {
|
|
|
344
353
|
`- use --server=happy-server with --upstream`
|
|
345
354
|
);
|
|
346
355
|
}
|
|
347
|
-
|
|
348
|
-
const
|
|
349
|
-
const
|
|
356
|
+
// Repo roots (clone locations)
|
|
357
|
+
const uiRepoDir = getComponentRepoDir(rootDir, 'happy');
|
|
358
|
+
const serverLightRepoDir = getComponentRepoDir(rootDir, 'happy-server-light');
|
|
359
|
+
|
|
360
|
+
// Ensure UI exists first (monorepo anchor in slopus/happy).
|
|
361
|
+
await ensureComponentPresent({
|
|
362
|
+
dir: uiRepoDir,
|
|
363
|
+
label: 'UI',
|
|
364
|
+
repoUrl: repos.ui,
|
|
365
|
+
allowClone,
|
|
366
|
+
});
|
|
367
|
+
|
|
368
|
+
// Package dirs (where we run installs/builds). Recompute after cloning UI.
|
|
350
369
|
const uiDir = getComponentDir(rootDir, 'happy');
|
|
370
|
+
const cliDir = getComponentDir(rootDir, 'happy-cli');
|
|
371
|
+
const serverFullDir = getComponentDir(rootDir, 'happy-server');
|
|
372
|
+
|
|
373
|
+
const cliRepoDir = getComponentRepoDir(rootDir, 'happy-cli');
|
|
374
|
+
const serverFullRepoDir = getComponentRepoDir(rootDir, 'happy-server');
|
|
375
|
+
const hasMonorepo = isHappyMonorepoRoot(uiRepoDir);
|
|
351
376
|
|
|
352
|
-
// Ensure components exist
|
|
377
|
+
// Ensure other components exist.
|
|
378
|
+
// - server-light stays separate for now.
|
|
379
|
+
// - full server + cli may be embedded in the monorepo.
|
|
353
380
|
if (serverComponentName === 'both' || serverComponentName === 'happy-server-light') {
|
|
354
|
-
|
|
355
|
-
dir:
|
|
356
|
-
|
|
381
|
+
await ensureComponentPresent({
|
|
382
|
+
dir: serverLightRepoDir,
|
|
383
|
+
label: 'SERVER',
|
|
357
384
|
repoUrl: repos.serverLight,
|
|
358
385
|
allowClone,
|
|
359
386
|
});
|
|
360
387
|
}
|
|
361
|
-
if (
|
|
388
|
+
if (!hasMonorepo) {
|
|
389
|
+
if (serverComponentName === 'both' || serverComponentName === 'happy-server') {
|
|
390
|
+
await ensureComponentPresent({
|
|
391
|
+
dir: serverFullRepoDir,
|
|
392
|
+
label: 'SERVER_FULL',
|
|
393
|
+
repoUrl: repos.serverFull,
|
|
394
|
+
allowClone,
|
|
395
|
+
});
|
|
396
|
+
}
|
|
362
397
|
await ensureComponentPresent({
|
|
363
|
-
dir:
|
|
364
|
-
label: '
|
|
365
|
-
repoUrl: repos.
|
|
366
|
-
|
|
367
|
-
|
|
398
|
+
dir: cliRepoDir,
|
|
399
|
+
label: 'CLI',
|
|
400
|
+
repoUrl: repos.cli,
|
|
401
|
+
allowClone,
|
|
402
|
+
});
|
|
403
|
+
} else {
|
|
404
|
+
if ((serverComponentName === 'both' || serverComponentName === 'happy-server') && !(await pathExists(serverFullDir))) {
|
|
405
|
+
throw new Error(`[bootstrap] expected monorepo server package at ${serverFullDir} (missing).`);
|
|
406
|
+
}
|
|
407
|
+
if (!(await pathExists(cliDir))) {
|
|
408
|
+
throw new Error(`[bootstrap] expected monorepo cli package at ${cliDir} (missing).`);
|
|
409
|
+
}
|
|
368
410
|
}
|
|
369
|
-
await ensureComponentPresent({
|
|
370
|
-
dir: cliDir,
|
|
371
|
-
label: 'CLI',
|
|
372
|
-
repoUrl: repos.cli,
|
|
373
|
-
allowClone,
|
|
374
|
-
});
|
|
375
|
-
await ensureComponentPresent({
|
|
376
|
-
dir: uiDir,
|
|
377
|
-
label: 'UI',
|
|
378
|
-
repoUrl: repos.ui,
|
|
379
|
-
allowClone,
|
|
380
|
-
});
|
|
381
411
|
|
|
382
412
|
// Ensure expected branches are checked out for server flavors (avoids "server-light directory contains full server" mistakes).
|
|
383
413
|
if (serverComponentName === 'both' || serverComponentName === 'happy-server-light') {
|
|
384
|
-
await ensureGitBranchCheckedOut({ repoDir:
|
|
414
|
+
await ensureGitBranchCheckedOut({ repoDir: serverLightRepoDir, branch: 'happy-server-light', label: 'SERVER' });
|
|
385
415
|
}
|
|
386
416
|
if (serverComponentName === 'both' || serverComponentName === 'happy-server') {
|
|
387
|
-
// In fork mode, full server is a branch in the fork server repo.
|
|
388
|
-
|
|
389
|
-
|
|
417
|
+
// In fork mode (split repos), full server is a branch in the fork server repo.
|
|
418
|
+
// In upstream mode and in monorepo mode, use main.
|
|
419
|
+
const serverFullBranch = isHappyMonorepoRoot(serverFullRepoDir) ? 'main' : repoSource === 'upstream' ? 'main' : 'happy-server';
|
|
420
|
+
await ensureGitBranchCheckedOut({ repoDir: serverFullRepoDir, branch: serverFullBranch, label: 'SERVER_FULL' });
|
|
390
421
|
}
|
|
391
422
|
|
|
392
423
|
const cliDirFinal = cliDir;
|
|
@@ -396,7 +427,7 @@ async function main() {
|
|
|
396
427
|
const skipUiDeps = flags.has('--no-ui-deps') || (process.env.HAPPY_STACKS_INSTALL_NO_UI_DEPS ?? '').trim() === '1';
|
|
397
428
|
const skipCliDeps = flags.has('--no-cli-deps') || (process.env.HAPPY_STACKS_INSTALL_NO_CLI_DEPS ?? '').trim() === '1';
|
|
398
429
|
if (serverComponentName === 'both' || serverComponentName === 'happy-server-light') {
|
|
399
|
-
await ensureDepsInstalled(
|
|
430
|
+
await ensureDepsInstalled(getComponentDir(rootDir, 'happy-server-light'), 'happy-server-light');
|
|
400
431
|
}
|
|
401
432
|
if (serverComponentName === 'both' || serverComponentName === 'happy-server') {
|
|
402
433
|
await ensureDepsInstalled(serverFullDir, 'happy-server');
|
|
@@ -442,14 +473,16 @@ async function main() {
|
|
|
442
473
|
if (wizard?.configureGit) {
|
|
443
474
|
// Ensure upstream remotes exist so `happys wt sync-all` works consistently.
|
|
444
475
|
const upstreamRepos = getRepoUrls({ repoSource: 'upstream' });
|
|
445
|
-
await ensureUpstreamRemote({ repoDir:
|
|
446
|
-
|
|
476
|
+
await ensureUpstreamRemote({ repoDir: uiRepoDir, upstreamUrl: upstreamRepos.ui });
|
|
477
|
+
if (cliRepoDir !== uiRepoDir) {
|
|
478
|
+
await ensureUpstreamRemote({ repoDir: cliRepoDir, upstreamUrl: upstreamRepos.cli });
|
|
479
|
+
}
|
|
447
480
|
// server-light and server-full both track upstream happy-server
|
|
448
|
-
if (await pathExists(
|
|
449
|
-
await ensureUpstreamRemote({ repoDir:
|
|
481
|
+
if (await pathExists(serverLightRepoDir)) {
|
|
482
|
+
await ensureUpstreamRemote({ repoDir: serverLightRepoDir, upstreamUrl: upstreamRepos.serverLight });
|
|
450
483
|
}
|
|
451
|
-
if (await pathExists(
|
|
452
|
-
await ensureUpstreamRemote({ repoDir:
|
|
484
|
+
if (serverFullRepoDir !== uiRepoDir && (await pathExists(serverFullRepoDir))) {
|
|
485
|
+
await ensureUpstreamRemote({ repoDir: serverFullRepoDir, upstreamUrl: upstreamRepos.serverFull });
|
|
453
486
|
}
|
|
454
487
|
|
|
455
488
|
// Create/update mirror branches like slopus/main for each repo (best-effort).
|
|
@@ -466,7 +499,16 @@ async function main() {
|
|
|
466
499
|
ok: true,
|
|
467
500
|
repoSource,
|
|
468
501
|
serverComponentName,
|
|
469
|
-
dirs: {
|
|
502
|
+
dirs: {
|
|
503
|
+
uiRepoDir,
|
|
504
|
+
uiDir: uiDirFinal,
|
|
505
|
+
cliRepoDir,
|
|
506
|
+
cliDir: cliDirFinal,
|
|
507
|
+
serverLightRepoDir,
|
|
508
|
+
serverLightDir: getComponentDir(rootDir, 'happy-server-light'),
|
|
509
|
+
serverFullRepoDir,
|
|
510
|
+
serverFullDir,
|
|
511
|
+
},
|
|
470
512
|
cloned: allowClone,
|
|
471
513
|
autostart: enableAutostart ? 'enabled' : sandboxed && enableAutostartRaw && !allowGlobal ? 'skipped (sandbox)' : disableAutostart ? 'disabled' : 'unchanged',
|
|
472
514
|
interactive: Boolean(wizard),
|
package/scripts/migrate.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import './utils/env/env.mjs';
|
|
2
2
|
import { copyFile, mkdir, readFile } from 'node:fs/promises';
|
|
3
3
|
import { basename, join } from 'node:path';
|
|
4
|
-
import { createRequire } from 'node:module';
|
|
5
4
|
|
|
6
5
|
import { parseArgs } from './utils/cli/args.mjs';
|
|
7
6
|
import { printResult, wantsHelp, wantsJson } from './utils/cli/cli.mjs';
|
|
@@ -13,6 +12,7 @@ import { ensureHappyServerManagedInfra, applyHappyServerMigrations } from './uti
|
|
|
13
12
|
import { runCapture } from './utils/proc/proc.mjs';
|
|
14
13
|
import { pickNextFreeTcpPort } from './utils/net/ports.mjs';
|
|
15
14
|
import { getEnvValue } from './utils/env/values.mjs';
|
|
15
|
+
import { importPrismaClientForHappyServerLight, importPrismaClientFromNodeModules } from './utils/server/prisma_import.mjs';
|
|
16
16
|
|
|
17
17
|
function usage() {
|
|
18
18
|
return [
|
|
@@ -54,14 +54,6 @@ async function ensureTargetSecretMatchesSource({ sourceSecretPath, targetSecretP
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
async function importPrismaClientFrom(dir) {
|
|
58
|
-
const req = createRequire(import.meta.url);
|
|
59
|
-
const resolved = req.resolve('@prisma/client', { paths: [dir] });
|
|
60
|
-
// eslint-disable-next-line import/no-dynamic-require
|
|
61
|
-
const mod = req(resolved);
|
|
62
|
-
return mod.PrismaClient;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
57
|
async function migrateLightToServer({ rootDir, fromStack, toStack, includeFiles, force, json }) {
|
|
66
58
|
const from = resolveStackEnvPath(fromStack);
|
|
67
59
|
const to = resolveStackEnvPath(toStack);
|
|
@@ -139,8 +131,8 @@ async function migrateLightToServer({ rootDir, fromStack, toStack, includeFiles,
|
|
|
139
131
|
await copyFile(fromParsed.path, snapshotPath);
|
|
140
132
|
const snapshotDbUrl = `file:${snapshotPath}`;
|
|
141
133
|
|
|
142
|
-
const SourcePrismaClient = await
|
|
143
|
-
const TargetPrismaClient = await
|
|
134
|
+
const SourcePrismaClient = await importPrismaClientForHappyServerLight({ serverDir: lightDir });
|
|
135
|
+
const TargetPrismaClient = await importPrismaClientFromNodeModules({ dir: fullDir });
|
|
144
136
|
|
|
145
137
|
const sourceDb = new SourcePrismaClient({ datasources: { db: { url: snapshotDbUrl } } });
|
|
146
138
|
const targetDb = new TargetPrismaClient({ datasources: { db: { url: infra.env.DATABASE_URL } } });
|
|
@@ -289,4 +281,3 @@ main().catch((err) => {
|
|
|
289
281
|
console.error(err);
|
|
290
282
|
process.exit(1);
|
|
291
283
|
});
|
|
292
|
-
|