@coreframe/scripts 0.1.26 → 0.1.28
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/dist/dev.js +1 -1
- package/dist/managed-dev-protocol.d.ts +26 -1
- package/dist/managed-dev-protocol.js +1 -1
- package/dist/managed-dev.d.ts +21 -4
- package/dist/managed-dev.js +4 -2
- package/package.json +1 -1
package/dist/dev.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{readProjectConfig as e}from"./config.js";import{fs as t,net as n}from"./environment.js";import{ProjectPostgresAlreadyRunningError as r,startProjectPostgres as i,stopProjectPostgres as a}from"./db/local-postgres.js";import o from"./_virtual/_@oxc-project_runtime@0.138.0/helpers/esm/usingCtx.js";import{devHttpsCertEnv as s,devHttpsKeyEnv as c,prepareDevHttps as l}from"./dev-https.js";import{acquireDevLock as u}from"./dev-lock.js";import{managedDevEnv as d}from"./managed-dev-protocol.js";import{isManagedDevCheckout as f}from"./managed-dev.js";import
|
|
2
|
+
import{readProjectConfig as e}from"./config.js";import{fs as t,net as n}from"./environment.js";import{ProjectPostgresAlreadyRunningError as r,startProjectPostgres as i,stopProjectPostgres as a}from"./db/local-postgres.js";import o from"./_virtual/_@oxc-project_runtime@0.138.0/helpers/esm/usingCtx.js";import{devHttpsCertEnv as s,devHttpsKeyEnv as c,prepareDevHttps as l}from"./dev-https.js";import{acquireDevLock as u}from"./dev-lock.js";import{managedDevEnv as d}from"./managed-dev-protocol.js";import{isManagedDevCheckout as f,isPrimaryCheckout as p}from"./managed-dev.js";import m from"node:path";import*as h from"@clack/prompts";import g from"node:process";import{createPrefixStream as _,supervise as v}from"procband";const y=[`web`,`desktop`,`ios`,`android`];function b(e){let t=e.dev?.platforms??[`web`];for(let e of t)if(!y.includes(e))throw Error(`Invalid development platform "${String(e)}". Expected one of: ${y.join(`, `)}.`);return[...new Set(t)]}const x=m.resolve(`node_modules`,`.bin`),S=g.platform===`win32`?`pnpm.cmd`:`pnpm`,C=g.platform===`win32`?`portless.cmd`:`portless`,w=g.platform===`win32`?`react-router.cmd`:`react-router`,T=g.platform===`win32`?`turso.cmd`:`turso`;async function E({cwd:r=g.cwd(),env:i=g.env,host:a,https:h=!1,interactive:y=g.stdin.isTTY===!0,managed:b=!1,noManaged:E=!1,platform:N=`web`,webPort:P}={}){let F=i.PATH??i.Path??``,I=N===`web`?M(P??i.COREFRAME_WEB_PORT):void 0,L,R,z=i;if(b&&E)throw Error(`Cannot use --managed and --no-managed together.`);if(h&&N!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);let B=await u({cwd:r,interactive:y});if(B)try{if(N===`web`){let u=await e({cwd:r}),k=i.PORTLESS!==`0`&&i.TAURI_ENV_PLATFORM===void 0&&await p(r),M=h&&!k?await l({cwd:r}):void 0;z=M?{...i,[s]:M.cert,[c]:M.key}:i;let N=async()=>{R=v({name:`web`,command:k?C:w,args:k?j({host:a,port:I}):A({host:a,port:I}),cwd:r,env:{...z,CLOUDFLARE_ENV:`development`,PATH:x+m.delimiter+F}}),await R.wait(),await R.expectSuccess(),R=void 0};if((b||y&&!E)&&await f(r)&&(z={...z,[d]:`1`}),u.database?.dialect===`sqlite`){let e=await n.getAvailablePort(),a=m.resolve(r,`.coreframe`),o=m.join(a,`turso.db`);await t.mkdir(a,{recursive:!0}),z={...z,TURSO_DATABASE_URL:`http://127.0.0.1:${e}`,TURSO_AUTH_TOKEN:`dev`},L=v({name:`turso`,command:T,args:[`dev`,`--port`,String(e),`--db-file`,o],cwd:r,env:i}),await L.waitFor(`listening`),await v({name:`db`,command:S,args:[`db`,`ensure`],cwd:r,env:z,prefix:!1}).expectSuccess()}if(O(u)){let e=_({label:`postgres`});e.pipe(g.stdout,{end:!1});try{try{var V=o();let t=await D({config:u,cwd:r,env:z,interactive:y,postgresOutput:e,takeoverApproved:B.takeoverApproved});if(!t)return;V.a(t);let n=t.env;z=n,await v({name:`db`,command:S,args:[`db`,`ensure`],cwd:r,env:n,prefix:!1}).expectSuccess(),await N()}catch(e){V.e=e}finally{await V.d()}}finally{e.end()}return}await N();return}let u=k(N);await v({name:N,command:S,args:u,cwd:r,env:i}).expectSuccess()}finally{R?.kill(`SIGTERM`),L&&L.kill(`SIGTERM`),await B.release()}}async function D({interactive:e,takeoverApproved:t,...n}){try{return await i(n)}catch(o){if(!(o instanceof r)||!e)throw o;if(!t){let e=await h.confirm({initialValue:!1,message:`PostgreSQL is already running for this project (PID ${o.pid}). Stop it and start here?`});if(h.isCancel(e)||!e){h.cancel(`Keeping the existing PostgreSQL process.`);return}}return await a(o),i(n)}}function O(e){return(e.database?.dialect??`postgres`)===`postgres`}function k(e){return[`--dir=tauri`,`tauri`,...e===`desktop`?[]:[e],`dev`]}function A({host:e,port:t}){return[`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)]]}function j({host:e,port:t}){return[`run`,...t===void 0?[]:[`--app-port`,String(t)],`react-router`,...A({host:e,port:void 0})]}function M(e){if(e===void 0)return;let t=Number(e);if(!Number.isInteger(t)||t<=0||t>65535)throw Error(`COREFRAME_WEB_PORT must be a valid TCP port.`);return t}export{y as devPlatforms,b as resolveDevPlatforms,E as runDevServer};
|
|
@@ -3,6 +3,7 @@ declare const managedDevEnv = "COREFRAME_MANAGED_DEV";
|
|
|
3
3
|
declare const managedDevEvents: {
|
|
4
4
|
readonly action: "coreframe:managed-dev:action";
|
|
5
5
|
readonly actionResult: "coreframe:managed-dev:action-result";
|
|
6
|
+
readonly codex: "coreframe:managed-dev:codex";
|
|
6
7
|
readonly status: "coreframe:managed-dev:status";
|
|
7
8
|
readonly statusRequest: "coreframe:managed-dev:status-request";
|
|
8
9
|
};
|
|
@@ -17,8 +18,18 @@ type ManagedDevDraft = {
|
|
|
17
18
|
tracked: boolean;
|
|
18
19
|
untracked: string[];
|
|
19
20
|
};
|
|
21
|
+
type ManagedDevCheck = {
|
|
22
|
+
command: "pnpm test" | "pnpm typecheck";
|
|
23
|
+
output?: string;
|
|
24
|
+
status: "failed" | "passed" | "pending" | "running";
|
|
25
|
+
};
|
|
26
|
+
type ManagedDevChecks = {
|
|
27
|
+
commit: string;
|
|
28
|
+
commands: ManagedDevCheck[];
|
|
29
|
+
};
|
|
20
30
|
type ManagedDevStatus = {
|
|
21
31
|
busy?: string;
|
|
32
|
+
checks?: ManagedDevChecks;
|
|
22
33
|
currentCommit?: string;
|
|
23
34
|
draft?: ManagedDevDraft;
|
|
24
35
|
message?: string;
|
|
@@ -51,6 +62,17 @@ type ManagedDevAction = {
|
|
|
51
62
|
type ManagedDevActionResult = {
|
|
52
63
|
status: ManagedDevStatus;
|
|
53
64
|
};
|
|
65
|
+
type ManagedDevCodexEvent = {
|
|
66
|
+
phase: "start";
|
|
67
|
+
} | {
|
|
68
|
+
phase: "stderr";
|
|
69
|
+
text: string;
|
|
70
|
+
} | {
|
|
71
|
+
message: string;
|
|
72
|
+
phase: "complete";
|
|
73
|
+
} | {
|
|
74
|
+
phase: "error";
|
|
75
|
+
};
|
|
54
76
|
type ManagedDevActionRequest = {
|
|
55
77
|
action: ManagedDevAction;
|
|
56
78
|
requestId: string;
|
|
@@ -59,8 +81,11 @@ type ManagedDevActionResponse = Partial<ManagedDevActionResult> & {
|
|
|
59
81
|
error?: string;
|
|
60
82
|
requestId: string;
|
|
61
83
|
};
|
|
84
|
+
type ManagedDevCodexResponse = ManagedDevCodexEvent & {
|
|
85
|
+
requestId: string;
|
|
86
|
+
};
|
|
62
87
|
type ManagedDevStatusResponse = {
|
|
63
88
|
status: ManagedDevStatus;
|
|
64
89
|
};
|
|
65
90
|
//#endregion
|
|
66
|
-
export { ManagedDevAction, ManagedDevActionRequest, ManagedDevActionResponse, ManagedDevActionResult, ManagedDevDraft, ManagedDevStatus, ManagedDevStatusResponse, ManagedDevTarget, managedDevEnv, managedDevEvents };
|
|
91
|
+
export { ManagedDevAction, ManagedDevActionRequest, ManagedDevActionResponse, ManagedDevActionResult, ManagedDevCheck, ManagedDevChecks, ManagedDevCodexEvent, ManagedDevCodexResponse, ManagedDevDraft, ManagedDevStatus, ManagedDevStatusResponse, ManagedDevTarget, managedDevEnv, managedDevEvents };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const e=`COREFRAME_MANAGED_DEV`,t={action:`coreframe:managed-dev:action`,actionResult:`coreframe:managed-dev:action-result`,status:`coreframe:managed-dev:status`,statusRequest:`coreframe:managed-dev:status-request`};export{e as managedDevEnv,t as managedDevEvents};
|
|
1
|
+
const e=`COREFRAME_MANAGED_DEV`,t={action:`coreframe:managed-dev:action`,actionResult:`coreframe:managed-dev:action-result`,codex:`coreframe:managed-dev:codex`,status:`coreframe:managed-dev:status`,statusRequest:`coreframe:managed-dev:status-request`};export{e as managedDevEnv,t as managedDevEvents};
|
package/dist/managed-dev.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CoreframeConfig } from "./config.js";
|
|
2
|
-
import { ManagedDevAction, ManagedDevActionResult, ManagedDevStatus } from "./managed-dev-protocol.js";
|
|
2
|
+
import { ManagedDevAction, ManagedDevActionResult, ManagedDevCodexEvent, ManagedDevStatus } from "./managed-dev-protocol.js";
|
|
3
|
+
import { FSWatcher } from "node:fs";
|
|
3
4
|
|
|
4
5
|
//#region managed-dev.d.ts
|
|
5
6
|
type ManagedDevSessionOptions = {
|
|
@@ -9,21 +10,37 @@ type ManagedDevSessionOptions = {
|
|
|
9
10
|
onRestart?(): void;
|
|
10
11
|
onStatusChange?(status: ManagedDevStatus): void;
|
|
11
12
|
remoteCheckInterval?: number;
|
|
13
|
+
runCheck?(script: ManagedDevCheckScript): Promise<void>;
|
|
14
|
+
watchState?(state: GitState, onChange: () => void): Promise<FSWatcher[]>;
|
|
15
|
+
};
|
|
16
|
+
type ManagedDevCheckScript = "test" | "typecheck";
|
|
17
|
+
type GitState = {
|
|
18
|
+
branch: string | undefined;
|
|
19
|
+
commonDir: string;
|
|
20
|
+
gitDir: string;
|
|
21
|
+
head: string;
|
|
22
|
+
main: string;
|
|
23
|
+
primary: boolean;
|
|
12
24
|
};
|
|
13
25
|
type ManagedDevSession = {
|
|
14
|
-
action(action: ManagedDevAction
|
|
26
|
+
action(action: ManagedDevAction, options?: {
|
|
27
|
+
onCodexEvent?(event: ManagedDevCodexEvent): void;
|
|
28
|
+
}): Promise<ManagedDevActionResult>;
|
|
15
29
|
activate(): Promise<void>;
|
|
16
30
|
getStatus(): ManagedDevStatus;
|
|
17
31
|
close(): Promise<void>;
|
|
18
32
|
};
|
|
19
33
|
declare function isManagedDevCheckout(cwd?: string): Promise<boolean>;
|
|
34
|
+
declare function isPrimaryCheckout(cwd?: string): Promise<boolean>;
|
|
20
35
|
declare function startManagedDevSession({
|
|
21
36
|
config,
|
|
22
37
|
cwd,
|
|
23
38
|
env,
|
|
24
39
|
onRestart,
|
|
25
40
|
onStatusChange,
|
|
26
|
-
remoteCheckInterval
|
|
41
|
+
remoteCheckInterval,
|
|
42
|
+
runCheck,
|
|
43
|
+
watchState
|
|
27
44
|
}: ManagedDevSessionOptions): Promise<ManagedDevSession>;
|
|
28
45
|
//#endregion
|
|
29
|
-
export { ManagedDevSession, isManagedDevCheckout, startManagedDevSession };
|
|
46
|
+
export { ManagedDevSession, isManagedDevCheckout, isPrimaryCheckout, startManagedDevSession };
|
package/dist/managed-dev.js
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
-
import{createHash as e,randomBytes as t}from"node:crypto";import{access as n,copyFile as r,mkdir as i,mkdtemp as a,open as o,readFile as s,realpath as c,rm as l,unlink as u}from"node:fs/promises";import d from"node:path";import f,{SubprocessError as p}from"nano-spawn";import{pathToFileURL as m}from"node:url";import h from"node:process";import{constants as g,watch as _}from"node:fs";import{resolve as v}from"import-meta-resolve";const y=`refs/heads/main`,b=`refs/heads/dev`,x=`refs/remotes/origin/main`,S=/^[a-z][a-z0-9-]*(?:\([^)]+\))?!?:\s+\S/i;async function C(e=h.cwd()){let t=await
|
|
2
|
-
`),fingerprint:o.digest(`hex`),tracked:n.length>0,untracked:a}}async function
|
|
1
|
+
import{createHash as e,randomBytes as t}from"node:crypto";import{access as n,copyFile as r,mkdir as i,mkdtemp as a,open as o,readFile as s,realpath as c,rm as l,unlink as u}from"node:fs/promises";import d from"node:path";import f,{SubprocessError as p}from"nano-spawn";import{pathToFileURL as m}from"node:url";import h from"node:process";import{constants as g,watch as _}from"node:fs";import{resolve as v}from"import-meta-resolve";const y=`refs/heads/main`,b=`refs/heads/dev`,x=`refs/remotes/origin/main`,S=/^[a-z][a-z0-9-]*(?:\([^)]+\))?!?:\s+\S/i;async function C(e=h.cwd()){let t=await D(e);return t.primary&&t.branch===`main`&&t.head===t.main}async function w(e=h.cwd()){try{let{commonDir:t,gitDir:n}=await T(e);return n===t}catch{return!1}}async function T(e){let t=await c(await Y(e,[`rev-parse`,`--show-toplevel`])),n=await c(e),r=d.resolve(n,await Y(e,[`rev-parse`,`--git-dir`])),i=d.resolve(n,await Y(e,[`rev-parse`,`--git-common-dir`]));return{commonDir:i,gitDir:r,primary:t===n&&r===i}}async function E({config:e,cwd:t=h.cwd(),env:n=h.env,onRestart:r=()=>void 0,onStatusChange:i=()=>void 0,remoteCheckInterval:a=6e4,runCheck:o=e=>ae(t,n,e),watchState:s=ee}){let c=n,l={mode:`waiting`,warnings:[]},u=!1,p=!1,m=!1,g=!1,_=!1,v,C,w,T,E,O=[],j,M,N=Promise.resolve(),P=()=>{u||i(l)},F=async({fetch:e=!1}={})=>{if(!(!p||u||!C)){if(g){_=!0;return}try{let[n,r]=await Promise.all([Y(t,[`rev-parse`,`--abbrev-ref`,`HEAD`]),Y(t,[`rev-parse`,`HEAD`])]);if(n!==`main`||r!==v){await R(`The local main checkout changed outside Coreframe; managed synchronization is disabled until restart.`);return}let i=await k(t);if(i.tracked||i.untracked.length>0){l={...l,currentCommit:v,draft:i,message:void 0,mode:`managed`,proposal:H(i.fingerprint),target:void 0};return}e&&await X(t,[`remote`,`get-url`,`origin`])&&await J(t,[`fetch`,`origin`,`+refs/heads/main:${x}`]);let a=await X(t,[`rev-parse`,b]),o=await X(t,[`rev-parse`,x]),s=[...o?[{commit:o,source:`upstream`}]:[],...a?[{commit:a,source:`dev`}]:[]],c;for(let e of s)if(!await ue(t,e.commit,v)){c=e;break}l={...l,currentCommit:v,draft:void 0,message:void 0,mode:`managed`,proposal:void 0,target:c===void 0?void 0:await le(t,c.commit,c.source)}}catch(e){l={...l,message:$(e),warnings:[$(e)]}}finally{P()}}},I=()=>{clearTimeout(E),E=setTimeout(()=>void F(),50),E.unref()},L=e=>{let t=async()=>{let t=[{command:`pnpm typecheck`,status:`running`},{command:`pnpm test`,status:`pending`}],n=()=>{l={...l,checks:{commit:e,commands:structuredClone(t)}},P()};n();for(let[e,r]of[`typecheck`,`test`].entries()){e>0&&(t[e].status=`running`,n());try{await o(r),t[e].status=`passed`}catch(n){t[e].status=`failed`,t[e].output=oe(n)}n()}};N=N.then(t,t)},R=async e=>{p=!1,m=!0,clearInterval(T),clearTimeout(E);for(let e of O)e.close();O=[],await q(w),w=void 0,l={message:e,mode:`unmanaged`,warnings:[]},P()},z=async()=>{if(p||u||m)return;let e=await D(t);if(!e.primary){l={message:`Managed development only runs from the primary checkout.`,mode:`unmanaged`,warnings:[]},P();return}if(e.branch!==`main`||e.head!==e.main){let t=`Managed development requires the primary checkout on local main; current branch is ${e.branch??`detached HEAD`}.`;console.warn(`Coreframe managed development disabled: ${t}`),l={message:t,mode:`unmanaged`,warnings:[]},P();return}w=d.join(e.commonDir,`coreframe-managed-dev.lock`),await G(w),await X(t,[`rev-parse`,`--verify`,b])||await J(t,[`branch`,`dev`,e.head]),C=e,v=e.head,p=!0,l={currentCommit:e.head,mode:`managed`,warnings:[]},P(),O=await s(e,I),T=setInterval(()=>void F({fetch:!0}),a),T.unref(),await F(),F({fetch:!0})},B=async(e,{onCodexEvent:n=()=>void 0}={})=>{if(!p||l.mode!==`managed`)throw Error(`Managed development is not active.`);if(g)throw Error(`Another managed development action is already running.`);g=!0,l={...l,busy:pe(e),message:void 0},P();try{if(e.type===`reject`)l={...l,draft:void 0,proposal:void 0};else if(e.type===`prepare`){let r=V(e.target),i=await k(t);i.tracked||i.untracked.length>0?l={...l,draft:i,proposal:H(i.fingerprint)}:await me({onCodexEvent:n,source:r.source,target:e.target})}else if(e.type===`message`){let n=await U(e.fingerprint,e.untracked),r=H(n.fingerprint);if(r===void 0){try{if(M??=ne(`codex`,c),!await M)throw Error("Codex CLI is not installed or is unavailable on PATH. Install it with `npm install -g @openai/codex`, then restart the dev server.");r=await te(t,c,n.context)}catch(e){r=``,l={...l,warnings:[...l.warnings,`Codex could not generate a commit message: ${$(e)}`]}}j={fingerprint:n.fingerprint,message:r}}l={...l,draft:n,proposal:r}}else if(e.type===`commit`){let t=await K(e);l={...l,currentCommit:t,draft:void 0,message:void 0,proposal:void 0,target:void 0},I()}else{let r=V(e.target),i=await k(t);if(i.tracked||i.untracked.length>0){if(!e.fingerprint||!e.untracked)throw Error(`Refresh requires the current working-tree confirmation.`);if(await U(e.fingerprint,e.untracked),!e.message||!S.test(fe(e.message)))throw Error(`Enter a commit message with a valid Conventional Commits header.`)}await me({fingerprint:e.fingerprint,message:e.message,onCodexEvent:n,source:r.source,target:e.target,untracked:e.untracked})}}finally{g=!1,l={...l,busy:void 0},P(),_&&(_=!1,I())}return{status:l}},V=e=>{if(!l.target||l.target.commit!==e)throw Error(`The offered update changed. Review the latest target before refreshing.`);return l.target},H=e=>j?.fingerprint===e?j.message:void 0,U=async(e,n)=>{let r=await k(t);if(r.fingerprint!==e)throw j=void 0,Error(`Working-tree changes changed; generate a new commit message.`);if(!de(r.untracked,n))throw Error(`Include every untracked file or remove it before refreshing.`);return r},K=async({fingerprint:e,message:n,untracked:r})=>{let i=await U(e,r);if(!n||!S.test(fe(n)))throw Error(`Enter a commit message with a valid Conventional Commits header.`);await J(t,[`add`,`--update`]),i.untracked.length>0&&await J(t,[`add`,`--`,...r]),await J(t,[`commit`,`--message`,n],{env:{GIT_EDITOR:`true`}});let a=await Y(t,[`rev-parse`,`HEAD`]);return v=a,j=void 0,a},me=async({fingerprint:n,message:i,onCodexEvent:a=()=>void 0,source:o,target:s,untracked:u=[]})=>{V(s);let d=await Y(t,[`rev-parse`,`HEAD`]),p,m,h=await k(t);if(h.tracked||h.untracked.length>0){if(!n||h.fingerprint!==n||!de(h.untracked,u))throw Error(`Working-tree changes changed; review them before refreshing.`);await J(t,[`add`,`--update`]),u.length>0&&await J(t,[`add`,`--`,...u]),await J(t,[`commit`,`--message`,i],{env:{GIT_EDITOR:`true`}}),p=await Y(t,[`rev-parse`,`HEAD`]),v=p,m=`refs/coreframe/recovery/${Date.now()}-${p.slice(0,12)}`,await J(t,[`update-ref`,m,p])}let g=p??d,x;try{if(x=await re({cwd:t,env:c,localMain:g,onCodexEvent:a,source:o,target:s}),await Y(t,[`rev-parse`,`HEAD`])!==g)throw Error(`HEAD changed while the accepted update was being prepared.`);if(await Y(t,[`rev-parse`,y])!==g)throw Error(`Local main changed while the accepted update was being prepared.`);try{await ie(t,x,g),await J(t,[`reset`,`--hard`,x.commit])}catch(e){throw await J(t,[`update-ref`,y,g,x.commit]).catch(()=>void 0),await J(t,[`reset`,`--hard`,g]).catch(()=>void 0),e}v=x.commit;let n=Z(await Y(t,[`diff`,`--name-only`,`-z`,d,x.commit]));W(n)&&await f(Q(),[`install`,`--frozen-lockfile`],{cwd:t,env:c,stdio:`inherit`});try{await se({config:e,cwd:t,env:c})}catch(e){throw await J(t,[`reset`,`--hard`,g]),v=g,l={...l,currentCommit:g},Error(`Database migration failed; the database and preview were restored. ${$(e)}`)}j=void 0,m&&await J(t,[`update-ref`,`-d`,m]),l={...l,currentCommit:x.commit,draft:void 0,proposal:void 0,target:void 0},L(x.commit),ce(n)&&r()}catch(e){e instanceof A&&(_=!0),x?.devTarget&&x.devTarget!==x.commit&&await J(t,[`update-ref`,b,x.devTarget,x.commit]).catch(()=>void 0),x?.commit&&v===x.commit&&(await J(t,[`reset`,`--hard`,g]).catch(()=>void 0),v=g);let n=m?` Recovery commit: ${m}.`:``;throw l={...l,currentCommit:v,message:`${$(e)}${n}`},e}};return{action:B,activate:z,getStatus:()=>l,async close(){if(!u){u=!0,clearInterval(T),clearTimeout(E);for(let e of O)e.close();await q(w)}}}}async function D(e){let t=await T(e);return{branch:O(await Y(e,[`rev-parse`,`--abbrev-ref`,`HEAD`])),commonDir:t.commonDir,gitDir:t.gitDir,head:await Y(e,[`rev-parse`,`HEAD`]),main:await Y(e,[`rev-parse`,y]),primary:t.primary}}function O(e){return e===`HEAD`?void 0:e}async function ee(e,t){let n=[e.gitDir,d.join(e.commonDir,`refs`,`heads`)],r=[];for(let e of n)try{r.push(_(e,{persistent:!1},t))}catch{}return r}async function k(t){let[n,r,i]=await Promise.all([Y(t,[`status`,`--porcelain`,`--untracked-files=no`]),Y(t,[`diff`,`HEAD`,`--binary`]),Y(t,[`ls-files`,`--others`,`--exclude-standard`,`-z`])]),a=Z(i).sort(),o=e(`sha256`).update(r),c=[`Tracked changes:`,r];for(let e of a){let n=await s(d.join(t,e));o.update(e).update(n),c.push(`\nUntracked file: ${e}\n`,n.toString(`utf8`))}return{context:c.join(`
|
|
2
|
+
`),fingerprint:o.digest(`hex`),tracked:n.length>0,untracked:a}}async function te(e,t,n){let{stdout:r}=await f(`codex`,[`exec`,`--ephemeral`,`--ignore-user-config`,`--sandbox`,`read-only`,`--cd`,e,`Return only a concise Conventional Commits message for the supplied working-tree changes. Use a body only when it adds material context.`],{cwd:e,env:t,stderr:`ignore`,stdin:{string:n}});return r.trim().replace(/^```(?:text)?\s*|\s*```$/g,``)}async function ne(e,t){let r=t.PATH??t.Path??t.path??``,i=h.platform===`win32`?(t.PATHEXT??`.COM;.EXE;.BAT;.CMD`).split(`;`):[``];for(let t of r.split(d.delimiter))for(let r of i)try{return await n(d.join(t||`.`,`${e}${r}`),g.X_OK),!0}catch{}return!1}var A=class extends Error{constructor(){super(`Local dev advanced while this update was being prepared. Nothing was changed. Review the latest update and try again.`)}};async function re({cwd:e,env:n,localMain:r,onCodexEvent:a,source:o,target:s}){if(o===`dev`&&await ue(e,r,s))return{commit:s,devTarget:s};let c=d.resolve(e,await Y(e,[`rev-parse`,`--git-common-dir`])),u=d.join(c,`coreframe-managed-dev`);await i(u,{recursive:!0});let f=t(8).toString(`hex`),p=d.join(u,`integration-${f}`);try{let t=o===`dev`?s:r,i=o===`dev`?r:s;if(await J(e,[`worktree`,`add`,`--detach`,p,t]),r!==s){let e=await X(p,[`merge-base`,r,s]);await j(p,n,e?[`rebase`,`--onto`,i,e]:[`rebase`,`--root`,`--onto`,i],`rebase`,a)}return{commit:await Y(p,[`rev-parse`,`HEAD`]),devTarget:o===`dev`?s:void 0}}finally{await J(e,[`worktree`,`remove`,`--force`,p]).catch(()=>void 0),await l(p,{force:!0,recursive:!0})}}async function ie(e,t,n){let r=[`start`,`update ${y} ${t.commit} ${n}`];t.devTarget&&r.push(t.devTarget===t.commit?`verify ${b} ${t.devTarget}`:`update ${b} ${t.commit} ${t.devTarget}`),r.push(`prepare`,`commit`);try{await f(`git`,[`update-ref`,`--stdin`],{cwd:e,stdin:{string:`${r.join(`
|
|
3
|
+
`)}\n`}})}catch(r){if(t.devTarget)try{let[r,i]=await Promise.all([Y(e,[`rev-parse`,y]),X(e,[`rev-parse`,b])]);if(r===n&&i!==t.devTarget)throw new A}catch(e){if(e instanceof A)throw e}throw r}}async function j(e,t,n,r,i){try{await J(e,n,{env:{GIT_EDITOR:`true`}});return}catch(n){let a=await P(e);if(a.length===0)throw n;try{for(;a.length>0;){await M(e,t,r,a,i),await J(e,[`diff`,`--check`]),await J(e,[`add`,`--all`]);let n=await P(e);if(n.length>0)throw Error(`Codex left unresolved paths: ${n.join(`, `)}`);try{await J(e,[r,`--continue`],{env:{GIT_EDITOR:`true`}})}catch(t){if(a=await P(e),a.length===0)throw t;continue}a=await P(e)}return}catch(t){throw await J(e,[r,`--abort`]).catch(()=>void 0),Error(`Codex could not resolve ${r} conflicts: ${$(t)}`)}}}async function M(e,t,n,r,i){i({phase:`start`});let a=f(`codex`,[`exec`,`--ephemeral`,`--ignore-user-config`,`--sandbox`,`workspace-write`,`--cd`,e,`Resolve the current Git ${n} conflicts cleanly. Edit only files needed for the resolution, preserve intended behavior from both sides, remove all conflict markers, and do not stage files or run Git continuation commands. Conflicted paths: ${r.join(`, `)}`],{cwd:e,env:t}),o=[];try{await Promise.all([N(a.stdout,e=>o.push(e)),N(a.stderr,e=>i({phase:`stderr`,text:`${e}\n`}))])}catch(e){throw i({phase:`error`}),e}i({message:o.join(`
|
|
4
|
+
`).trim(),phase:`complete`})}async function N(e,t){for await(let n of e)t(n)}async function P(e){return Z(await Y(e,[`diff`,`--name-only`,`--diff-filter=U`,`-z`]))}async function ae(e,t,n){await f(Q(),[n],{cwd:e,env:t})}function oe(e){if(e instanceof p){let t=e.output.trim();if(t)return t}return $(e)}async function se({config:e,cwd:t,env:n}){if(!e.database)return;let r=await F({config:e,cwd:t,env:n});try{await f(Q(),[`db`,`migrate`],{cwd:t,env:n,stdio:`inherit`})}catch(e){throw await r.restore(),e}await r.discard().catch(e=>{console.warn(`Could not remove the managed-development database snapshot: ${$(e)}`)}),await l(r.directory,{force:!0,recursive:!0})}async function F({config:e,cwd:t,env:n}){let o=d.join(t,`.coreframe`,`managed-dev-backups`);await i(o,{recursive:!0});let s=await a(d.join(o,`refresh-`));if(e.database?.dialect===`sqlite`){let e=[`turso.db`,`turso.db-wal`,`turso.db-shm`],n=new Set;for(let r of e)await I(d.join(t,`.coreframe`,r),d.join(s,r))&&n.add(r);return{directory:s,async discard(){},async restore(){for(let i of e){let e=d.join(t,`.coreframe`,i);n.has(i)?await r(d.join(s,i),e):await l(e,{force:!0})}}}}if(!n.DATABASE_URL)throw Error(`DATABASE_URL is required to snapshot local PostgreSQL.`);let c=await L(t);if(c)return R({directory:s,connectionString:n.DATABASE_URL,postgres:c});let u=d.join(s,`database.dump`),p=U(n,n.DATABASE_URL);return await f(`pg_dump`,[`--format=custom`,`--file`,u],{cwd:t,env:p,stdin:`ignore`}),{directory:s,async discard(){},async restore(){await f(`pg_restore`,[`--clean`,`--if-exists`,`--no-owner`,`--dbname`,p.PGDATABASE,u],{cwd:t,env:p,stdin:`ignore`})}}}async function I(e,t){try{return await r(e,t),!0}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e;return!1}}async function L(e){let t=JSON.parse(await s(d.join(e,`package.json`),`utf8`));if(!(!t.dependencies?.pg&&!t.devDependencies?.pg&&!t.optionalDependencies?.pg))try{return await import(v(`pg`,m(d.join(e,`package.json`)).href))}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ERR_MODULE_NOT_FOUND`)return;throw e}}async function R({directory:e,connectionString:n,postgres:r}){let i=new URL(n),a=decodeURIComponent(i.pathname.slice(1));if(!a)throw Error(`DATABASE_URL must name a PostgreSQL database to snapshot.`);let o=`coreframe_backup_${t(6).toString(`hex`)}`,s=`${o}_failed`,c=new URL(i);c.pathname=a===`postgres`?`/template1`:`/postgres`;let l=new r.Client({connectionString:c.href});await l.connect();try{await B(l,a,!1),await V(l,a),await l.query(`CREATE DATABASE ${H(o)} WITH TEMPLATE ${H(a)}`),await B(l,o,!0)}finally{await B(l,a,!0).catch(()=>void 0),await l.end()}return{directory:e,async discard(){await z(r,c.href,async e=>{await V(e,o),await e.query(`DROP DATABASE ${H(o)}`)})},async restore(){await z(r,c.href,async e=>{await B(e,a,!1),await V(e,a),await e.query(`ALTER DATABASE ${H(a)} RENAME TO ${H(s)}`);try{await e.query(`ALTER DATABASE ${H(o)} RENAME TO ${H(a)}`)}catch(t){throw await e.query(`ALTER DATABASE ${H(s)} RENAME TO ${H(a)}`).catch(()=>void 0),await B(e,a,!0).catch(()=>void 0),t}await V(e,s),await e.query(`DROP DATABASE ${H(s)}`)})}}}async function z(e,t,n){let r=new e.Client({connectionString:t});await r.connect();try{return await n(r)}finally{await r.end()}}async function B(e,t,n){await e.query(`ALTER DATABASE ${H(t)} ALLOW_CONNECTIONS ${n?`true`:`false`}`)}async function V(e,t){await e.query(`SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname = $1 AND pid <> pg_backend_pid()`,[t])}function H(e){return`"${e.replaceAll(`"`,`""`)}"`}function U(e,t){let n=new URL(t);return{...e,PGDATABASE:decodeURIComponent(n.pathname.slice(1)),PGHOST:n.hostname,PGPASSWORD:decodeURIComponent(n.password),PGPORT:n.port||`5432`,PGUSER:decodeURIComponent(n.username)}}function W(e){return e.some(e=>d.basename(e)===`package.json`||d.basename(e).endsWith(`lock.yaml`)||d.basename(e)===`pnpm-workspace.yaml`)}function ce(e){return e.some(e=>W([e])||/(^|\/)(vite|coreframe|tsconfig|drizzle)\.[^/]+$/.test(e)||/(^|\/)(drizzle|scripts|src\/api|tauri)(\/|$)/.test(e))}async function le(e,t,n){return{commit:t,shortCommit:t.slice(0,12),source:n,subject:await Y(e,[`show`,`-s`,`--format=%s`,t])}}async function G(e){try{let t=await o(e,`wx`);await t.writeFile(`${h.pid}\n`),await t.close()}catch(t){if(!(t instanceof Error&&`code`in t&&t.code===`EEXIST`))throw t;let n=(await s(e,`utf8`).catch(()=>`unknown`)).trim(),r=Number(n);if(Number.isInteger(r)&&!K(r)){await u(e).catch(()=>void 0),await G(e);return}throw Error(`Managed development is already owned by PID ${n}.`)}}function K(e){try{return h.kill(e,0),!0}catch(e){return!(e instanceof Error&&`code`in e&&e.code===`ESRCH`)}}async function q(e){e&&(await s(e,`utf8`).catch(()=>void 0))?.trim()===String(h.pid)&&await u(e).catch(()=>void 0)}async function J(e,t,{env:n}={}){return f(`git`,t,{cwd:e,env:n,stdin:`ignore`})}async function Y(e,t){return(await J(e,t)).stdout.trim()}async function X(e,t){try{return await Y(e,t)||void 0}catch(e){if(e instanceof p&&e.exitCode&&e.exitCode>0)return;throw e}}async function ue(e,t,n){try{return await J(e,[`merge-base`,`--is-ancestor`,t,n]),!0}catch(e){if(e instanceof p&&e.exitCode===1)return!1;throw e}}function de(e,t){return e.length===t.length&&[...e].sort().every((e,n)=>e===[...t].sort()[n])}function Z(e){return e.split(`\0`).filter(Boolean)}function fe(e){return e.split(/\r?\n/,1)[0]??``}function pe(e){return e.type===`message`?`Generating commit message`:e.type===`commit`?`Committing local changes`:e.type===`apply`?`Integrating accepted update`:e.type===`prepare`?`Reviewing working tree`:`Aborting refresh`}function Q(){return h.platform===`win32`?`pnpm.cmd`:`pnpm`}function $(e){return e instanceof Error?e.message:String(e)}export{C as isManagedDevCheckout,w as isPrimaryCheckout,E as startManagedDevSession};
|