@coreframe/scripts 0.2.4 → 0.2.6

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.
@@ -173,6 +173,7 @@ declare const coreframeCli: Partial<import("@alloc/cmd-ts/dist/cjs/argparser").R
173
173
  https: boolean;
174
174
  fresh: boolean;
175
175
  host: string | undefined;
176
+ lan: boolean;
176
177
  managed: boolean;
177
178
  noManaged: boolean;
178
179
  reuseVite: boolean;
@@ -462,6 +463,7 @@ declare const coreframeCli: Partial<import("@alloc/cmd-ts/dist/cjs/argparser").R
462
463
  https: boolean;
463
464
  fresh: boolean;
464
465
  host: string | undefined;
466
+ lan: boolean;
465
467
  managed: boolean;
466
468
  noManaged: boolean;
467
469
  reuseVite: boolean;
package/dist/coreframe.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import*as e from"@alloc/cmd-ts";import{array as t,command as n,extendType as r,flag as i,multioption as a,number as o,oneOf as s,option as c,optional as l,positional as u,rest as d,string as f,subcommands as p}from"@alloc/cmd-ts";import{ProjectPostgresAlreadyRunningError as m,checkDeployMigrations as h,checkSchemaPush as g,collectDeployMigrationFiles as _,createProjectDeployDatabase as v,ensureLocalDb as y,filterPendingMigrations as b,formatDbErrorMessage as x,formatMigrationList as S,formatMigrationScanFailures as C,migrateHeldMigrations as w,migrateLocalDb as T,readAppliedMigrationNames as ee,resetLocalDb as E,runDrizzleKitCommand as D,scanDeployMigrationFiles as O,seedLocalDb as te,setupLocalDb as ne,startProjectPostgres as k,stopProjectPostgres as A}from"@coreframe/db";import{checkFlutterClient as j,ensureFlutterDevAssetDirectories as re,flutterPlatforms as M,generateFlutterNativeBridge as ie,prepareFlutterClient as N,prepareFlutterDevOutput as ae,productionApiOrigin as P,runFlutterAcceptance as oe}from"@coreframe/flutter-tools";import F,{dirname as I,isAbsolute as se,join as L,posix as ce,resolve as R,sep as le}from"node:path";import z from"nano-spawn";import*as B from"@clack/prompts";import{addAsset as ue,buildAssets as de,checkAssets as fe,printAssetResult as pe,publishAssets as me}from"@coreframe/assets";import{assertAssetCredentialProfile as he,configureAssetCredentials as ge,createB2PrivateObjectStore as _e}from"@coreframe/object-storage";import{access as ve,chmod as ye,copyFile as be,cp as xe,link as Se,mkdir as V,mkdtemp as Ce,readFile as H,realpath as we,rename as Te,rm as U,stat as Ee,unlink as De,writeFile as W}from"node:fs/promises";import{homedir as Oe,networkInterfaces as ke,tmpdir as Ae}from"node:os";import{importProjectDependency as je,importProjectModule as Me,normalizeWorkerEnvironment as Ne,readProjectConfig as Pe,wranglerEnvironmentNames as Fe}from"@coreframe/config";import{createHash as Ie,randomUUID as Le}from"node:crypto";import G from"node:process";import{spawnSync as K}from"node:child_process";import{chmodSync as Re,existsSync as q,lstatSync as ze,mkdirSync as Be,mkdtempSync as Ve,readFileSync as J,readlinkSync as He,rmSync as Ue,symlinkSync as We,writeFileSync as Ge}from"node:fs";import{parse as Ke,stringify as qe}from"yaml";import{accessTokenSigningSecretName as Je,clearAppliedPendingWorkerSecrets as Ye,deployEnvironments as Xe,discardPendingWorkerSecret as Ze,discoverStagingUrl as Qe,inspectWorkerEnvironment as $e,materializePrimaryWorkerConfig as et,materializePrimaryWorkerTypeConfig as tt,parseDeclaredWorkerSecretEnv as nt,parseTauriReleasePlatform as rt,prepareAccessTokenSigningSecret as it,prepareTauriRelease as at,queueWorkerSecret as ot,queueWorkerSecrets as st,readDeclaredWorkerSecrets as ct,readPackageJson as lt,readPendingWorkerSecretSnapshot as ut,reassignStagingHostname as dt,releaseName as ft,resolveDeployConfig as pt,resolveReleaseVersion as mt,resolveTauriReleasePlan as ht,restoreTauriReleaseMetadata as gt,rotateAccessTokenSigningSecret as _t,runAfterWorkerDeploy as vt,runPostDeployChecks as yt,tauriReleasePlatforms as bt,uploadTauriReleaseToB2 as xt,validateTauriReleasePlan as St,validateWorkerEnvironmentForDeploy as Ct,verifyAccessTokenSigningSecret as wt,writePackageVersion as Tt,writeTauriReleaseMetadata as Et}from"@coreframe/deploy";import{connectDevSupervisor as Dt,createDevStartupTiming as Ot,devHttpsCertEnv as kt,devHttpsKeyEnv as At,isManagedDevCheckout as jt,isPrimaryCheckout as Mt,prepareDevHttps as Nt,stopDevSupervisor as Pt}from"@coreframe/dev";import{inspect as Ft,parseEnv as It}from"node:util";import{once as Lt}from"node:events";import{finished as Rt}from"node:stream/promises";import{codexTaskEnv as zt}from"@coreframe/dev-contracts/codex-task";import{managedDevEnv as Bt}from"@coreframe/dev-contracts/managed-dev";import{determineAgent as Vt}from"@vercel/detect-agent";import{createPrefixStream as Y,supervise as Ht}from"procband";import{createConnection as Ut,createServer as Wt}from"node:net";import{setTimeout as Gt}from"node:timers/promises";import{runPreview as Kt}from"@coreframe/preview";const qt=[`web`,...M];function Jt(e=`web`,{apiOrigin:t,cwd:n=process.cwd(),simulator:r=!1}={}){if($t(e,r),e===`web`)return[tn(`pnpm`,[`build`],n,{COREFRAME_PLATFORM:`web`})];let i=P(t);return[{kind:`prepare`,platform:e},tn(`flutter`,Yt(e,i,{simulator:r}),R(n,`src-flutter`),{COREFRAME_API_ORIGIN:i})]}function Yt(e,t,{noCodesign:n=e===`macos`,simulator:r=!1}={}){$t(e,r);let i=P(t);return[`build`,e===`android`?`apk`:e,`--release`,...r?[`--simulator`]:[],...n?[`--no-codesign`]:[],`--dart-define=COREFRAME_API_ORIGIN=${i}`]}function Xt(e){let t=R(e,`src-flutter/build/app/outputs/flutter-apk/app-release.apk`),n=JSON.stringify(t);return[`Android release build succeeded.`,``,`Install it on a connected Android device:`,` 1. Enable Developer options and USB debugging, connect the device, and accept the authorization prompt.`,` 2. Verify the device is visible:`,` adb devices`,` 3. Install or update the APK:`,` adb install -r ${n}`,``,`If multiple devices are connected, use:`,` adb -s <device-id> install -r ${n}`].join(`
3
- `)}function Zt(e,{simulator:t=!1}={}){let n=R(e,`src-flutter/build/ios/${t?`iphonesimulator`:`iphoneos`}/Runner.app`),r=JSON.stringify(n);return t?[`iOS Simulator release build succeeded.`,``,`Install it on a booted iOS Simulator:`,` 1. Verify available simulators:`,` xcrun simctl list devices`,` 2. Install the app:`,` xcrun simctl install booted ${r}`,``,"If multiple simulators are available, replace `booted` with the simulator UDID."].join(`
2
+ import*as e from"@alloc/cmd-ts";import{array as t,command as n,extendType as r,flag as i,multioption as a,number as o,oneOf as s,option as c,optional as l,positional as u,rest as d,string as f,subcommands as p}from"@alloc/cmd-ts";import{ProjectPostgresAlreadyRunningError as m,checkDeployMigrations as h,checkSchemaPush as g,collectDeployMigrationFiles as _,createProjectDeployDatabase as v,ensureLocalDb as y,filterPendingMigrations as b,formatDbErrorMessage as x,formatMigrationList as S,formatMigrationScanFailures as C,migrateHeldMigrations as w,migrateLocalDb as T,readAppliedMigrationNames as E,resetLocalDb as ee,runDrizzleKitCommand as te,scanDeployMigrationFiles as D,seedLocalDb as O,setupLocalDb as ne,startProjectPostgres as re,stopProjectPostgres as k}from"@coreframe/db";import{checkFlutterClient as A,ensureFlutterDevAssetDirectories as ie,flutterPlatforms as j,generateFlutterNativeBridge as ae,prepareFlutterClient as M,prepareFlutterDevOutput as oe,productionApiOrigin as N,runFlutterAcceptance as se}from"@coreframe/flutter-tools";import P,{dirname as F,isAbsolute as ce,join as I,posix as le,resolve as L,sep as ue}from"node:path";import R from"nano-spawn";import*as z from"@clack/prompts";import{addAsset as de,buildAssets as fe,checkAssets as pe,printAssetResult as me,publishAssets as he}from"@coreframe/assets";import{assertAssetCredentialProfile as ge,configureAssetCredentials as _e,createB2PrivateObjectStore as ve}from"@coreframe/object-storage";import{access as ye,chmod as be,copyFile as xe,cp as Se,link as Ce,mkdir as B,mkdtemp as we,readFile as V,realpath as Te,rename as Ee,rm as H,stat as De,unlink as Oe,writeFile as U}from"node:fs/promises";import{homedir as ke,networkInterfaces as Ae,tmpdir as je}from"node:os";import{importProjectDependency as Me,importProjectModule as Ne,normalizeWorkerEnvironment as Pe,readProjectConfig as Fe,wranglerEnvironmentNames as Ie}from"@coreframe/config";import{createHash as Le,randomUUID as W}from"node:crypto";import G from"node:process";import{spawnSync as K}from"node:child_process";import{chmodSync as Re,existsSync as q,lstatSync as ze,mkdirSync as Be,mkdtempSync as Ve,readFileSync as J,readlinkSync as He,rmSync as Ue,symlinkSync as We,writeFileSync as Ge}from"node:fs";import{parse as Ke,stringify as qe}from"yaml";import{accessTokenSigningSecretName as Je,clearAppliedPendingWorkerSecrets as Ye,deployEnvironments as Xe,discardPendingWorkerSecret as Ze,discoverStagingUrl as Qe,inspectWorkerEnvironment as $e,materializePrimaryWorkerConfig as et,materializePrimaryWorkerTypeConfig as tt,parseDeclaredWorkerSecretEnv as nt,parseTauriReleasePlatform as rt,prepareAccessTokenSigningSecret as it,prepareTauriRelease as at,queueWorkerSecret as ot,queueWorkerSecrets as st,readDeclaredWorkerSecrets as ct,readPackageJson as lt,readPendingWorkerSecretSnapshot as ut,reassignStagingHostname as dt,releaseName as ft,resolveDeployConfig as pt,resolveReleaseVersion as mt,resolveTauriReleasePlan as ht,restoreTauriReleaseMetadata as gt,rotateAccessTokenSigningSecret as _t,runAfterWorkerDeploy as vt,runPostDeployChecks as yt,tauriReleasePlatforms as bt,uploadTauriReleaseToB2 as xt,validateTauriReleasePlan as St,validateWorkerEnvironmentForDeploy as Ct,verifyAccessTokenSigningSecret as wt,writePackageVersion as Tt,writeTauriReleaseMetadata as Et}from"@coreframe/deploy";import{connectDevSupervisor as Dt,createDevStartupTiming as Ot,devHttpsCertEnv as kt,devHttpsKeyEnv as At,isManagedDevCheckout as jt,isPrimaryCheckout as Mt,prepareDevHttps as Nt,stopDevSupervisor as Pt}from"@coreframe/dev";import{inspect as Ft,parseEnv as It}from"node:util";import{once as Lt}from"node:events";import{finished as Rt}from"node:stream/promises";import{codexTaskEnv as zt}from"@coreframe/dev-contracts/codex-task";import{managedDevEnv as Bt}from"@coreframe/dev-contracts/managed-dev";import{createPrefixStream as Y,supervise as Vt}from"procband";import{createConnection as Ht,createServer as Ut}from"node:net";import{setTimeout as Wt}from"node:timers/promises";import{determineAgent as Gt}from"@vercel/detect-agent";import{runPreview as Kt}from"@coreframe/preview";const qt=[`web`,...j];function Jt(e=`web`,{apiOrigin:t,cwd:n=process.cwd(),simulator:r=!1}={}){if($t(e,r),e===`web`)return[tn(`pnpm`,[`build`],n,{COREFRAME_PLATFORM:`web`})];let i=N(t);return[{kind:`prepare`,platform:e},tn(`flutter`,Yt(e,i,{simulator:r}),L(n,`src-flutter`),{COREFRAME_API_ORIGIN:i})]}function Yt(e,t,{noCodesign:n=e===`macos`,simulator:r=!1}={}){$t(e,r);let i=N(t);return[`build`,e===`android`?`apk`:e,`--release`,...r?[`--simulator`]:[],...n?[`--no-codesign`]:[],`--dart-define=COREFRAME_API_ORIGIN=${i}`]}function Xt(e){let t=L(e,`src-flutter/build/app/outputs/flutter-apk/app-release.apk`),n=JSON.stringify(t);return[`Android release build succeeded.`,``,`Install it on a connected Android device:`,` 1. Enable Developer options and USB debugging, connect the device, and accept the authorization prompt.`,` 2. Verify the device is visible:`,` adb devices`,` 3. Install or update the APK:`,` adb install -r ${n}`,``,`If multiple devices are connected, use:`,` adb -s <device-id> install -r ${n}`].join(`
3
+ `)}function Zt(e,{simulator:t=!1}={}){let n=L(e,`src-flutter/build/ios/${t?`iphonesimulator`:`iphoneos`}/Runner.app`),r=JSON.stringify(n);return t?[`iOS Simulator release build succeeded.`,``,`Install it on a booted iOS Simulator:`,` 1. Verify available simulators:`,` xcrun simctl list devices`,` 2. Install the app:`,` xcrun simctl install booted ${r}`,``,"If multiple simulators are available, replace `booted` with the simulator UDID."].join(`
4
4
  `):[`iOS release build succeeded.`,``,`Install it on a connected iOS device:`,` 1. Enable Developer Mode, connect the device, and trust this Mac if prompted.`,` 2. Verify the device is visible:`,` xcrun devicectl list devices`,` 3. Install the signed app:`,` xcrun devicectl device install app --device <device-id> ${r}`,``,`If multiple devices are connected, use the device UDID shown by devicectl.`].join(`
5
- `)}async function Qt({apiOrigin:e,cwd:t=process.cwd(),environment:n=process.env,platform:r=`web`,simulator:i=!1,prepareClient:a=N,runCommand:o=en}={}){$t(r,i);let s={...n};delete s.COREFRAME_PLATFORM,delete s.TAURI_ENV_PLATFORM;let c=r===`web`?void 0:P(e??n.COREFRAME_API_ORIGIN);for(let e of Jt(r,{apiOrigin:c,cwd:t,simulator:i})){if(e.kind===`prepare`){if(!c)throw Error(`A production API origin is required for the Flutter ${e.platform} build.`);await a({apiOrigin:c,cwd:t,environment:s,platform:e.platform});continue}await o(e.command,e.args,{cwd:e.cwd,env:{...s,...e.environment}})}r===`android`?console.log(Xt(t)):r===`ios`&&console.log(Zt(t,{simulator:i}))}function $t(e,t){if(t&&e!==`ios`)throw Error(`The --simulator flag is only supported for the iOS build target.`)}async function en(e,t,{cwd:n,env:r}){await z(e,t,{cwd:n,env:r,stdio:`inherit`})}function tn(e,t,n,r){return{kind:`command`,command:e,args:t,cwd:n,...r===void 0?{}:{environment:r}}}const nn=r(f,{displayName:`origin`,description:`Exact production HTTPS API origin embedded in a packaged Flutter client.`,async from(e){return P(e)}}),rn=n({name:`build`,description:`Build the web client or a release Flutter app. Tauri is not built.`,args:{platform:u({type:l(s(qt)),displayName:`platform`,description:`Build target: web, iOS, Android, or macOS. Defaults to web.`}),apiOrigin:c({long:`api-origin`,type:l(nn),description:`Exact production HTTPS API origin for a Flutter build. Defaults to COREFRAME_API_ORIGIN.`}),simulator:i({long:`simulator`,description:`Build iOS for the simulator instead of a physical device.`,defaultValue:()=>!1})},handler:({apiOrigin:e,platform:t,simulator:n})=>Qt({apiOrigin:e,platform:t,simulator:n})}),an=/^[a-f0-9]{64}$/,on=/^[a-f0-9]{40}$/,sn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function cn(e){if(!an.test(e))throw Error(`Invalid SHA-256 digest "${e}".`);return e}function ln(e){if(!on.test(e))throw Error(`Invalid full Git revision "${e}".`);return e}function un(e,t){if(!sn.test(e))throw Error(`${t} must contain only letters, numbers, dots, underscores, or hyphens.`);return e}function dn(e){return`projects/${un(e,`Project ID`)}/i18n/v1`}function fn(e,t){return cn(t),`${dn(e)}/objects/sha256/${t.slice(0,2)}/${t}`}function pn(e,t){return ln(t),`${dn(e)}/commits/${t}.json`}function mn(e,t){return hn(t),`${dn(e)}/releases/${encodeURIComponent(t)}.json`}function hn(e){if(!e.startsWith(`v`)||e.length<2||e.length>128||/\s/.test(e)||e.includes(`..`))throw Error(`Release tag "${e}" must be a valid v-prefixed tag.`);return e}function X(e,t){if(!t||t.startsWith(`/`)||t.includes(`\0`))throw Error(`Unsafe i18n artifact path "${t}".`);let n=R(e),r=R(n,t);if(r!==n&&!r.startsWith(`${n}${le}`))throw Error(`Unsafe i18n artifact path "${t}".`);return r}function Z(e,t,n){return`${e.directory}/${t}/${n}.json`}function gn(e,t,n){return`${e.directory}/${t}/${n}.mjs`}async function _n(e){await z(`pnpm`,[`exec`,`lingui`,`extract`],{cwd:e,stdio:`inherit`})}async function vn({config:e,cwd:t,strict:n,temporaryDirectory:r}){let i=[];try{for(let n of e.locales)for(let a of e.catalogs){let o=X(t,Z(e,n,a)),s=await Cn(o),c=Object.fromEntries(Object.entries(s).filter(([,e])=>!e.obsolete)),l=L(r,`${n}-${a}.json`);await V(I(l),{recursive:!0}),await be(o,l),i.push({path:o,backup:l}),await wn(o,c)}await z(`pnpm`,[`exec`,`lingui`,`compile`,...n?[`--strict`]:[]],{cwd:t,stdio:`inherit`})}finally{try{for(let{path:e,backup:t}of i)await be(t,e)}finally{for(let n of e.locales)for(let r of e.catalogs)await U(X(t,gn(e,n,r)),{force:!0})}}}async function yn({config:e,cwd:t}){let n=[];for(let r of e.locales)if(r!==e.sourceLocale)for(let i of e.catalogs){let a=await Cn(X(t,Z(e,r,i)));for(let[e,t]of Object.entries(a)){if(t.obsolete||t.translation?.trim())continue;let a=t.message;if(typeof a!=`string`||!a)throw Error(`Missing source message metadata for ${r}:${e}.`);n.push({catalog:i,comments:t.comments?.filter(e=>typeof e==`string`)??[],context:t.context,id:e,locale:r,message:a,origins:t.origin?.map(([e,t])=>t?`${e}:${t}`:e)??[],placeholders:Object.keys(t.placeholders??{}).sort()})}}return n.sort((e,t)=>kn(e).localeCompare(kn(t)))}async function bn({config:e,cwd:t,messages:n,env:r=process.env}){if(n.length===0)return{translations:[],version:1};if(!e.generator)throw Error(`I18n preparation found ${n.length} missing translations, but no generator is configured.`);let i={messages:n,sourceLocale:e.sourceLocale,version:1};return Tn(await En({args:e.generator.args??[],command:e.generator.command,cwd:t,env:r,input:JSON.stringify(i)}))}async function xn({config:e,cwd:t,missing:n,response:r}){let i=new Map(n.map(e=>[kn(e),e])),a=new Map;for(let e of r.translations){let t=kn(e);if(!i.has(t))throw Error(`Translation generator returned unexpected entry ${e.locale}:${e.catalog}:${e.id}.`);if(a.has(t))throw Error(`Translation generator returned duplicate entry ${e.locale}:${e.catalog}:${e.id}.`);if(!e.translation.trim())throw Error(`Translation generator returned an empty entry ${e.locale}:${e.id}.`);a.set(t,e.translation)}let o=[...i.keys()].filter(e=>!a.has(e));if(o.length>0)throw Error(`Translation generator omitted ${o.length} required entries.`);let s=await je(`@lingui/message-utils/compileMessage`,t);for(let e of n){let t=a.get(kn(e));Dn({compileMessage:s,id:e.id,locale:e.locale,source:e.message,translation:t})}for(let n of e.locales)if(n!==e.sourceLocale)for(let r of e.catalogs){let i=X(t,Z(e,n,r)),o=await Cn(i),s=!1;for(let[e,t]of Object.entries(o)){let i=a.get(kn({catalog:r,id:e,locale:n}));if(i!==void 0){if(t.translation?.trim())throw Error(`Refusing to overwrite preserved translation ${n}:${e}.`);t.translation=i,s=!0}}s&&await wn(i,o)}}async function Sn({config:e,cwd:t}){let n=await yn({config:e,cwd:t});if(n.length>0)throw Error(`I18n catalogs remain incomplete: ${n.length} translations are missing.`);let r=await je(`@lingui/message-utils/compileMessage`,t);for(let n of e.locales)if(n!==e.sourceLocale)for(let i of e.catalogs){let a=await Cn(X(t,Z(e,n,i)));for(let[e,t]of Object.entries(a))if(!t.obsolete){if(typeof t.message!=`string`||typeof t.translation!=`string`)throw Error(`Incomplete source metadata for active translation ${n}:${e}.`);Dn({compileMessage:r,id:e,locale:n,source:t.message,translation:t.translation})}}}async function Cn(e){let t=JSON.parse(await H(e,`utf8`));if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Lingui rich JSON catalog must be an object: ${e}.`);for(let[n,r]of Object.entries(t)){if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`Invalid Lingui rich JSON message ${n} in ${e}.`);let t=r;if(t.translation!==void 0&&typeof t.translation!=`string`)throw Error(`Invalid translation value for ${n} in ${e}.`);if(t.message!==void 0&&t.message!==null&&typeof t.message!=`string`)throw Error(`Invalid source message value for ${n} in ${e}.`);if(t.context!==void 0&&typeof t.context!=`string`)throw Error(`Invalid context value for ${n} in ${e}.`);if(t.obsolete!==void 0&&typeof t.obsolete!=`boolean`)throw Error(`Invalid obsolete marker for ${n} in ${e}.`);if(t.comments!==void 0&&(!Array.isArray(t.comments)||t.comments.some(e=>typeof e!=`string`)))throw Error(`Invalid comments for ${n} in ${e}.`);if(t.origin!==void 0&&(!Array.isArray(t.origin)||t.origin.some(e=>!Array.isArray(e)||typeof e[0]!=`string`||e[1]!==void 0&&typeof e[1]!=`number`)))throw Error(`Invalid origins for ${n} in ${e}.`);if(t.placeholders!==void 0&&(!t.placeholders||typeof t.placeholders!=`object`||Array.isArray(t.placeholders)))throw Error(`Invalid placeholders for ${n} in ${e}.`)}return t}async function wn(e,t){await V(I(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;await W(n,`${JSON.stringify(t,null,2)}\n`),await Te(n,e)}function Tn(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Translation generator returned invalid JSON.`)}if(!t||typeof t!=`object`||t.version!==1||!Array.isArray(t.translations))throw Error(`Translation generator returned an invalid response envelope.`);for(let e of t.translations)if(!e||typeof e!=`object`||typeof e.id!=`string`||typeof e.catalog!=`string`||typeof e.locale!=`string`||typeof e.translation!=`string`)throw Error(`Translation generator returned an invalid translation entry.`);return t}function En({args:e,command:t,cwd:n,env:r,input:i}){return z(t,e,{cwd:n,env:r,stdio:[{string:i},`pipe`,`ignore`]}).then(({stdout:e})=>{if(Buffer.byteLength(e)>10*1024*1024)throw Error(`Translation generator output exceeded 10 MiB.`);return e}).catch(()=>{throw Error(`Translation generator exited unsuccessfully.`)})}function Dn({compileMessage:e,id:t,locale:n,source:r,translation:i}){let a,o;try{a=e.compileMessageOrThrow(r),o=e.compileMessageOrThrow(i)}catch{throw Error(`Translation ${n}:${t} is not valid ICU MessageFormat.`)}let s=On(a),c=On(o);if(s.length!==c.length||s.some((e,t)=>e!==c[t]))throw Error(`Translation ${n}:${t} does not preserve source ICU placeholders.`)}function On(e){let t=[];function n(e){for(let r of e){if(typeof r==`string`)continue;let[e,i=`argument`,a]=r;if(t.push(`${e}:${i}`),a&&typeof a==`object`&&!Array.isArray(a))for(let e of Object.values(a))Array.isArray(e)&&n(e)}}return n(e),t.sort()}function kn(e){return`${e.locale}\0${e.catalog}\0${e.id}`}function An(e){return Ie(`sha256`).update(e).digest(`hex`)}async function jn(e){return An(await H(e))}function Mn(e){return Buffer.from(`${JSON.stringify(e,null,2)}\n`)}async function Nn({bucket:e,digest:t,projectId:n,source:r,store:i}){if(cn(t),await jn(r)!==t)throw Error(`I18n object source does not match declared SHA-256 digest ${t}.`);let a=fn(n,t);await i.has(e,a)||await i.upload(e,a,r,`application/octet-stream`);let o=`${r}.${process.pid}.${Le()}.verify`;try{if(await i.download(e,a,o),await jn(o)!==t)throw Error(`Existing immutable i18n object ${a} failed integrity verification.`)}finally{await U(o,{force:!0})}}async function Pn({bucket:e,key:t,reference:n,store:r,temporaryDirectory:i}){let a=Mn(n),o=L(i,`reference-${Le()}.json`);if(await r.has(e,t))try{if(await r.download(e,t,o),!(await H(o)).equals(a))throw Error(`Immutable i18n reference ${t} already resolves to different snapshot data.`);return}finally{await U(o,{force:!0})}await W(o,a,{flag:`wx`});try{await r.upload(e,t,o,`application/json`)}finally{await U(o,{force:!0})}let s=L(i,`reference-${Le()}.verify.json`);try{if(await r.download(e,t,s),!(await H(s)).equals(a))throw Error(`Uploaded immutable i18n reference ${t} failed verification.`)}finally{await U(s,{force:!0})}}async function Fn({bucket:e,manifest:t,projectId:n,store:r,temporaryDirectory:i}){let a=Mn(t),o=An(a),s=L(i,`manifest-${o}.json`);await W(s,a,{flag:`wx`});try{await Nn({bucket:e,digest:o,projectId:n,source:s,store:r})}finally{await U(s,{force:!0})}return o}async function In({bucket:e,key:t,store:n,temporaryDirectory:r}){if(!await n.has(e,t))return;let i=L(r,`reference-${Le()}.json`);try{await n.download(e,t,i);let r=JSON.parse(await H(i,`utf8`));if(r.version!==1||typeof r.revision!=`string`||typeof r.snapshot!=`string`)throw Error(`Invalid i18n reference at ${t}.`);return ln(r.revision),cn(r.snapshot),r}finally{await U(i,{force:!0})}}async function Ln({bucket:e,projectId:t,revision:n,store:r,temporaryDirectory:i}){let a=await In({bucket:e,key:pn(t,n),store:r,temporaryDirectory:i});if(a&&a.revision!==n)throw Error(`I18n commit reference does not match requested revision ${n}.`);return a}async function Rn({bucket:e,projectId:t,reference:n,store:r,tag:i,temporaryDirectory:a}){await Pn({bucket:e,key:pn(t,n.revision),reference:n,store:r,temporaryDirectory:a}),i&&await Pn({bucket:e,key:mn(t,i),reference:n,store:r,temporaryDirectory:a})}async function zn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,target:a}){cn(n);let o=L(R(t),`v1`,`sha256`,n.slice(0,2),n);if(await Vn(o,n)===!1){await V(I(o),{recursive:!0});let t=`${o}.${process.pid}.${Le()}.tmp`;try{if(await i.download(e,fn(r,n),t),await jn(t)!==n)throw Error(`Downloaded i18n object failed SHA-256 verification: ${n}.`);await U(o,{force:!0}),await Te(t,o)}finally{await U(t,{force:!0})}}await V(I(a),{recursive:!0});let s=`${a}.${process.pid}.${Le()}.tmp`;try{if(await be(o,s),await jn(s)!==n)throw Error(`Cached i18n object failed SHA-256 verification: ${n}.`);await U(a,{force:!0}),await Te(s,a)}finally{await U(s,{force:!0})}}async function Bn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,temporaryDirectory:a}){let o=L(a,`manifest-${n}.json`);await zn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,target:o});let s=JSON.parse(await H(o,`utf8`));if(s.version!==1||s.projectId!==r||typeof s.revision!=`string`||!Array.isArray(s.files)||!Array.isArray(s.catalogs)||s.catalogs.some(e=>typeof e!=`string`)||!Array.isArray(s.locales)||s.locales.some(e=>typeof e!=`string`)||typeof s.sourceLocale!=`string`||typeof s.generator!=`string`||typeof s.linguiVersion!=`string`)throw Error(`Invalid i18n snapshot manifest ${n}.`);ln(s.revision),s.baseline!==void 0&&cn(s.baseline);for(let e of s.files){if(!e||typeof e!=`object`||typeof e.path!=`string`||typeof e.digest!=`string`||typeof e.size!=`number`)throw Error(`Invalid file entry in i18n snapshot manifest ${n}.`);cn(e.digest)}return s}async function Vn(e,t){try{return(await Ee(e)).isFile()&&await jn(e)===t}catch{return!1}}async function Hn({cwd:e=process.cwd(),env:t=process.env}={}){if((await Pe({cwd:e})).i18n){if(t.COREFRAME_I18N_RELEASE_REVISION){await Gn({cwd:e,env:t,revision:t.COREFRAME_I18N_RELEASE_REVISION});return}await _n(e)}}async function Un({cwd:e=process.cwd(),projectConfig:t}={}){let n=t??await Pe({cwd:e});if(!n.i18n)return;let r=Kn(n.i18n),i=X(e,r.directory);try{if(!(await Ee(i)).isDirectory())throw Error(`I18n catalog path is not a directory: ${i}.`)}catch(t){if(t.code!==`ENOENT`)throw t;await _n(e);return}for(let t of r.locales)for(let n of r.catalogs)try{if(!(await Ee(X(e,Z(r,t,n)))).isFile())throw Error(`I18n catalog path is not a file: ${t}/${n}.json.`)}catch(t){if(t.code!==`ENOENT`)throw t;await _n(e);return}}async function Wn({cwd:e=process.cwd(),env:t=process.env,store:n,tag:r}){hn(r);let i=await qn({cwd:e,env:t,store:n});await tr(e);let a=await er(e);await nr(e,r,a);let o=await Ce(L(Ae(),`coreframe-i18n-prepare-`));try{let n=await Ln({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,revision:a,store:i.store,temporaryDirectory:o});if(n){let e=await Bn({bucket:i.assets.sourceBucket,cacheRoot:i.cacheRoot,digest:n.snapshot,projectId:i.assets.projectId,store:i.store,temporaryDirectory:o});return $n(i,e,a),await Yn(i,e),await Rn({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,reference:n,store:i.store,tag:r,temporaryDirectory:o}),{reused:!0,snapshot:n.snapshot}}return await Qn(i,o,async()=>{let n=await Jn(i,a,o);n||await Zn(i),await _n(e);let s=await yn({config:i.config,cwd:e}),c=await bn({config:i.config,cwd:e,env:t,messages:s});await xn({config:i.config,cwd:e,missing:s,response:c}),await Sn({config:i.config,cwd:e}),await vn({config:i.config,cwd:e,strict:!0,temporaryDirectory:o});let l=await Xn(i),u={...n?{baseline:n}:{},catalogs:i.config.catalogs,files:l,generator:s.length>0?i.config.generator?.id??`unconfigured`:`none`,linguiVersion:await rr(e),locales:i.config.locales,projectId:i.assets.projectId,revision:a,sourceLocale:i.config.sourceLocale,version:1},d=await Fn({bucket:i.assets.sourceBucket,manifest:u,projectId:i.assets.projectId,store:i.store,temporaryDirectory:o});return await Rn({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,reference:{revision:a,snapshot:d,version:1},store:i.store,tag:r,temporaryDirectory:o}),{reused:!1,snapshot:d}})}finally{await U(o,{force:!0,recursive:!0})}}async function Gn({cwd:e=process.cwd(),env:t=process.env,revision:n,store:r}={}){let i=await Pe({cwd:e});if(!i.i18n)return;let a=await qn({cwd:e,env:t,store:r,projectConfig:i}),o=ln(n??await er(e)),s=await Ce(L(Ae(),`coreframe-i18n-materialize-`));try{let e=await Ln({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,revision:o,store:a.store,temporaryDirectory:s});if(!e)throw Error(`No prepared i18n snapshot exists for commit ${o}. Push a v* tag for this commit and wait for the translation gate.`);let t=await Bn({bucket:a.assets.sourceBucket,cacheRoot:a.cacheRoot,digest:e.snapshot,projectId:a.assets.projectId,store:a.store,temporaryDirectory:s});return $n(a,t,o),await Yn(a,t),{revision:o,snapshot:e.snapshot}}finally{await U(s,{force:!0,recursive:!0})}}function Kn(e){let t=un(e.sourceLocale,`Source locale`),n=[...new Set(e.locales.map(e=>un(e,`Locale`)))],r=[...new Set(e.catalogs.map(e=>un(e,`Catalog`)))];if(n.length===0||!n.includes(t))throw Error(`I18n locales must include the source locale.`);if(r.length===0)throw Error(`I18n configuration requires at least one catalog.`);if(e.generator&&(!e.generator.command.trim()||!e.generator.id.trim()))throw Error(`I18n generator command and ID must be non-empty.`);return{catalogs:r,directory:e.directory??`locales`,generator:e.generator,locales:n,sourceLocale:t}}async function qn({cwd:e=process.cwd(),env:t=process.env,projectConfig:n,store:r}){let i=n??await Pe({cwd:e});if(!i.i18n)throw Error(`Missing i18n configuration in coreframe.config.ts.`);if(!i.assets)throw Error(`I18n snapshots require the existing private build bucket configured under assets.`);let a=i.assets;return{assets:a,cacheRoot:R(e,`.coreframe`,`i18n`,`cache`),config:Kn(i.i18n),cwd:R(e),env:t,store:r??_e({config:a,env:t})}}async function Jn(e,t,n){let{stdout:r}=await z(`git`,[`rev-list`,`--first-parent`,`--skip=1`,t],{cwd:e.cwd,stdin:`ignore`});for(let t of r.split(/\r?\n/).filter(Boolean)){let r=await Ln({bucket:e.assets.sourceBucket,projectId:e.assets.projectId,revision:ln(t),store:e.store,temporaryDirectory:n});if(!r)continue;let i=await Bn({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:r.snapshot,projectId:e.assets.projectId,store:e.store,temporaryDirectory:n});return $n(e,i,t),await Yn(e,i),r.snapshot}}async function Yn(e,t){for(let n of t.files)if(await zn({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:n.digest,projectId:e.assets.projectId,store:e.store,target:X(e.cwd,n.path)}),(await Ee(X(e.cwd,n.path))).size!==n.size)throw Error(`Materialized i18n artifact size does not match manifest: ${n.path}.`)}async function Xn(e){let t=[];for(let n of e.config.locales)for(let r of e.config.catalogs){let i=Z(e.config,n,r),a=X(e.cwd,i),o=await jn(a);await Nn({bucket:e.assets.sourceBucket,digest:o,projectId:e.assets.projectId,source:a,store:e.store}),t.push({digest:o,path:i,size:(await Ee(a)).size})}return t.sort((e,t)=>e.path.localeCompare(t.path))}async function Zn(e){let{stdout:t}=await z(`git`,[`rev-parse`,`--show-prefix`],{cwd:e.cwd,stdin:`ignore`}),n=t.trim(),{stdout:r}=await z(`git`,[`log`,`-1`,`--format=%H`,`--diff-filter=AM`,`--`,`:(top)${`${n}${e.config.directory}/${e.config.sourceLocale}/${e.config.catalogs[0]}.po`}`],{cwd:e.cwd,stdin:`ignore`}),i=r.trim();if(!i)return!1;let a=(await je(`@lingui/format-po`,e.cwd)).formatter({lineNumbers:!1}),o=!1;for(let t of e.config.locales)for(let r of e.config.catalogs){let s=`${n}${`${e.config.directory}/${t}/${r}.po`}`;try{let{stdout:n}=await z(`git`,[`show`,`${i}:${s}`],{cwd:e.cwd,stdin:`ignore`});await wn(X(e.cwd,Z(e.config,t,r)),a.parse(n)),o=!0}catch{}}return o}async function Qn(e,t,n){let r=[];for(let n of e.config.locales)for(let i of e.config.catalogs){let a=Z(e.config,n,i),o=X(e.cwd,a);try{await ve(o)}catch{continue}let s=L(t,`previous-catalogs`,a);await V(I(s),{recursive:!0}),await Te(o,s),r.push({backup:s,path:o})}try{let e=await n();return await U(L(t,`previous-catalogs`),{force:!0,recursive:!0}),e}catch(t){for(let t of e.config.locales)for(let n of e.config.catalogs)await U(X(e.cwd,Z(e.config,t,n)),{force:!0});for(let{backup:e,path:t}of r)await V(I(t),{recursive:!0}),await Te(e,t);throw t}}function $n(e,t,n){if(t.revision!==n||t.projectId!==e.assets.projectId||t.sourceLocale!==e.config.sourceLocale||JSON.stringify(t.locales)!==JSON.stringify(e.config.locales)||JSON.stringify(t.catalogs)!==JSON.stringify(e.config.catalogs))throw Error(`I18n snapshot does not match commit or project configuration.`);let r=e.config.locales.flatMap(t=>e.config.catalogs.map(n=>Z(e.config,t,n))),i=t.files.map(e=>e.path);if(new Set(i).size!==i.length||JSON.stringify(i.sort())!==JSON.stringify(r.sort()))throw Error(`I18n snapshot has an incomplete or unexpected artifact set.`)}async function er(e){let{stdout:t}=await z(`git`,[`rev-parse`,`HEAD`],{cwd:e,stdin:`ignore`});return ln(t.trim())}async function tr(e){let{stdout:t}=await z(`git`,[`status`,`--porcelain`],{cwd:e,stdin:`ignore`});if(t.trim())throw Error(`Tagged i18n preparation requires a clean Git tree.`)}async function nr(e,t,n){let{stdout:r}=await z(`git`,[`rev-parse`,`${t}^{commit}`],{cwd:e,stdin:`ignore`});if(r.trim()!==n)throw Error(`Release tag ${t} does not point to checked-out commit ${n}.`)}async function rr(e){let{stdout:t}=await z(`pnpm`,[`exec`,`lingui`,`--version`],{cwd:e,stdin:`ignore`});return t.trim()}const ir=[`Use a B2 Multi-Bucket Application Key restricted to the configured private build-object and public generated-assets buckets.`,`Required capabilities: listAllBucketNames, readFiles, and writeFiles.`,`Deletion, bucket-management, and key-management capabilities are not needed.`].join(` `),ar=r(f,{displayName:`widths`,description:`Comma-separated responsive variant widths.`,async from(e){let t=e.split(`,`).map(e=>Number(e));if(t.length===0||t.some(e=>!Number.isInteger(e)||e<=0)||t.some((e,n)=>n>0&&e<=t[n-1]))throw Error(`Widths must be positive, unique, strictly ascending integers.`);return t}}),or=r(f,{displayName:`profile`,async from(e){return he(e)}}),sr=r(f,{displayName:`pack`,description:`Asset pack name, such as training-videos.`,async from(e){if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e))throw Error(`Asset pack names must use lowercase hyphen-separated segments.`);return e}}),cr=r(f,{displayName:`origin`,description:`Exact production HTTPS API origin embedded in the packaged Flutter client.`,async from(e){return P(e)}}),lr=p({name:`assets`,cmds:{configure:n({name:`configure`,description:`Store a Backblaze B2 private build-object key in the operating system credential store. ${ir}`,args:{profile:u({type:or,displayName:`profile`,description:`Credential profile named by coreframe.config.ts.`})},handler:async({profile:e})=>{B.note(ir,`Required B2 key access`);let t=await B.text({message:`Backblaze B2 application key ID`,validate:e=>e?.trim()?void 0:`The application key ID is required.`});if(B.isCancel(t))throw Error(`Asset credential configuration was cancelled.`);let n=await B.password({message:`Backblaze B2 application key`,validate:e=>e?void 0:`The application key is required.`});if(B.isCancel(n))throw Error(`Asset credential configuration was cancelled.`);await ge({applicationKey:n,applicationKeyId:t.trim(),profile:e}),console.log(`Stored Coreframe asset credential profile "${e}".`)}}),add:n({name:`add`,args:{file:u({type:f,displayName:`file`,description:`Source raster image, SVG, MP3, MP4, or Lottie JSON to add to the asset library.`}),id:c({long:`id`,type:f,description:`Logical asset ID, such as blog/my-post/hero.`}),alt:c({long:`alt`,type:l(f),description:`Required alt text for raster image and SVG assets.`}),pack:c({long:`pack`,type:l(sr),description:`Place the asset in a named, lazily loaded pack.`}),variantWidths:c({long:`widths`,type:l(ar),description:`Generate exactly these raster-image widths instead of the default ladder.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({alt:e,file:t,id:n,json:r,pack:i,variantWidths:a})=>pe(await ue({alt:e,file:t,id:n,pack:i,variantWidths:a}),r)}),build:n({name:`build`,args:{id:c({long:`id`,type:l(f),description:`Build only one logical asset ID.`}),pack:c({long:`pack`,type:l(sr),description:`Build only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({id:e,json:t,pack:n})=>pe(await de({id:e,pack:n}),t)}),check:n({name:`check`,args:{fix:i({long:`fix`,description:`Migrate asset state and build missing generated output when possible.`,defaultValue:()=>!1}),pack:c({long:`pack`,type:l(sr),description:`Check only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({fix:e,json:t,pack:n})=>{let r=await fe({fix:e,pack:n});pe(r,t),r.ok||(process.exitCode=1)}}),publish:n({name:`publish`,args:{pack:c({long:`pack`,type:l(sr),description:`Publish only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,pack:t})=>{let n=await me({pack:t});pe(n,e),n.ok||(process.exitCode=1)}}),status:n({name:`status`,args:{pack:c({long:`pack`,type:l(sr),description:`Report status for only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,pack:t})=>{let n=await fe({pack:t});pe(n,e),n.ok||(process.exitCode=1)}})}}),ur=p({name:`flutter`,cmds:{acceptance:n({name:`acceptance`,description:`Run the complete packaged Flutter conformance gate on macOS.`,args:{apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e})=>oe({environment:{...process.env,COREFRAME_API_ORIGIN:e}})}),codegen:n({name:`codegen`,description:`Generate Flutter bridge contracts and Panda-backed Mix theme tokens.`,args:{check:i({long:`check`,description:`Fail when generated Flutter artifacts are missing or stale.`,defaultValue:()=>!1})},handler:({check:e})=>ie({check:e})}),prepare:n({name:`prepare`,description:`Build and package the React client for one Flutter platform.`,args:{platform:u({type:s(M),displayName:`platform`,description:`Flutter platform whose packaged client should be prepared.`}),apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e,platform:t})=>N({apiOrigin:e,platform:t})}),check:n({name:`check`,description:`Reject missing, stale, modified, or incorrectly targeted Flutter assets.`,args:{platform:u({type:s(M),displayName:`platform`,description:`Flutter platform whose packaged client should be checked.`}),apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e,platform:t})=>j({apiOrigin:e,platform:t})})}}),dr=p({name:`i18n`,cmds:{build:n({name:`build`,description:`Extract source messages or materialize an exact release catalog snapshot.`,args:{},handler:async()=>{await Hn()}}),materialize:n({name:`materialize`,description:`Materialize the immutable i18n snapshot for an exact commit.`,args:{revision:c({long:`revision`,type:l(f),description:`Full commit SHA. Defaults to the checked-out commit.`})},handler:async({revision:e})=>{let t=await Gn({revision:e});t&&console.log(`Materialized i18n snapshot ${t.snapshot}.`)}}),prepare:n({name:`prepare`,description:`Fill missing translations, strictly compile, and publish an immutable tagged snapshot.`,args:{tag:c({long:`tag`,type:f,description:`Pushed v* release tag that points to the checked-out commit.`})},handler:async({tag:e})=>{let t=await Wn({tag:e});console.log(`${t.reused?`Reused`:`Published`} i18n snapshot ${t.snapshot}.`)}})}}),fr=G.platform===`win32`?`react-router.cmd`:`react-router`,pr=G.platform===`win32`?`panda.cmd`:`panda`;async function mr(e=G.cwd()){await _r(e),await gr(e,[`typegen`])}async function hr(e=G.cwd(),t=G.env){if((t.COREFRAME_PLATFORM??t.TAURI_ENV_PLATFORM??`web`)!==`web`)return;let n=F.resolve(e,`.coreframe/dashboard-build`),r=F.join(n,`client`),i=F.resolve(e,`dist/client/__dashboard`);await U(n,{force:!0,recursive:!0}),await vr(e,pr,[`build`],t),await gr(e,[`build`],t),await U(i,{force:!0,recursive:!0}),await V(F.dirname(i),{recursive:!0}),await xe(r,i,{recursive:!0})}async function gr(e,t,n=G.env){await vr(e,fr,t,n)}async function _r(e){await U(F.resolve(e,`dashboard/.react-router`),{force:!0,recursive:!0})}async function vr(e,t,n,r=G.env){await z(t,n,{cwd:F.resolve(e,`dashboard`),env:{...r,PATH:F.resolve(e,`node_modules/.bin`)+F.delimiter+(r.PATH??r.Path??``)},stdio:`inherit`})}const yr=p({name:`dashboard`,cmds:{build:n({name:`build`,args:{},handler:()=>hr()}),typegen:n({name:`typegen`,args:{},handler:()=>mr()})}}),br=/^[a-z0-9]+(?:-[a-z0-9]+)*$/u;function xr(e,t){let n=Cr(e,t);if(!wr(n)||!Tr(n,[`description`,`requires`,`routes`,`verifier`])||!Dr(n.description)||n.requires!==void 0&&(!Array.isArray(n.requires)||!n.requires.every(Dr))||n.verifier!==void 0&&!Dr(n.verifier)||!Array.isArray(n.routes))throw Error(`${t} must contain a description string, routes array, and optional requires and verifier fields.`);let r=(n.requires??[]).map(e=>Sr(e));if(new Set(r).size!==r.length)throw Error(`${t} contains duplicate recipe requirements.`);let i=n.routes.map((e,n)=>{if(!wr(e)||!Er(e,[`path`,`router`,`when`])||!Dr(e.path)||!Dr(e.router)||!Dr(e.when))throw Error(`${t} route ${n+1} must contain router, path, and when strings.`);return{path:e.path,router:e.router,when:e.when}}),a=i.map(e=>`${e.router}\0${e.path}`);if(new Set(a).size!==a.length)throw Error(`${t} contains a duplicate router and path pair.`);return{description:n.description,requires:r,routes:i,verifier:n.verifier}}function Sr(e){if(!br.test(e))throw Error(`Recipe names use lowercase letters, numbers, and single hyphens.`);return e}function Cr(e,t){try{return Ke(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function wr(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Tr(e,t){return Object.keys(e).every(e=>t.includes(e))}function Er(e,t){let n=Object.keys(e).sort();return n.length===t.length&&n.every((e,n)=>e===t[n])}function Dr(e){return typeof e==`string`&&e.length>0}const Or=`https://github.com/airlock-labs/coreframe.git`;function kr(e,t){return K(`git`,e,{cwd:t,encoding:`utf8`})}function Ar(e,t){let n=kr(e,t);if(n.status!==0){let t=n.stderr.trim()||n.stdout.trim();throw Error(`Git command failed: git ${e.join(` `)}${t?`\n${t}`:``}`)}return n.stdout}function jr(e,t){let n=kr([`remote`,`get-url`,e],t);if(n.status===2)return null;if(n.status!==0){let t=n.stderr.trim()||n.stdout.trim();throw Error(`Could not inspect remote ${e}.${t?`\n${t}`:``}`)}return n.stdout.trim()}function Mr({cwd:e=process.cwd(),fetch:t=!0,remote:n=`template`}={}){if(n.length===0)throw Error(`Remote name must not be empty.`);Ar([`rev-parse`,`--show-toplevel`],e);let r=jr(n,e);if(r===null)Ar([`remote`,`add`,n,Or],e),console.log(`Added ${n} remote: ${Or}`);else if(r===Or)console.log(`${n} remote already points at ${Or}`);else throw Error(`${n} remote points at ${r}, not ${Or}.\nChoose the intended template source before continuing, then update or rename the remote manually.`);t&&(Ar([`fetch`,n,`--tags`,`--prune`],e),console.log(`Fetched ${n}.`))}const Nr=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;function Pr(e){return Nr.test(e)?`v${e}`:e}function Fr(e){return`${Pr(e)}:template`}function Ir(e,t){return`${Fr(e)}/${t}`}function Lr({cwd:e=process.cwd(),fetch:t=!0,remote:n=`template`,target:r}={}){let i=Vr(e),a=Gr(i,[`rev-parse`,`--show-toplevel`]),o=Pr(r??Hr(i));return Mr({cwd:a,fetch:t,remote:n}),{projectRoot:i,ref:o,repositoryRoot:a}}function Rr(e,t,n){return zr(e,t,n).toString(`utf8`)}function zr(e,t,n){let r=`${t}:${n}`,i=K(`git`,[`show`,r],{cwd:e,encoding:`buffer`});if(i.status!==0)throw Error(`Could not read ${r}. ${Kr([`show`,r],i)}`);return i.stdout}function Br(e,t,n){let r=K(`git`,[`ls-tree`,`-r`,`--name-only`,`-z`,t,`--`,n],{cwd:e,encoding:`buffer`});if(r.status!==0)throw Error(Kr([`ls-tree`,t,n],r));return r.stdout.toString(`utf8`).split(`\0`).filter(Boolean)}function Vr(e){let t=R(e);for(;;){let e=L(t,`package.json`),n=Wr(e);if(n!==void 0&&Ur(n,e).engines?.coreframe)return t;let r=I(t);if(r===t)throw Error(`Could not find a package.json with engines.coreframe.`);t=r}}function Hr(e){let t=L(e,`package.json`),n=Wr(t);if(n===void 0)throw Error(`Required file package.json does not exist.`);let r=Ur(n,t).engines?.coreframe;if(!r)throw Error(`package.json must declare an exact engines.coreframe recipe baseline.`);return r}function Ur(e,t){try{return JSON.parse(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function Wr(e){try{return J(e,`utf8`)}catch(e){if(qr(e)&&e.code===`ENOENT`)return;throw e}}function Gr(e,t){let n=K(`git`,t,{cwd:e,encoding:`utf8`});if(n.status!==0)throw Error(Kr(t,n));return n.stdout.trim()}function Kr(e,t){let n=t.stderr.toString(`utf8`).trim()||t.stdout.toString(`utf8`).trim();return`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`}function qr(e){return e instanceof Error&&`code`in e}const Jr=[{path:`package.json`,requirement:`retain the Coreframe Flutter JavaScript runtime used by src-flutter`,test:e=>e.includes(`"@coreframe/flutter-js"`)},{path:`coreframe.config.ts`,requirement:`enable web and at least one Flutter development platform`,test:Zr},{path:`src/api/client/app-origin.ts`,requirement:`allow the Flutter shell to provide its exact API origin`,test:e=>Xr(e,[`@coreframe/flutter-js/client`,`resolveAppOrigin`,`browserOrigin: location?.origin`])},{path:`src/api/worker/auth-config.ts`,requirement:`trust the exact Flutter authentication origins`,test:e=>Xr(e,[`appendFlutterAuthOrigins`,`appendFlutterAuthOrigins([], development)`])},{path:`src/api/worker/middleware/auth.ts`,requirement:`broker Flutter access tokens and accept only Flutter bearer origins`,test:e=>Xr(e,[`createFlutterAccessTokenResponse`,`isFlutterAuthOrigin(origin, import.meta.env.DEV)`,`readFlutterBearerToken`,`native && ctx.request.method !== "GET"`])&&!e.includes(`isNativeOrigin`)},{path:`src/api/worker/middleware/flutter-cors.ts`,requirement:`provide the Flutter packaged-origin CORS boundary`,test:e=>Xr(e,[`applyFlutterCors`,`handleFlutterCorsPreflight`,`flutterCorsMiddleware`])},{path:`src/api/worker/middleware/index.ts`,requirement:`apply Flutter CORS to ordinary Worker responses`,test:e=>e.includes(`flutterCorsMiddleware`)},{path:`src/web/app/flutter-shell/application.ts`,requirement:`configure the Flutter shell's app-owned query and session hooks`,test:e=>Xr(e,[`configureShellQueryFocus`,`authSessionHint`])},{path:`src/web/dev/flutter-devtools.ts`,requirement:`install the Flutter development tools bridge`,test:e=>e.includes(`installFlutterDevTools`)},{path:`src/web/entry.client.tsx`,requirement:`load Flutter development tools only for non-browser development`,test:e=>Xr(e,[`./dev/flutter-devtools.ts`,`import.meta.env.PLATFORM !== "web"`])}];function Yr(e){let t=[];for(let n of Jr){let r=L(e,n.path);if(!q(r)){t.push(`${n.path} is missing; it must ${n.requirement}.`);continue}let i=J(r,`utf8`);n.test(i)||t.push(`${n.path} must ${n.requirement}.`)}return t}function Xr(e,t){return t.every(t=>e.includes(t))}function Zr(e){let t=e.match(/\bplatforms\s*:\s*\[([\s\S]*?)\]/)?.[1];if(!t)return!1;let n=new Set([...t.matchAll(/(["'`])([^"'`]*)\1/g)].map(e=>e[2]));return n.has(`web`)&&[`ios`,`android`,`macos`].some(e=>n.has(e))}const Qr=[{path:`package.json`,requirement:`declare the Tauri CLI, plugin-log, and Coreframe Tauri runtime packages`,test:e=>Q(e,[`"@tauri-apps/cli"`,`"@tauri-apps/plugin-log"`,`"@coreframe/tauri-js"`,`"@coreframe/tauri-plugin-auth-session"`])},{path:`src-tauri/Cargo.toml`,requirement:`declare Tauri, plugin-log, and Coreframe auth-session Rust dependencies`,test:e=>Q(e,[`tauri-build`,`tauri-plugin-log`,`coreframe-tauri-plugin-auth-session`])},{path:`src-tauri/src/main.rs`,requirement:`launch the project-owned Tauri Rust library`,test:e=>e.includes(`::run();`)},{path:`src-tauri/src/lib.rs`,requirement:`register plugin-log and the Coreframe auth-session broker`,test:e=>Q(e,[`tauri_plugin_log::Builder`,`coreframe_tauri_plugin_auth_session::init`,`VITE_APP_ORIGIN`])},{path:`src-tauri/build.rs`,requirement:`forward VITE_APP_ORIGIN and TAURI_DEV_HOST into the Rust build`,test:e=>Q(e,[`VITE_APP_ORIGIN`,`TAURI_DEV_HOST`])},{path:`src-tauri/capabilities/default.json`,requirement:`grant log and auth-session permissions to the main window`,test:e=>Q(e,[`"windows": ["main"]`,`"log:default"`,`"coreframe-tauri-plugin-auth-session:default"`])},{path:`vite.config.ts`,requirement:`define the Tauri runtime and platform environment and fixed native dev server`,test:e=>Q(e,[`env.host === "tauri"`,`"import.meta.env.TAURI"`,`"import.meta.env.PLATFORM"`,`TAURI_DEV_HOST`,`strictPort: true`])},{path:`src/vite-env.d.ts`,requirement:`type the Tauri runtime, platform, development origin, and packaged app origin`,test:e=>Q(e,[`PLATFORM: import("@coreframe/lib/shell").ShellPlatform`,`TAURI: boolean`,`TAURI_DEV_ORIGIN`,`VITE_APP_ORIGIN`])},{path:`react-router.config.ts`,requirement:`skip service-worker generation for non-browser hosts`,test:e=>Q(e,[`resolveCoreframeHost`,`resolveCoreframeHost() === "browser"`])},{path:`src/api/client/app-origin.ts`,requirement:`resolve browser and packaged application origins through the Tauri runtime`,test:e=>Q(e,[`@coreframe/tauri-js/client`,`browserOrigin: location?.origin`,`development: import.meta.env.DEV`,`packagedAppOrigin: import.meta.env.VITE_APP_ORIGIN`,`tauri: import.meta.env.TAURI`,`tauriDevelopmentOrigin: import.meta.env.TAURI_DEV_ORIGIN`])&&!e.includes(`resolveAppOrigin(import.meta.env`)},{path:`src/api/client/auth-fetch.ts`,requirement:`call the selected framework authentication composition`,test:e=>Q(e,[`createAuthenticatedFetch`,`refreshAccess`,`sessionHint: authSessionHint`])},{path:`src/api/client/auth-session-hint.ts`,requirement:`keep native session hints in memory until the credential broker revalidates`,test:e=>Q(e,[`import.meta.env.PLATFORM !== "web"`,`persistence: browserPersistence`,`return false`])},{path:`src/api/client/tauri-auth.ts`,requirement:`compose native API and Better Auth transports behind the virtual auth contract`,test:e=>Q(e,[`createAuthenticatedFetch`,`createTauriAuthenticatedFetch`,`authSessionHint: options.sessionHint`,`mintAccessToken`,`createAuthClient`,`createAuthFetch`,`onSessionChange: options.onSessionChange`])},{path:`src/web/auth/client.ts`,requirement:`call the selected framework Better Auth composition`,test:e=>Q(e,[`createAuthClient as createCoreframeAuthClient`,`createCoreframeAuthClient`,`authFetch`,`customFetchImpl`])},{path:`src/api/worker/middleware/auth.ts`,requirement:`mint and accept bearer access tokens only across the fixed native origin boundary`,test:e=>Q(e,[`appendTauriAppOrigins`,`createTauriAccessTokenResponse`,`isTauriAppOrigin`,`readTauriBearerToken`])},{path:`src/api/worker/fetch.ts`,requirement:`apply native CORS at every Worker response boundary`,test:e=>Q(e,[`handleTauriCorsPreflight`,`applyTauriCors`])},{path:`coreframe.config.ts`,requirement:`enable web and desktop development platforms`,test:e=>Q(e,[`platforms: ["web", "desktop"]`])&&!e.includes(`"ios"`)&&!e.includes(`"android"`)},{path:`src/web/entry.client.tsx`,requirement:`attach native development logs and skip service-worker registration in Tauri`,test:e=>Q(e,[`import "./dev/tauri-log.ts"`,`import.meta.env.TAURI`])},{path:`.env.example`,requirement:`document the packaged VITE_APP_ORIGIN build value`,test:e=>e.includes(`VITE_APP_ORIGIN`)},{path:`.gitignore`,requirement:`ignore the Tauri Cargo target directory`,test:e=>e.includes(`src-tauri/target`)},{path:`.oxfmtrc.json`,requirement:`ignore generated Tauri schemas and target output`,test:e=>Q(e,[`src-tauri/gen/schemas`,`src-tauri/target`])},{path:`src-tauri/AGENTS.md`,requirement:`route native work to owner-local rules and documentation`,test:e=>Q(e,[`.agents/rules/tauri.md`,`docs/authentication.md`,`docs/deployment.md`])},{path:`src-tauri/.agents/rules/tauri.md`,requirement:`install the owner-local durable Tauri native-boundary rule`,test:e=>Q(e,[`## Native Boundary`,`## Security`,`## Documentation`])},{path:`.agents/rules/integrations.yaml`,requirement:`route cross-boundary Tauri work to the owner-local native rule`,test:e=>e.includes(`src-tauri/.agents/rules/tauri.md`)},{path:`src-tauri/docs/authentication.md`,requirement:`document the native credential broker and bearer-token boundary`,test:e=>Q(e,[`@coreframe/tauri-js`,`@coreframe/tauri-plugin-auth-session`,`VITE_APP_ORIGIN`])},{path:`src-tauri/docs/development.md`,requirement:`document native development asset delivery and Leylines scopes`,test:e=>Q(e,[`dev.tauri`,`browser.tauri`,`managed asset`])},{path:`src-tauri/docs/deployment.md`,requirement:`document native release topology, signing, token recovery, and provider setup`,test:e=>Q(e,[`VITE_APP_ORIGIN`,`native-auth`,`access-token signing-secret`])},{path:`src-tauri/docs/privacy-security.md`,requirement:`record the shipped Tauri remote API and secure-storage boundary`,test:e=>Q(e,[`## Remote API Boundary`,`platform secure storage`])},{path:`.github/workflows/tauri-release-artifacts.yml`,requirement:`provide a desktop-only Tauri release-artifact workflow`,test:e=>Q(e,[`Build Tauri Release Artifacts`,`pnpm exec tauri`])&&!e.toLowerCase().includes(`ios`)&&!e.toLowerCase().includes(`android`)}],$r=[`CoreframeTemplateProject7A91C`,`coreframe-template-project-7a91c`,`coreframe_template_project_7a91c`,`com.example.coreframetemplateproject7a91c`];function ei(e){let t=[];for(let n of Qr){let r=L(e,n.path);if(!q(r)){t.push(`${n.path} is missing; it must ${n.requirement}.`);continue}let i=J(r,`utf8`);n.test(i)||t.push(`${n.path} must ${n.requirement}.`)}let n=L(e,`src-tauri/tauri.conf.json`);q(n)?ti(n,t):t.push(`src-tauri/tauri.conf.json is missing.`);for(let n of[`src-tauri/Cargo.toml`,`src-tauri/src/main.rs`,`src-tauri/tauri.conf.json`]){let r=L(e,n);q(r)&&$r.some(e=>J(r,`utf8`).includes(e))&&t.push(`${n} must replace the Coreframe template identity sentinel.`)}return t}function ti(e,t){let n;try{n=JSON.parse(J(e,`utf8`))}catch{t.push(`src-tauri/tauri.conf.json must contain valid JSON.`);return}(typeof n.identifier!=`string`||!/^[a-z0-9]+(?:\.[a-z0-9]+){2,}$/.test(n.identifier)||n.identifier.startsWith(`com.example.`))&&t.push(`src-tauri/tauri.conf.json must use an organization-owned reverse-domain identifier.`)}function Q(e,t){return t.every(t=>e.includes(t))}function ni({name:e,...t}){let n=Lr(t),r=`recipes/${e}/recipe.yaml`,i=ai(xr(Rr(n.repositoryRoot,n.ref,r),r).verifier,n.projectRoot);if(i.length>0)throw Error(`Recipe ${e} verification failed:\n${i.map(e=>`- ${e}`).join(`
5
+ `)}async function Qt({apiOrigin:e,cwd:t=process.cwd(),environment:n=process.env,platform:r=`web`,simulator:i=!1,prepareClient:a=M,runCommand:o=en}={}){$t(r,i);let s={...n};delete s.COREFRAME_PLATFORM,delete s.TAURI_ENV_PLATFORM;let c=r===`web`?void 0:N(e??n.COREFRAME_API_ORIGIN);for(let e of Jt(r,{apiOrigin:c,cwd:t,simulator:i})){if(e.kind===`prepare`){if(!c)throw Error(`A production API origin is required for the Flutter ${e.platform} build.`);await a({apiOrigin:c,cwd:t,environment:s,platform:e.platform});continue}await o(e.command,e.args,{cwd:e.cwd,env:{...s,...e.environment}})}r===`android`?console.log(Xt(t)):r===`ios`&&console.log(Zt(t,{simulator:i}))}function $t(e,t){if(t&&e!==`ios`)throw Error(`The --simulator flag is only supported for the iOS build target.`)}async function en(e,t,{cwd:n,env:r}){await R(e,t,{cwd:n,env:r,stdio:`inherit`})}function tn(e,t,n,r){return{kind:`command`,command:e,args:t,cwd:n,...r===void 0?{}:{environment:r}}}const nn=r(f,{displayName:`origin`,description:`Exact production HTTPS API origin embedded in a packaged Flutter client.`,async from(e){return N(e)}}),rn=n({name:`build`,description:`Build the web client or a release Flutter app. Tauri is not built.`,args:{platform:u({type:l(s(qt)),displayName:`platform`,description:`Build target: web, iOS, Android, or macOS. Defaults to web.`}),apiOrigin:c({long:`api-origin`,type:l(nn),description:`Exact production HTTPS API origin for a Flutter build. Defaults to COREFRAME_API_ORIGIN.`}),simulator:i({long:`simulator`,description:`Build iOS for the simulator instead of a physical device.`,defaultValue:()=>!1})},handler:({apiOrigin:e,platform:t,simulator:n})=>Qt({apiOrigin:e,platform:t,simulator:n})}),an=/^[a-f0-9]{64}$/,on=/^[a-f0-9]{40}$/,sn=/^[A-Za-z0-9][A-Za-z0-9._-]*$/;function cn(e){if(!an.test(e))throw Error(`Invalid SHA-256 digest "${e}".`);return e}function ln(e){if(!on.test(e))throw Error(`Invalid full Git revision "${e}".`);return e}function un(e,t){if(!sn.test(e))throw Error(`${t} must contain only letters, numbers, dots, underscores, or hyphens.`);return e}function dn(e){return`projects/${un(e,`Project ID`)}/i18n/v1`}function fn(e,t){return cn(t),`${dn(e)}/objects/sha256/${t.slice(0,2)}/${t}`}function pn(e,t){return ln(t),`${dn(e)}/commits/${t}.json`}function mn(e,t){return hn(t),`${dn(e)}/releases/${encodeURIComponent(t)}.json`}function hn(e){if(!e.startsWith(`v`)||e.length<2||e.length>128||/\s/.test(e)||e.includes(`..`))throw Error(`Release tag "${e}" must be a valid v-prefixed tag.`);return e}function X(e,t){if(!t||t.startsWith(`/`)||t.includes(`\0`))throw Error(`Unsafe i18n artifact path "${t}".`);let n=L(e),r=L(n,t);if(r!==n&&!r.startsWith(`${n}${ue}`))throw Error(`Unsafe i18n artifact path "${t}".`);return r}function Z(e,t,n){return`${e.directory}/${t}/${n}.json`}function gn(e,t,n){return`${e.directory}/${t}/${n}.mjs`}async function _n(e){await R(`pnpm`,[`exec`,`lingui`,`extract`],{cwd:e,stdio:`inherit`})}async function vn({config:e,cwd:t,strict:n,temporaryDirectory:r}){let i=[];try{for(let n of e.locales)for(let a of e.catalogs){let o=X(t,Z(e,n,a)),s=await Cn(o),c=Object.fromEntries(Object.entries(s).filter(([,e])=>!e.obsolete)),l=I(r,`${n}-${a}.json`);await B(F(l),{recursive:!0}),await xe(o,l),i.push({path:o,backup:l}),await wn(o,c)}await R(`pnpm`,[`exec`,`lingui`,`compile`,...n?[`--strict`]:[]],{cwd:t,stdio:`inherit`})}finally{try{for(let{path:e,backup:t}of i)await xe(t,e)}finally{for(let n of e.locales)for(let r of e.catalogs)await H(X(t,gn(e,n,r)),{force:!0})}}}async function yn({config:e,cwd:t}){let n=[];for(let r of e.locales)if(r!==e.sourceLocale)for(let i of e.catalogs){let a=await Cn(X(t,Z(e,r,i)));for(let[e,t]of Object.entries(a)){if(t.obsolete||t.translation?.trim())continue;let a=t.message;if(typeof a!=`string`||!a)throw Error(`Missing source message metadata for ${r}:${e}.`);n.push({catalog:i,comments:t.comments?.filter(e=>typeof e==`string`)??[],context:t.context,id:e,locale:r,message:a,origins:t.origin?.map(([e,t])=>t?`${e}:${t}`:e)??[],placeholders:Object.keys(t.placeholders??{}).sort()})}}return n.sort((e,t)=>kn(e).localeCompare(kn(t)))}async function bn({config:e,cwd:t,messages:n,env:r=process.env}){if(n.length===0)return{translations:[],version:1};if(!e.generator)throw Error(`I18n preparation found ${n.length} missing translations, but no generator is configured.`);let i={messages:n,sourceLocale:e.sourceLocale,version:1};return Tn(await En({args:e.generator.args??[],command:e.generator.command,cwd:t,env:r,input:JSON.stringify(i)}))}async function xn({config:e,cwd:t,missing:n,response:r}){let i=new Map(n.map(e=>[kn(e),e])),a=new Map;for(let e of r.translations){let t=kn(e);if(!i.has(t))throw Error(`Translation generator returned unexpected entry ${e.locale}:${e.catalog}:${e.id}.`);if(a.has(t))throw Error(`Translation generator returned duplicate entry ${e.locale}:${e.catalog}:${e.id}.`);if(!e.translation.trim())throw Error(`Translation generator returned an empty entry ${e.locale}:${e.id}.`);a.set(t,e.translation)}let o=[...i.keys()].filter(e=>!a.has(e));if(o.length>0)throw Error(`Translation generator omitted ${o.length} required entries.`);let s=await Me(`@lingui/message-utils/compileMessage`,t);for(let e of n){let t=a.get(kn(e));Dn({compileMessage:s,id:e.id,locale:e.locale,source:e.message,translation:t})}for(let n of e.locales)if(n!==e.sourceLocale)for(let r of e.catalogs){let i=X(t,Z(e,n,r)),o=await Cn(i),s=!1;for(let[e,t]of Object.entries(o)){let i=a.get(kn({catalog:r,id:e,locale:n}));if(i!==void 0){if(t.translation?.trim())throw Error(`Refusing to overwrite preserved translation ${n}:${e}.`);t.translation=i,s=!0}}s&&await wn(i,o)}}async function Sn({config:e,cwd:t}){let n=await yn({config:e,cwd:t});if(n.length>0)throw Error(`I18n catalogs remain incomplete: ${n.length} translations are missing.`);let r=await Me(`@lingui/message-utils/compileMessage`,t);for(let n of e.locales)if(n!==e.sourceLocale)for(let i of e.catalogs){let a=await Cn(X(t,Z(e,n,i)));for(let[e,t]of Object.entries(a))if(!t.obsolete){if(typeof t.message!=`string`||typeof t.translation!=`string`)throw Error(`Incomplete source metadata for active translation ${n}:${e}.`);Dn({compileMessage:r,id:e,locale:n,source:t.message,translation:t.translation})}}}async function Cn(e){let t=JSON.parse(await V(e,`utf8`));if(!t||typeof t!=`object`||Array.isArray(t))throw Error(`Lingui rich JSON catalog must be an object: ${e}.`);for(let[n,r]of Object.entries(t)){if(!r||typeof r!=`object`||Array.isArray(r))throw Error(`Invalid Lingui rich JSON message ${n} in ${e}.`);let t=r;if(t.translation!==void 0&&typeof t.translation!=`string`)throw Error(`Invalid translation value for ${n} in ${e}.`);if(t.message!==void 0&&t.message!==null&&typeof t.message!=`string`)throw Error(`Invalid source message value for ${n} in ${e}.`);if(t.context!==void 0&&typeof t.context!=`string`)throw Error(`Invalid context value for ${n} in ${e}.`);if(t.obsolete!==void 0&&typeof t.obsolete!=`boolean`)throw Error(`Invalid obsolete marker for ${n} in ${e}.`);if(t.comments!==void 0&&(!Array.isArray(t.comments)||t.comments.some(e=>typeof e!=`string`)))throw Error(`Invalid comments for ${n} in ${e}.`);if(t.origin!==void 0&&(!Array.isArray(t.origin)||t.origin.some(e=>!Array.isArray(e)||typeof e[0]!=`string`||e[1]!==void 0&&typeof e[1]!=`number`)))throw Error(`Invalid origins for ${n} in ${e}.`);if(t.placeholders!==void 0&&(!t.placeholders||typeof t.placeholders!=`object`||Array.isArray(t.placeholders)))throw Error(`Invalid placeholders for ${n} in ${e}.`)}return t}async function wn(e,t){await B(F(e),{recursive:!0});let n=`${e}.${process.pid}.tmp`;await U(n,`${JSON.stringify(t,null,2)}\n`),await Ee(n,e)}function Tn(e){let t;try{t=JSON.parse(e)}catch{throw Error(`Translation generator returned invalid JSON.`)}if(!t||typeof t!=`object`||t.version!==1||!Array.isArray(t.translations))throw Error(`Translation generator returned an invalid response envelope.`);for(let e of t.translations)if(!e||typeof e!=`object`||typeof e.id!=`string`||typeof e.catalog!=`string`||typeof e.locale!=`string`||typeof e.translation!=`string`)throw Error(`Translation generator returned an invalid translation entry.`);return t}function En({args:e,command:t,cwd:n,env:r,input:i}){return R(t,e,{cwd:n,env:r,stdio:[{string:i},`pipe`,`ignore`]}).then(({stdout:e})=>{if(Buffer.byteLength(e)>10*1024*1024)throw Error(`Translation generator output exceeded 10 MiB.`);return e}).catch(()=>{throw Error(`Translation generator exited unsuccessfully.`)})}function Dn({compileMessage:e,id:t,locale:n,source:r,translation:i}){let a,o;try{a=e.compileMessageOrThrow(r),o=e.compileMessageOrThrow(i)}catch{throw Error(`Translation ${n}:${t} is not valid ICU MessageFormat.`)}let s=On(a),c=On(o);if(s.length!==c.length||s.some((e,t)=>e!==c[t]))throw Error(`Translation ${n}:${t} does not preserve source ICU placeholders.`)}function On(e){let t=[];function n(e){for(let r of e){if(typeof r==`string`)continue;let[e,i=`argument`,a]=r;if(t.push(`${e}:${i}`),a&&typeof a==`object`&&!Array.isArray(a))for(let e of Object.values(a))Array.isArray(e)&&n(e)}}return n(e),t.sort()}function kn(e){return`${e.locale}\0${e.catalog}\0${e.id}`}function An(e){return Le(`sha256`).update(e).digest(`hex`)}async function jn(e){return An(await V(e))}function Mn(e){return Buffer.from(`${JSON.stringify(e,null,2)}\n`)}async function Nn({bucket:e,digest:t,projectId:n,source:r,store:i}){if(cn(t),await jn(r)!==t)throw Error(`I18n object source does not match declared SHA-256 digest ${t}.`);let a=fn(n,t);await i.has(e,a)||await i.upload(e,a,r,`application/octet-stream`);let o=`${r}.${process.pid}.${W()}.verify`;try{if(await i.download(e,a,o),await jn(o)!==t)throw Error(`Existing immutable i18n object ${a} failed integrity verification.`)}finally{await H(o,{force:!0})}}async function Pn({bucket:e,key:t,reference:n,store:r,temporaryDirectory:i}){let a=Mn(n),o=I(i,`reference-${W()}.json`);if(await r.has(e,t))try{if(await r.download(e,t,o),!(await V(o)).equals(a))throw Error(`Immutable i18n reference ${t} already resolves to different snapshot data.`);return}finally{await H(o,{force:!0})}await U(o,a,{flag:`wx`});try{await r.upload(e,t,o,`application/json`)}finally{await H(o,{force:!0})}let s=I(i,`reference-${W()}.verify.json`);try{if(await r.download(e,t,s),!(await V(s)).equals(a))throw Error(`Uploaded immutable i18n reference ${t} failed verification.`)}finally{await H(s,{force:!0})}}async function Fn({bucket:e,manifest:t,projectId:n,store:r,temporaryDirectory:i}){let a=Mn(t),o=An(a),s=I(i,`manifest-${o}.json`);await U(s,a,{flag:`wx`});try{await Nn({bucket:e,digest:o,projectId:n,source:s,store:r})}finally{await H(s,{force:!0})}return o}async function In({bucket:e,key:t,store:n,temporaryDirectory:r}){if(!await n.has(e,t))return;let i=I(r,`reference-${W()}.json`);try{await n.download(e,t,i);let r=JSON.parse(await V(i,`utf8`));if(r.version!==1||typeof r.revision!=`string`||typeof r.snapshot!=`string`)throw Error(`Invalid i18n reference at ${t}.`);return ln(r.revision),cn(r.snapshot),r}finally{await H(i,{force:!0})}}async function Ln({bucket:e,projectId:t,revision:n,store:r,temporaryDirectory:i}){let a=await In({bucket:e,key:pn(t,n),store:r,temporaryDirectory:i});if(a&&a.revision!==n)throw Error(`I18n commit reference does not match requested revision ${n}.`);return a}async function Rn({bucket:e,projectId:t,reference:n,store:r,tag:i,temporaryDirectory:a}){await Pn({bucket:e,key:pn(t,n.revision),reference:n,store:r,temporaryDirectory:a}),i&&await Pn({bucket:e,key:mn(t,i),reference:n,store:r,temporaryDirectory:a})}async function zn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,target:a}){cn(n);let o=I(L(t),`v1`,`sha256`,n.slice(0,2),n);if(await Vn(o,n)===!1){await B(F(o),{recursive:!0});let t=`${o}.${process.pid}.${W()}.tmp`;try{if(await i.download(e,fn(r,n),t),await jn(t)!==n)throw Error(`Downloaded i18n object failed SHA-256 verification: ${n}.`);await H(o,{force:!0}),await Ee(t,o)}finally{await H(t,{force:!0})}}await B(F(a),{recursive:!0});let s=`${a}.${process.pid}.${W()}.tmp`;try{if(await xe(o,s),await jn(s)!==n)throw Error(`Cached i18n object failed SHA-256 verification: ${n}.`);await H(a,{force:!0}),await Ee(s,a)}finally{await H(s,{force:!0})}}async function Bn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,temporaryDirectory:a}){let o=I(a,`manifest-${n}.json`);await zn({bucket:e,cacheRoot:t,digest:n,projectId:r,store:i,target:o});let s=JSON.parse(await V(o,`utf8`));if(s.version!==1||s.projectId!==r||typeof s.revision!=`string`||!Array.isArray(s.files)||!Array.isArray(s.catalogs)||s.catalogs.some(e=>typeof e!=`string`)||!Array.isArray(s.locales)||s.locales.some(e=>typeof e!=`string`)||typeof s.sourceLocale!=`string`||typeof s.generator!=`string`||typeof s.linguiVersion!=`string`)throw Error(`Invalid i18n snapshot manifest ${n}.`);ln(s.revision),s.baseline!==void 0&&cn(s.baseline);for(let e of s.files){if(!e||typeof e!=`object`||typeof e.path!=`string`||typeof e.digest!=`string`||typeof e.size!=`number`)throw Error(`Invalid file entry in i18n snapshot manifest ${n}.`);cn(e.digest)}return s}async function Vn(e,t){try{return(await De(e)).isFile()&&await jn(e)===t}catch{return!1}}async function Hn({cwd:e=process.cwd(),env:t=process.env}={}){if((await Fe({cwd:e})).i18n){if(t.COREFRAME_I18N_RELEASE_REVISION){await Gn({cwd:e,env:t,revision:t.COREFRAME_I18N_RELEASE_REVISION});return}await _n(e)}}async function Un({cwd:e=process.cwd(),projectConfig:t}={}){let n=t??await Fe({cwd:e});if(!n.i18n)return;let r=Kn(n.i18n),i=X(e,r.directory);try{if(!(await De(i)).isDirectory())throw Error(`I18n catalog path is not a directory: ${i}.`)}catch(t){if(t.code!==`ENOENT`)throw t;await _n(e);return}for(let t of r.locales)for(let n of r.catalogs)try{if(!(await De(X(e,Z(r,t,n)))).isFile())throw Error(`I18n catalog path is not a file: ${t}/${n}.json.`)}catch(t){if(t.code!==`ENOENT`)throw t;await _n(e);return}}async function Wn({cwd:e=process.cwd(),env:t=process.env,store:n,tag:r}){hn(r);let i=await qn({cwd:e,env:t,store:n});await tr(e);let a=await er(e);await nr(e,r,a);let o=await we(I(je(),`coreframe-i18n-prepare-`));try{let n=await Ln({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,revision:a,store:i.store,temporaryDirectory:o});if(n){let e=await Bn({bucket:i.assets.sourceBucket,cacheRoot:i.cacheRoot,digest:n.snapshot,projectId:i.assets.projectId,store:i.store,temporaryDirectory:o});return $n(i,e,a),await Yn(i,e),await Rn({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,reference:n,store:i.store,tag:r,temporaryDirectory:o}),{reused:!0,snapshot:n.snapshot}}return await Qn(i,o,async()=>{let n=await Jn(i,a,o);n||await Zn(i),await _n(e);let s=await yn({config:i.config,cwd:e}),c=await bn({config:i.config,cwd:e,env:t,messages:s});await xn({config:i.config,cwd:e,missing:s,response:c}),await Sn({config:i.config,cwd:e}),await vn({config:i.config,cwd:e,strict:!0,temporaryDirectory:o});let l=await Xn(i),u={...n?{baseline:n}:{},catalogs:i.config.catalogs,files:l,generator:s.length>0?i.config.generator?.id??`unconfigured`:`none`,linguiVersion:await rr(e),locales:i.config.locales,projectId:i.assets.projectId,revision:a,sourceLocale:i.config.sourceLocale,version:1},d=await Fn({bucket:i.assets.sourceBucket,manifest:u,projectId:i.assets.projectId,store:i.store,temporaryDirectory:o});return await Rn({bucket:i.assets.sourceBucket,projectId:i.assets.projectId,reference:{revision:a,snapshot:d,version:1},store:i.store,tag:r,temporaryDirectory:o}),{reused:!1,snapshot:d}})}finally{await H(o,{force:!0,recursive:!0})}}async function Gn({cwd:e=process.cwd(),env:t=process.env,revision:n,store:r}={}){let i=await Fe({cwd:e});if(!i.i18n)return;let a=await qn({cwd:e,env:t,store:r,projectConfig:i}),o=ln(n??await er(e)),s=await we(I(je(),`coreframe-i18n-materialize-`));try{let e=await Ln({bucket:a.assets.sourceBucket,projectId:a.assets.projectId,revision:o,store:a.store,temporaryDirectory:s});if(!e)throw Error(`No prepared i18n snapshot exists for commit ${o}. Push a v* tag for this commit and wait for the translation gate.`);let t=await Bn({bucket:a.assets.sourceBucket,cacheRoot:a.cacheRoot,digest:e.snapshot,projectId:a.assets.projectId,store:a.store,temporaryDirectory:s});return $n(a,t,o),await Yn(a,t),{revision:o,snapshot:e.snapshot}}finally{await H(s,{force:!0,recursive:!0})}}function Kn(e){let t=un(e.sourceLocale,`Source locale`),n=[...new Set(e.locales.map(e=>un(e,`Locale`)))],r=[...new Set(e.catalogs.map(e=>un(e,`Catalog`)))];if(n.length===0||!n.includes(t))throw Error(`I18n locales must include the source locale.`);if(r.length===0)throw Error(`I18n configuration requires at least one catalog.`);if(e.generator&&(!e.generator.command.trim()||!e.generator.id.trim()))throw Error(`I18n generator command and ID must be non-empty.`);return{catalogs:r,directory:e.directory??`locales`,generator:e.generator,locales:n,sourceLocale:t}}async function qn({cwd:e=process.cwd(),env:t=process.env,projectConfig:n,store:r}){let i=n??await Fe({cwd:e});if(!i.i18n)throw Error(`Missing i18n configuration in coreframe.config.ts.`);if(!i.assets)throw Error(`I18n snapshots require the existing private build bucket configured under assets.`);let a=i.assets;return{assets:a,cacheRoot:L(e,`.coreframe`,`i18n`,`cache`),config:Kn(i.i18n),cwd:L(e),env:t,store:r??ve({config:a,env:t})}}async function Jn(e,t,n){let{stdout:r}=await R(`git`,[`rev-list`,`--first-parent`,`--skip=1`,t],{cwd:e.cwd,stdin:`ignore`});for(let t of r.split(/\r?\n/).filter(Boolean)){let r=await Ln({bucket:e.assets.sourceBucket,projectId:e.assets.projectId,revision:ln(t),store:e.store,temporaryDirectory:n});if(!r)continue;let i=await Bn({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:r.snapshot,projectId:e.assets.projectId,store:e.store,temporaryDirectory:n});return $n(e,i,t),await Yn(e,i),r.snapshot}}async function Yn(e,t){for(let n of t.files)if(await zn({bucket:e.assets.sourceBucket,cacheRoot:e.cacheRoot,digest:n.digest,projectId:e.assets.projectId,store:e.store,target:X(e.cwd,n.path)}),(await De(X(e.cwd,n.path))).size!==n.size)throw Error(`Materialized i18n artifact size does not match manifest: ${n.path}.`)}async function Xn(e){let t=[];for(let n of e.config.locales)for(let r of e.config.catalogs){let i=Z(e.config,n,r),a=X(e.cwd,i),o=await jn(a);await Nn({bucket:e.assets.sourceBucket,digest:o,projectId:e.assets.projectId,source:a,store:e.store}),t.push({digest:o,path:i,size:(await De(a)).size})}return t.sort((e,t)=>e.path.localeCompare(t.path))}async function Zn(e){let{stdout:t}=await R(`git`,[`rev-parse`,`--show-prefix`],{cwd:e.cwd,stdin:`ignore`}),n=t.trim(),{stdout:r}=await R(`git`,[`log`,`-1`,`--format=%H`,`--diff-filter=AM`,`--`,`:(top)${`${n}${e.config.directory}/${e.config.sourceLocale}/${e.config.catalogs[0]}.po`}`],{cwd:e.cwd,stdin:`ignore`}),i=r.trim();if(!i)return!1;let a=(await Me(`@lingui/format-po`,e.cwd)).formatter({lineNumbers:!1}),o=!1;for(let t of e.config.locales)for(let r of e.config.catalogs){let s=`${n}${`${e.config.directory}/${t}/${r}.po`}`;try{let{stdout:n}=await R(`git`,[`show`,`${i}:${s}`],{cwd:e.cwd,stdin:`ignore`});await wn(X(e.cwd,Z(e.config,t,r)),a.parse(n)),o=!0}catch{}}return o}async function Qn(e,t,n){let r=[];for(let n of e.config.locales)for(let i of e.config.catalogs){let a=Z(e.config,n,i),o=X(e.cwd,a);try{await ye(o)}catch{continue}let s=I(t,`previous-catalogs`,a);await B(F(s),{recursive:!0}),await Ee(o,s),r.push({backup:s,path:o})}try{let e=await n();return await H(I(t,`previous-catalogs`),{force:!0,recursive:!0}),e}catch(t){for(let t of e.config.locales)for(let n of e.config.catalogs)await H(X(e.cwd,Z(e.config,t,n)),{force:!0});for(let{backup:e,path:t}of r)await B(F(t),{recursive:!0}),await Ee(e,t);throw t}}function $n(e,t,n){if(t.revision!==n||t.projectId!==e.assets.projectId||t.sourceLocale!==e.config.sourceLocale||JSON.stringify(t.locales)!==JSON.stringify(e.config.locales)||JSON.stringify(t.catalogs)!==JSON.stringify(e.config.catalogs))throw Error(`I18n snapshot does not match commit or project configuration.`);let r=e.config.locales.flatMap(t=>e.config.catalogs.map(n=>Z(e.config,t,n))),i=t.files.map(e=>e.path);if(new Set(i).size!==i.length||JSON.stringify(i.sort())!==JSON.stringify(r.sort()))throw Error(`I18n snapshot has an incomplete or unexpected artifact set.`)}async function er(e){let{stdout:t}=await R(`git`,[`rev-parse`,`HEAD`],{cwd:e,stdin:`ignore`});return ln(t.trim())}async function tr(e){let{stdout:t}=await R(`git`,[`status`,`--porcelain`],{cwd:e,stdin:`ignore`});if(t.trim())throw Error(`Tagged i18n preparation requires a clean Git tree.`)}async function nr(e,t,n){let{stdout:r}=await R(`git`,[`rev-parse`,`${t}^{commit}`],{cwd:e,stdin:`ignore`});if(r.trim()!==n)throw Error(`Release tag ${t} does not point to checked-out commit ${n}.`)}async function rr(e){let{stdout:t}=await R(`pnpm`,[`exec`,`lingui`,`--version`],{cwd:e,stdin:`ignore`});return t.trim()}const ir=[`Use a B2 Multi-Bucket Application Key restricted to the configured private build-object and public generated-assets buckets.`,`Required capabilities: listAllBucketNames, readFiles, and writeFiles.`,`Deletion, bucket-management, and key-management capabilities are not needed.`].join(` `),ar=r(f,{displayName:`widths`,description:`Comma-separated responsive variant widths.`,async from(e){let t=e.split(`,`).map(e=>Number(e));if(t.length===0||t.some(e=>!Number.isInteger(e)||e<=0)||t.some((e,n)=>n>0&&e<=t[n-1]))throw Error(`Widths must be positive, unique, strictly ascending integers.`);return t}}),or=r(f,{displayName:`profile`,async from(e){return ge(e)}}),sr=r(f,{displayName:`pack`,description:`Asset pack name, such as training-videos.`,async from(e){if(!/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(e))throw Error(`Asset pack names must use lowercase hyphen-separated segments.`);return e}}),cr=r(f,{displayName:`origin`,description:`Exact production HTTPS API origin embedded in the packaged Flutter client.`,async from(e){return N(e)}}),lr=p({name:`assets`,cmds:{configure:n({name:`configure`,description:`Store a Backblaze B2 private build-object key in the operating system credential store. ${ir}`,args:{profile:u({type:or,displayName:`profile`,description:`Credential profile named by coreframe.config.ts.`})},handler:async({profile:e})=>{z.note(ir,`Required B2 key access`);let t=await z.text({message:`Backblaze B2 application key ID`,validate:e=>e?.trim()?void 0:`The application key ID is required.`});if(z.isCancel(t))throw Error(`Asset credential configuration was cancelled.`);let n=await z.password({message:`Backblaze B2 application key`,validate:e=>e?void 0:`The application key is required.`});if(z.isCancel(n))throw Error(`Asset credential configuration was cancelled.`);await _e({applicationKey:n,applicationKeyId:t.trim(),profile:e}),console.log(`Stored Coreframe asset credential profile "${e}".`)}}),add:n({name:`add`,args:{file:u({type:f,displayName:`file`,description:`Source raster image, SVG, MP3, MP4, or Lottie JSON to add to the asset library.`}),id:c({long:`id`,type:f,description:`Logical asset ID, such as blog/my-post/hero.`}),alt:c({long:`alt`,type:l(f),description:`Required alt text for raster image and SVG assets.`}),pack:c({long:`pack`,type:l(sr),description:`Place the asset in a named, lazily loaded pack.`}),variantWidths:c({long:`widths`,type:l(ar),description:`Generate exactly these raster-image widths instead of the default ladder.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({alt:e,file:t,id:n,json:r,pack:i,variantWidths:a})=>me(await de({alt:e,file:t,id:n,pack:i,variantWidths:a}),r)}),build:n({name:`build`,args:{id:c({long:`id`,type:l(f),description:`Build only one logical asset ID.`}),pack:c({long:`pack`,type:l(sr),description:`Build only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({id:e,json:t,pack:n})=>me(await fe({id:e,pack:n}),t)}),check:n({name:`check`,args:{fix:i({long:`fix`,description:`Migrate asset state and build missing generated output when possible.`,defaultValue:()=>!1}),pack:c({long:`pack`,type:l(sr),description:`Check only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({fix:e,json:t,pack:n})=>{let r=await pe({fix:e,pack:n});me(r,t),r.ok||(process.exitCode=1)}}),publish:n({name:`publish`,args:{pack:c({long:`pack`,type:l(sr),description:`Publish only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,pack:t})=>{let n=await he({pack:t});me(n,e),n.ok||(process.exitCode=1)}}),status:n({name:`status`,args:{pack:c({long:`pack`,type:l(sr),description:`Report status for only one named asset pack.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e,pack:t})=>{let n=await pe({pack:t});me(n,e),n.ok||(process.exitCode=1)}})}}),ur=p({name:`flutter`,cmds:{acceptance:n({name:`acceptance`,description:`Run the complete packaged Flutter conformance gate on macOS.`,args:{apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e})=>se({environment:{...process.env,COREFRAME_API_ORIGIN:e}})}),codegen:n({name:`codegen`,description:`Generate Flutter bridge contracts and Panda-backed Mix theme tokens.`,args:{check:i({long:`check`,description:`Fail when generated Flutter artifacts are missing or stale.`,defaultValue:()=>!1})},handler:({check:e})=>ae({check:e})}),prepare:n({name:`prepare`,description:`Build and package the React client for one Flutter platform.`,args:{platform:u({type:s(j),displayName:`platform`,description:`Flutter platform whose packaged client should be prepared.`}),apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e,platform:t})=>M({apiOrigin:e,platform:t})}),check:n({name:`check`,description:`Reject missing, stale, modified, or incorrectly targeted Flutter assets.`,args:{platform:u({type:s(j),displayName:`platform`,description:`Flutter platform whose packaged client should be checked.`}),apiOrigin:c({long:`api-origin`,env:`COREFRAME_API_ORIGIN`,type:cr,description:`Defaults to COREFRAME_API_ORIGIN.`})},handler:({apiOrigin:e,platform:t})=>A({apiOrigin:e,platform:t})})}}),dr=p({name:`i18n`,cmds:{build:n({name:`build`,description:`Extract source messages or materialize an exact release catalog snapshot.`,args:{},handler:async()=>{await Hn()}}),materialize:n({name:`materialize`,description:`Materialize the immutable i18n snapshot for an exact commit.`,args:{revision:c({long:`revision`,type:l(f),description:`Full commit SHA. Defaults to the checked-out commit.`})},handler:async({revision:e})=>{let t=await Gn({revision:e});t&&console.log(`Materialized i18n snapshot ${t.snapshot}.`)}}),prepare:n({name:`prepare`,description:`Fill missing translations, strictly compile, and publish an immutable tagged snapshot.`,args:{tag:c({long:`tag`,type:f,description:`Pushed v* release tag that points to the checked-out commit.`})},handler:async({tag:e})=>{let t=await Wn({tag:e});console.log(`${t.reused?`Reused`:`Published`} i18n snapshot ${t.snapshot}.`)}})}}),fr=G.platform===`win32`?`react-router.cmd`:`react-router`,pr=G.platform===`win32`?`panda.cmd`:`panda`;async function mr(e=G.cwd()){await _r(e),await gr(e,[`typegen`])}async function hr(e=G.cwd(),t=G.env){if((t.COREFRAME_PLATFORM??t.TAURI_ENV_PLATFORM??`web`)!==`web`)return;let n=P.resolve(e,`.coreframe/dashboard-build`),r=P.join(n,`client`),i=P.resolve(e,`dist/client/__dashboard`);await H(n,{force:!0,recursive:!0}),await vr(e,pr,[`build`],t),await gr(e,[`build`],t),await H(i,{force:!0,recursive:!0}),await B(P.dirname(i),{recursive:!0}),await Se(r,i,{recursive:!0})}async function gr(e,t,n=G.env){await vr(e,fr,t,n)}async function _r(e){await H(P.resolve(e,`dashboard/.react-router`),{force:!0,recursive:!0})}async function vr(e,t,n,r=G.env){await R(t,n,{cwd:P.resolve(e,`dashboard`),env:{...r,PATH:P.resolve(e,`node_modules/.bin`)+P.delimiter+(r.PATH??r.Path??``)},stdio:`inherit`})}const yr=p({name:`dashboard`,cmds:{build:n({name:`build`,args:{},handler:()=>hr()}),typegen:n({name:`typegen`,args:{},handler:()=>mr()})}}),br=/^[a-z0-9]+(?:-[a-z0-9]+)*$/u;function xr(e,t){let n=Cr(e,t);if(!wr(n)||!Tr(n,[`description`,`requires`,`routes`,`verifier`])||!Dr(n.description)||n.requires!==void 0&&(!Array.isArray(n.requires)||!n.requires.every(Dr))||n.verifier!==void 0&&!Dr(n.verifier)||!Array.isArray(n.routes))throw Error(`${t} must contain a description string, routes array, and optional requires and verifier fields.`);let r=(n.requires??[]).map(e=>Sr(e));if(new Set(r).size!==r.length)throw Error(`${t} contains duplicate recipe requirements.`);let i=n.routes.map((e,n)=>{if(!wr(e)||!Er(e,[`path`,`router`,`when`])||!Dr(e.path)||!Dr(e.router)||!Dr(e.when))throw Error(`${t} route ${n+1} must contain router, path, and when strings.`);return{path:e.path,router:e.router,when:e.when}}),a=i.map(e=>`${e.router}\0${e.path}`);if(new Set(a).size!==a.length)throw Error(`${t} contains a duplicate router and path pair.`);return{description:n.description,requires:r,routes:i,verifier:n.verifier}}function Sr(e){if(!br.test(e))throw Error(`Recipe names use lowercase letters, numbers, and single hyphens.`);return e}function Cr(e,t){try{return Ke(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function wr(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Tr(e,t){return Object.keys(e).every(e=>t.includes(e))}function Er(e,t){let n=Object.keys(e).sort();return n.length===t.length&&n.every((e,n)=>e===t[n])}function Dr(e){return typeof e==`string`&&e.length>0}const Or=`https://github.com/airlock-labs/coreframe.git`;function kr(e,t){return K(`git`,e,{cwd:t,encoding:`utf8`})}function Ar(e,t){let n=kr(e,t);if(n.status!==0){let t=n.stderr.trim()||n.stdout.trim();throw Error(`Git command failed: git ${e.join(` `)}${t?`\n${t}`:``}`)}return n.stdout}function jr(e,t){let n=kr([`remote`,`get-url`,e],t);if(n.status===2)return null;if(n.status!==0){let t=n.stderr.trim()||n.stdout.trim();throw Error(`Could not inspect remote ${e}.${t?`\n${t}`:``}`)}return n.stdout.trim()}function Mr({cwd:e=process.cwd(),fetch:t=!0,remote:n=`template`}={}){if(n.length===0)throw Error(`Remote name must not be empty.`);Ar([`rev-parse`,`--show-toplevel`],e);let r=jr(n,e);if(r===null)Ar([`remote`,`add`,n,Or],e),console.log(`Added ${n} remote: ${Or}`);else if(r===Or)console.log(`${n} remote already points at ${Or}`);else throw Error(`${n} remote points at ${r}, not ${Or}.\nChoose the intended template source before continuing, then update or rename the remote manually.`);t&&(Ar([`fetch`,n,`--tags`,`--prune`],e),console.log(`Fetched ${n}.`))}const Nr=/^\d+\.\d+\.\d+(?:-[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/u;function Pr(e){return Nr.test(e)?`v${e}`:e}function Fr(e){return`${Pr(e)}:template`}function Ir(e,t){return`${Fr(e)}/${t}`}function Lr({cwd:e=process.cwd(),fetch:t=!0,remote:n=`template`,target:r}={}){let i=Vr(e),a=Gr(i,[`rev-parse`,`--show-toplevel`]),o=Pr(r??Hr(i));return Mr({cwd:a,fetch:t,remote:n}),{projectRoot:i,ref:o,repositoryRoot:a}}function Rr(e,t,n){return zr(e,t,n).toString(`utf8`)}function zr(e,t,n){let r=`${t}:${n}`,i=K(`git`,[`show`,r],{cwd:e,encoding:`buffer`});if(i.status!==0)throw Error(`Could not read ${r}. ${Kr([`show`,r],i)}`);return i.stdout}function Br(e,t,n){let r=K(`git`,[`ls-tree`,`-r`,`--name-only`,`-z`,t,`--`,n],{cwd:e,encoding:`buffer`});if(r.status!==0)throw Error(Kr([`ls-tree`,t,n],r));return r.stdout.toString(`utf8`).split(`\0`).filter(Boolean)}function Vr(e){let t=L(e);for(;;){let e=I(t,`package.json`),n=Wr(e);if(n!==void 0&&Ur(n,e).engines?.coreframe)return t;let r=F(t);if(r===t)throw Error(`Could not find a package.json with engines.coreframe.`);t=r}}function Hr(e){let t=I(e,`package.json`),n=Wr(t);if(n===void 0)throw Error(`Required file package.json does not exist.`);let r=Ur(n,t).engines?.coreframe;if(!r)throw Error(`package.json must declare an exact engines.coreframe recipe baseline.`);return r}function Ur(e,t){try{return JSON.parse(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function Wr(e){try{return J(e,`utf8`)}catch(e){if(qr(e)&&e.code===`ENOENT`)return;throw e}}function Gr(e,t){let n=K(`git`,t,{cwd:e,encoding:`utf8`});if(n.status!==0)throw Error(Kr(t,n));return n.stdout.trim()}function Kr(e,t){let n=t.stderr.toString(`utf8`).trim()||t.stdout.toString(`utf8`).trim();return`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`}function qr(e){return e instanceof Error&&`code`in e}const Jr=[{path:`package.json`,requirement:`retain the Coreframe Flutter JavaScript runtime used by src-flutter`,test:e=>e.includes(`"@coreframe/flutter-js"`)},{path:`coreframe.config.ts`,requirement:`enable web and at least one Flutter development platform`,test:Zr},{path:`src/api/client/app-origin.ts`,requirement:`allow the Flutter shell to provide its exact API origin`,test:e=>Xr(e,[`@coreframe/flutter-js/client`,`resolveAppOrigin`,`browserOrigin: location?.origin`])},{path:`src/api/worker/auth-config.ts`,requirement:`trust the exact Flutter authentication origins`,test:e=>Xr(e,[`appendFlutterAuthOrigins`,`appendFlutterAuthOrigins([], development)`])},{path:`src/api/worker/middleware/auth.ts`,requirement:`broker Flutter access tokens and accept only Flutter bearer origins`,test:e=>Xr(e,[`createFlutterAccessTokenResponse`,`isFlutterAuthOrigin(origin, import.meta.env.DEV)`,`readFlutterBearerToken`,`native && ctx.request.method !== "GET"`])&&!e.includes(`isNativeOrigin`)},{path:`src/api/worker/middleware/flutter-cors.ts`,requirement:`provide the Flutter packaged-origin CORS boundary`,test:e=>Xr(e,[`applyFlutterCors`,`handleFlutterCorsPreflight`,`flutterCorsMiddleware`])},{path:`src/api/worker/middleware/index.ts`,requirement:`apply Flutter CORS to ordinary Worker responses`,test:e=>e.includes(`flutterCorsMiddleware`)},{path:`src/web/app/flutter-shell/application.ts`,requirement:`configure the Flutter shell's app-owned query and session hooks`,test:e=>Xr(e,[`configureShellQueryFocus`,`authSessionHint`])},{path:`src/web/dev/flutter-devtools.ts`,requirement:`install the Flutter development tools bridge`,test:e=>e.includes(`installFlutterDevTools`)},{path:`src/web/entry.client.tsx`,requirement:`load Flutter development tools only for non-browser development`,test:e=>Xr(e,[`./dev/flutter-devtools.ts`,`import.meta.env.PLATFORM !== "web"`])}];function Yr(e){let t=[];for(let n of Jr){let r=I(e,n.path);if(!q(r)){t.push(`${n.path} is missing; it must ${n.requirement}.`);continue}let i=J(r,`utf8`);n.test(i)||t.push(`${n.path} must ${n.requirement}.`)}return t}function Xr(e,t){return t.every(t=>e.includes(t))}function Zr(e){let t=e.match(/\bplatforms\s*:\s*\[([\s\S]*?)\]/)?.[1];if(!t)return!1;let n=new Set([...t.matchAll(/(["'`])([^"'`]*)\1/g)].map(e=>e[2]));return n.has(`web`)&&[`ios`,`android`,`macos`].some(e=>n.has(e))}const Qr=[{path:`package.json`,requirement:`declare the Tauri CLI, plugin-log, and Coreframe Tauri runtime packages`,test:e=>Q(e,[`"@tauri-apps/cli"`,`"@tauri-apps/plugin-log"`,`"@coreframe/tauri-js"`,`"@coreframe/tauri-plugin-auth-session"`])},{path:`src-tauri/Cargo.toml`,requirement:`declare Tauri, plugin-log, and Coreframe auth-session Rust dependencies`,test:e=>Q(e,[`tauri-build`,`tauri-plugin-log`,`coreframe-tauri-plugin-auth-session`])},{path:`src-tauri/src/main.rs`,requirement:`launch the project-owned Tauri Rust library`,test:e=>e.includes(`::run();`)},{path:`src-tauri/src/lib.rs`,requirement:`register plugin-log and the Coreframe auth-session broker`,test:e=>Q(e,[`tauri_plugin_log::Builder`,`coreframe_tauri_plugin_auth_session::init`,`VITE_APP_ORIGIN`])},{path:`src-tauri/build.rs`,requirement:`forward VITE_APP_ORIGIN and TAURI_DEV_HOST into the Rust build`,test:e=>Q(e,[`VITE_APP_ORIGIN`,`TAURI_DEV_HOST`])},{path:`src-tauri/capabilities/default.json`,requirement:`grant log and auth-session permissions to the main window`,test:e=>Q(e,[`"windows": ["main"]`,`"log:default"`,`"coreframe-tauri-plugin-auth-session:default"`])},{path:`vite.config.ts`,requirement:`define the Tauri runtime and platform environment and fixed native dev server`,test:e=>Q(e,[`env.host === "tauri"`,`"import.meta.env.TAURI"`,`"import.meta.env.PLATFORM"`,`TAURI_DEV_HOST`,`strictPort: true`])},{path:`src/vite-env.d.ts`,requirement:`type the Tauri runtime, platform, development origin, and packaged app origin`,test:e=>Q(e,[`PLATFORM: import("@coreframe/lib/shell").ShellPlatform`,`TAURI: boolean`,`TAURI_DEV_ORIGIN`,`VITE_APP_ORIGIN`])},{path:`react-router.config.ts`,requirement:`skip service-worker generation for non-browser hosts`,test:e=>Q(e,[`resolveCoreframeHost`,`resolveCoreframeHost() === "browser"`])},{path:`src/api/client/app-origin.ts`,requirement:`resolve browser and packaged application origins through the Tauri runtime`,test:e=>Q(e,[`@coreframe/tauri-js/client`,`browserOrigin: location?.origin`,`development: import.meta.env.DEV`,`packagedAppOrigin: import.meta.env.VITE_APP_ORIGIN`,`tauri: import.meta.env.TAURI`,`tauriDevelopmentOrigin: import.meta.env.TAURI_DEV_ORIGIN`])&&!e.includes(`resolveAppOrigin(import.meta.env`)},{path:`src/api/client/auth-fetch.ts`,requirement:`call the selected framework authentication composition`,test:e=>Q(e,[`createAuthenticatedFetch`,`refreshAccess`,`sessionHint: authSessionHint`])},{path:`src/api/client/auth-session-hint.ts`,requirement:`keep native session hints in memory until the credential broker revalidates`,test:e=>Q(e,[`import.meta.env.PLATFORM !== "web"`,`persistence: browserPersistence`,`return false`])},{path:`src/api/client/tauri-auth.ts`,requirement:`compose native API and Better Auth transports behind the virtual auth contract`,test:e=>Q(e,[`createAuthenticatedFetch`,`createTauriAuthenticatedFetch`,`authSessionHint: options.sessionHint`,`mintAccessToken`,`createAuthClient`,`createAuthFetch`,`onSessionChange: options.onSessionChange`])},{path:`src/web/auth/client.ts`,requirement:`call the selected framework Better Auth composition`,test:e=>Q(e,[`createAuthClient as createCoreframeAuthClient`,`createCoreframeAuthClient`,`authFetch`,`customFetchImpl`])},{path:`src/api/worker/middleware/auth.ts`,requirement:`mint and accept bearer access tokens only across the fixed native origin boundary`,test:e=>Q(e,[`appendTauriAppOrigins`,`createTauriAccessTokenResponse`,`isTauriAppOrigin`,`readTauriBearerToken`])},{path:`src/api/worker/fetch.ts`,requirement:`apply native CORS at every Worker response boundary`,test:e=>Q(e,[`handleTauriCorsPreflight`,`applyTauriCors`])},{path:`coreframe.config.ts`,requirement:`enable web and desktop development platforms`,test:e=>Q(e,[`platforms: ["web", "desktop"]`])&&!e.includes(`"ios"`)&&!e.includes(`"android"`)},{path:`src/web/entry.client.tsx`,requirement:`attach native development logs and skip service-worker registration in Tauri`,test:e=>Q(e,[`import "./dev/tauri-log.ts"`,`import.meta.env.TAURI`])},{path:`.env.example`,requirement:`document the packaged VITE_APP_ORIGIN build value`,test:e=>e.includes(`VITE_APP_ORIGIN`)},{path:`.gitignore`,requirement:`ignore the Tauri Cargo target directory`,test:e=>e.includes(`src-tauri/target`)},{path:`.oxfmtrc.json`,requirement:`ignore generated Tauri schemas and target output`,test:e=>Q(e,[`src-tauri/gen/schemas`,`src-tauri/target`])},{path:`src-tauri/AGENTS.md`,requirement:`route native work to owner-local rules and documentation`,test:e=>Q(e,[`.agents/rules/tauri.md`,`docs/authentication.md`,`docs/deployment.md`])},{path:`src-tauri/.agents/rules/tauri.md`,requirement:`install the owner-local durable Tauri native-boundary rule`,test:e=>Q(e,[`## Native Boundary`,`## Security`,`## Documentation`])},{path:`.agents/rules/integrations.yaml`,requirement:`route cross-boundary Tauri work to the owner-local native rule`,test:e=>e.includes(`src-tauri/.agents/rules/tauri.md`)},{path:`src-tauri/docs/authentication.md`,requirement:`document the native credential broker and bearer-token boundary`,test:e=>Q(e,[`@coreframe/tauri-js`,`@coreframe/tauri-plugin-auth-session`,`VITE_APP_ORIGIN`])},{path:`src-tauri/docs/development.md`,requirement:`document native development asset delivery and Leylines scopes`,test:e=>Q(e,[`dev.tauri`,`browser.tauri`,`managed asset`])},{path:`src-tauri/docs/deployment.md`,requirement:`document native release topology, signing, token recovery, and provider setup`,test:e=>Q(e,[`VITE_APP_ORIGIN`,`native-auth`,`access-token signing-secret`])},{path:`src-tauri/docs/privacy-security.md`,requirement:`record the shipped Tauri remote API and secure-storage boundary`,test:e=>Q(e,[`## Remote API Boundary`,`platform secure storage`])},{path:`.github/workflows/tauri-release-artifacts.yml`,requirement:`provide a desktop-only Tauri release-artifact workflow`,test:e=>Q(e,[`Build Tauri Release Artifacts`,`pnpm exec tauri`])&&!e.toLowerCase().includes(`ios`)&&!e.toLowerCase().includes(`android`)}],$r=[`CoreframeTemplateProject7A91C`,`coreframe-template-project-7a91c`,`coreframe_template_project_7a91c`,`com.example.coreframetemplateproject7a91c`];function ei(e){let t=[];for(let n of Qr){let r=I(e,n.path);if(!q(r)){t.push(`${n.path} is missing; it must ${n.requirement}.`);continue}let i=J(r,`utf8`);n.test(i)||t.push(`${n.path} must ${n.requirement}.`)}let n=I(e,`src-tauri/tauri.conf.json`);q(n)?ti(n,t):t.push(`src-tauri/tauri.conf.json is missing.`);for(let n of[`src-tauri/Cargo.toml`,`src-tauri/src/main.rs`,`src-tauri/tauri.conf.json`]){let r=I(e,n);q(r)&&$r.some(e=>J(r,`utf8`).includes(e))&&t.push(`${n} must replace the Coreframe template identity sentinel.`)}return t}function ti(e,t){let n;try{n=JSON.parse(J(e,`utf8`))}catch{t.push(`src-tauri/tauri.conf.json must contain valid JSON.`);return}(typeof n.identifier!=`string`||!/^[a-z0-9]+(?:\.[a-z0-9]+){2,}$/.test(n.identifier)||n.identifier.startsWith(`com.example.`))&&t.push(`src-tauri/tauri.conf.json must use an organization-owned reverse-domain identifier.`)}function Q(e,t){return t.every(t=>e.includes(t))}function ni({name:e,...t}){let n=Lr(t),r=`recipes/${e}/recipe.yaml`,i=ai(xr(Rr(n.repositoryRoot,n.ref,r),r).verifier,n.projectRoot);if(i.length>0)throw Error(`Recipe ${e} verification failed:\n${i.map(e=>`- ${e}`).join(`
6
6
  `)}`);return{name:e,ref:n.ref}}function ri(e){console.log(`Verified Coreframe recipe ${e.name} from ${e.ref}.`)}function ii(e,t){for(let n of e){let e=`recipes/${n}/recipe.yaml`,r=ai(xr(Rr(t.repositoryRoot,t.ref,e),e).verifier,t.projectRoot);if(r.length>0)throw Error(`Recipe ${n} is required but is not fully applied:\n${r.map(e=>`- ${e}`).join(`
7
- `)}\nApply and verify ${n} before continuing.`)}}function ai(e,t){if(!e)throw Error(`Required recipe does not declare a verifier.`);if(e===`tauri`)return ei(t);if(e===`flutter`)return Yr(t);throw Error(`Unknown recipe verifier ${JSON.stringify(e)}.`)}function oi({cwd:e=process.cwd(),fetch:t=!0,name:n,remote:r=`template`,target:i}){Sr(n);let a=Lr({cwd:e,fetch:t,remote:r,target:i}),{projectRoot:o,ref:s,repositoryRoot:c}=a,l=`recipes/${n}`,u=`${l}/recipe.yaml`,d=xr(Rr(c,s,u),u);ii(d.requires,a);let f=Rr(c,s,`${l}/RECIPE.md`),p=Br(c,s,`${l}/files`),m=Br(c,s,`${l}/patches`),h=Br(c,s,`${l}/.agents`),g=new Map,_=new Map,v=[],y=[],b=[],x=[],S=[],C=[];for(let e of p){let t=e.slice(`${l}/files/`.length);if(pi(t,`Recipe file ${e}`),t.startsWith(`.agents/`))throw Error(`Recipe file ${e} must be stored in the recipe's .agents directory.`);g.set(t,zr(c,s,e)),_.set(t,e)}for(let e of h){let t=e.slice(`${l}/`.length);if(ui(t,`Recipe asset ${e}`),g.has(t))throw Error(`Recipe declares ${t} as both a file and an agent asset.`);g.set(t,zr(c,s,e)),_.set(t,e)}for(let e of m){let t=mi(e,l);if(g.has(t))throw Error(`Recipe declares ${t} as both a file and a patch.`);let n=zr(c,s,e);hi(n.toString(`utf8`),t,e),fi(o,t),gi(o,n,!1)?(v.push({contents:n,destinationPath:t}),x.push(t)):gi(o,n,!0)?S.push(t):b.push({destination:t,source:e})}let w=new Map;for(let[e,t]of g){let r=yi(fi(o,e));if(r===void 0)w.set(e,t),y.push(e);else if(r.equals(t))S.push(e);else if(e.startsWith(`.agents/`))throw Error(`Recipe ${n} cannot replace modified ${e}. Reconcile that agent asset manually.`);else b.push({destination:e,source:_.get(e)})}let T=new Map;for(let e of d.routes){if(ui(e.router,`Recipe route router`),di(e.path,`Recipe route path`),g.has(e.router))throw Error(`Recipe cannot replace its destination router ${e.router}.`);if(!g.has(e.path)&&!q(fi(o,e.path)))throw Error(`Recipe route target ${e.path} does not exist.`);let t=T.get(e.router)??ci(bi(fi(o,e.router),e.router),e.router);T.set(e.router,t);let r=t.routes.find(t=>t.path===e.path);if(r){if(r.when!==e.when)throw Error(`Recipe ${n} route ${e.path} conflicts with the existing trigger in ${e.router}.`);continue}t.routes.push({path:e.path,when:e.when})}for(let[e,t]of T){t.routes.sort((e,t)=>e.path<t.path?-1:+(e.path>t.path));let n=bi(fi(o,e),e),r=qe(t,{lineWidth:0});r===n?S.push(e):(w.set(e,r),C.push(e))}for(let{destinationPath:e}of v)if(w.has(e))throw Error(`Recipe cannot both write and patch ${e}.`);for(let[e,t]of w){let n=fi(o,e);Be(I(n),{recursive:!0}),Ge(n,t)}return v.length>0&&_i(o,v.map(({contents:e})=>e)),{created:y.sort(),instructions:f,mergeRequired:b.sort((e,t)=>e.destination.localeCompare(t.destination)),name:n,patched:x.sort(),ref:s,unchanged:[...new Set(S)].sort(),updated:C.sort()}}function si(e){console.log(`Prepared Coreframe recipe ${e.name} from ${e.ref}.`);for(let t of e.created)console.log(`created: ${t}`);for(let t of e.updated)console.log(`updated: ${t}`);for(let t of e.patched)console.log(`patched: ${t}`);for(let t of e.mergeRequired)console.log(`merge-required: ${t.destination} (source: ${e.ref}:${t.source})`);for(let t of e.unchanged)console.log(`unchanged: ${t}`);console.log(`\nContinue by following ${e.ref}:recipes/${e.name}/RECIPE.md:\n`),console.log(e.instructions.trimEnd())}function ci(e,t){let n=li(e,t);if(!xi(n)||!Si(n,[`routes`,`rules`])||!Array.isArray(n.rules)||!n.rules.every(Ci)||!Array.isArray(n.routes))throw Error(`${t} must contain only string rules and a routes array.`);let r=n.routes.map((e,n)=>{if(!xi(e)||!Si(e,[`path`,`when`])||!Ci(e.path)||!Ci(e.when))throw Error(`${t} route ${n+1} must contain path and when strings.`);return{path:e.path,when:e.when}}),i=r.map(e=>e.path);if(new Set(i).size!==i.length)throw Error(`${t} contains duplicate route paths.`);return{rules:n.rules,routes:r}}function li(e,t){try{return Ke(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function ui(e,t){if(!e.startsWith(`.agents/`))throw Error(`${t} must be a normalized project-relative path beneath .agents/.`);pi(e,t)}function di(e,t){if(pi(e,t),!/(?:^|\/)\.agents\/rules\/.+\.md$/u.test(e))throw Error(`${t} must point to a Markdown rule beneath an .agents/rules directory.`)}function fi(e,t){pi(t,`Recipe destination`);let n=L(e,t),r=e;for(let e of t.split(`/`))if(r=L(r,e),q(r)&&ze(r).isSymbolicLink())throw Error(`Recipe destination ${t} crosses symbolic link ${r}.`);return n}function pi(e,t){if(e.length===0||se(e)||e===`..`||e.startsWith(`../`)||e.includes(`\\`)||ce.normalize(e)!==e)throw Error(`${t} must be a normalized project-relative path.`)}function mi(e,t){let n=e.slice(`${t}/patches/`.length);if(!n.endsWith(`.patch`))throw Error(`Recipe patch ${e} must use a .patch suffix.`);let r=n.slice(0,-6);return pi(r,`Recipe patch ${e}`),r}function hi(e,t,n){let r=e.match(/^diff --git .+$/gmu)??[],i=e.match(/^--- .+$/gmu)??[],a=e.match(/^\+\+\+ .+$/gmu)??[];if(r.length!==1||r[0]!==`diff --git a/${t} b/${t}`||i.length!==1||a.length!==1||i[0]!==`--- a/${t}`||a[0]!==`+++ b/${t}`||/^(?:deleted file mode |GIT binary patch$|new file mode |rename from |rename to )/mu.test(e))throw Error(`Recipe patch ${n} must modify only ${t}.`)}function gi(e,t,n){let r=[`apply`,`--check`,`--whitespace=nowarn`];return n&&r.push(`--reverse`),r.push(`-`),K(`git`,r,{cwd:e,input:t}).status===0}function _i(e,t){let n=K(`git`,[`apply`,`--whitespace=nowarn`,`-`],{cwd:e,input:Buffer.concat(t.flatMap(e=>[e,Buffer.from(e.at(-1)===10?``:`
8
- `)])),encoding:`utf8`});if(n.status!==0){let e=n.stderr.trim()||n.stdout.trim();throw Error(`Could not apply recipe patches.${e?`\n${e}`:``}`)}}function vi(e){return yi(e)?.toString(`utf8`)}function yi(e){try{return J(e)}catch(e){if(wi(e)&&e.code===`ENOENT`)return;throw e}}function bi(e,t){let n=vi(e);if(n===void 0)throw Error(`Required file ${t} does not exist.`);return n}function xi(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Si(e,t){let n=Object.keys(e).sort();return n.length===t.length&&n.every((e,n)=>e===t[n])}function Ci(e){return typeof e==`string`&&e.length>0}function wi(e){return e instanceof Error&&`code`in e}function Ti(e={}){let{ref:t,repositoryRoot:n}=Lr(e),r=Br(n,t,`recipes`).filter(e=>/^recipes\/[^/]+\/recipe\.yaml$/u.test(e)).map(e=>{let r=e.split(`/`)[1];return Sr(r),{description:xr(Rr(n,t,e),e).description,name:r}});return r.sort((e,t)=>e.name.localeCompare(t.name)),{recipes:r,ref:t}}function Ei(e){console.log(`Coreframe recipes at ${e.ref}:`);for(let t of e.recipes)console.log(`${t.name} — ${t.description}`)}const Di=`.agents/skills/coreframe-upgrade/SKILL.md`;function Oi(e,t={}){return K(`git`,e,t)}function ki(e){return e.stderr.toString(`utf8`).trim()||e.stdout.toString(`utf8`).trim()}function Ai(e,t){let n=Ir(e,t),r=Oi([`show`,n],{encoding:`utf8`});if(r.status!==0){let e=ki(r);throw Error(`Could not read ${n}.${e?` ${e}`:``}`)}return r.stdout.toString()}function ji(){let e=Oi([`rev-parse`,`--show-toplevel`],{encoding:`utf8`});if(e.status!==0){let t=ki(e);throw Error(`Could not find git repository root.${t?` ${t}`:``}`)}return e.stdout.toString().trim()}function Mi(e,t){let n=Ve(L(Ae(),`coreframe-upgrade-skill-`)),r=L(n,`SKILL.md`);try{Ge(r,t);let n=ki(Oi([`--no-pager`,`diff`,`--no-index`,`--color=never`,`--`,e,r]));n&&console.log(n)}finally{Ue(n,{force:!0,recursive:!0})}}function Ni({apply:e,target:t}){let n=L(ji(),Di),r=Pr(t);if(!q(n))throw Error(`Local ${Di} does not exist.`);let i=J(n,`utf8`),a=Ai(t,Di);return i===a?(console.log(`Coreframe upgrade skill matches ${r}:template/${Di}.`),0):e?(Ge(n,a),console.error(`Updated ${Di} from ${r}:template. Reread it before continuing the upgrade.`),20):(console.error(`Coreframe upgrade skill differs from ${r}:template/${Di}.`),console.error(`Run again with --apply to update it, then reread ${Di} before continuing.`),Mi(n,a),20)}const Pi=[{matches:e=>e===`drizzle`||e.startsWith(`drizzle/`),reason:`project-owned migration history`},{matches:e=>e===`drizzle-hold`||e.startsWith(`drizzle-hold/`),reason:`project-owned migration history`},{matches:e=>e===`src/web/routes.ts`||e.startsWith(`src/web/app/routes/`),reason:`downstream-owned demonstration routes`},{matches:e=>e===`pnpm-lock.yaml`||e===`src-tauri/Cargo.lock`,reason:`downstream-owned dependency lockfile`}],Fi=new Set([`100644`,`100755`,`120000`]);function Ii(e,t={}){return K(`git`,e,t)}function Li(e){let t=Ii(e,{encoding:`utf8`});if(t.status!==0){let n=t.stderr.toString().trim()||t.stdout.toString().trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout.toString()}function Ri(e){let t=Ii(e);if(t.status!==0){let n=t.stderr.toString(`utf8`).trim()||t.stdout.toString(`utf8`).trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout}function zi(){return Li([`rev-parse`,`--show-toplevel`]).trim()}function Bi(e){let t=L(e,`package.json`);if(!q(t))throw Error(`Missing --base <git-ref>, and package.json does not exist.`);let n=JSON.parse(J(t,`utf8`)).engines?.coreframe;if(typeof n!=`string`||n.length===0)throw Error(`Missing --base <git-ref>, and package.json engines.coreframe is not set.`);return n}function Vi(e){let t=[],n=0;for(let r=0;r<e.length;r+=1)e[r]===0&&(t.push(e.subarray(n,r).toString(`utf8`)),n=r+1);return t.filter(e=>e.length>0)}function Hi(e,t){let n=Vi(Ri([`diff`,`--name-status`,`-z`,`--no-renames`,Fr(e),Fr(t),`--`])),r=[];for(let e=0;e<n.length;e+=2){let t=n[e],i=n[e+1];if(!t||!i)throw Error(`Could not parse git diff --name-status output.`);r.push({path:i,status:t})}return r}function Ui(e,t){let n=Ri([`ls-tree`,`-z`,Fr(e),`--`,t]);if(n.length===0)return null;let r=Vi(n)[0],i=r.indexOf(` `);if(i===-1)throw Error(`Could not parse git ls-tree output for ${e}:${t}.`);let[a,o,s]=r.slice(0,i).split(` `);if(!a||!o||!s)throw Error(`Could not parse git ls-tree metadata for ${e}:${t}.`);return{mode:a,object:s,path:t,type:o}}function Wi(e){return Ri([`cat-file`,`blob`,e.object])}function Gi(e,t){let n=R(e,t),r=e.endsWith(le)?e:`${e}${le}`;if(n!==e&&!n.startsWith(r))throw Error(`Refusing to access path outside repository: ${t}`);return n}function Ki(e){try{return ze(e),!0}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return!1;throw e}}function qi(e){return(e.mode&73)!=0}function Ji(e){return e===null||e.type===`blob`&&Fi.has(e.mode)}function Yi(e){return Pi.find(t=>t.matches(e))?.reason}function Xi(e,t,n){let r=Gi(e,t);if(n===null)return{matches:!Ki(r)};if(!Ji(n))return{matches:!1,reason:`unsupported template entry mode ${n.mode} ${n.type}`};let i;try{i=ze(r)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{matches:!1,reason:`path is missing from worktree`};throw e}let a=Wi(n);return n.mode===`120000`?i.isSymbolicLink()?{matches:Buffer.from(He(r),`utf8`).equals(a)}:{matches:!1,reason:`worktree path is not a symlink`}:i.isFile()?(n.mode===`100755`?qi(i):!qi(i))?{matches:J(r).equals(a)}:{matches:!1,reason:`worktree executable bit differs from template`}:{matches:!1,reason:`worktree path is not a regular file`}}function Zi(e){Ki(e)&&Ue(e,{force:!0,recursive:!1})}function Qi(e,t,n){let r=Gi(e,t);if(n===null){Zi(r);return}if(Be(I(r),{recursive:!0}),n.mode===`120000`){Zi(r),We(Wi(n).toString(`utf8`),r);return}let i=Ki(r)?ze(r):null;i&&!i.isFile()&&Zi(r),Ge(r,Wi(n)),Re(r,n.mode===`100755`?493:420)}function $i(e,t){return e===null&&t!==null?`add`:e!==null&&t===null?`delete`:`update`}function ea(e,t){if(t.length!==0){console.log(`${e}:`);for(let e of t){let t=e.reason?` (${e.reason})`:``;console.log(` ${e.action}: ${e.path}${t}`)}console.log(``)}}function ta(e){let t=zi(),n=Pr(e.base??Bi(t)),r=Pr(e.target),i=Hi(n,r),a=[],o=[],s=[],c=[];for(let e of i){let i=Yi(e.path);if(i){o.push({action:`ignored`,path:e.path,reason:i});continue}let l=Ui(n,e.path),u=Ui(r,e.path),d=$i(l,u);if(!Ji(l)||!Ji(u)){s.push({action:d,path:e.path,reason:`unsupported template entry type`});continue}if(Xi(t,e.path,u).matches){c.push({action:`unchanged`,path:e.path});continue}let f=Xi(t,e.path,l);if(!f.matches){s.push({action:d,path:e.path,reason:f.reason??`downstream differs from base template`});continue}a.push({action:d,path:e.path,targetEntry:u})}if(e.apply)for(let e of a)Qi(t,e.path,e.targetEntry??null);console.log(`Coreframe template fast-forward: ${n} -> ${r}`),console.log(``),ea(e.apply?`Applied clean template updates`:`Would apply clean template updates`,a),ea(`Ignored downstream-owned paths`,o),ea(`Skipped for agent review`,s),c.length>0&&console.log(`${c.length} changed template path(s) already matched the target state.`),i.length===0&&console.log(`No template file changes found in the requested range.`),!e.apply&&a.length>0&&(console.log(``),console.log(`Run with --apply to write the ${a.length} clean update(s).`))}const na=[`dependencies`,`devDependencies`];function ra(e){let t=K(`git`,e,{encoding:`utf8`});if(t.status!==0){let n=t.stderr.trim()||t.stdout.trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout}function ia(e,t){try{return JSON.parse(e)}catch(e){throw Error(`Could not parse ${t}: ${e instanceof Error?e.message:e}`)}}function aa(e,t){let n=`${Pr(e)}:${t}`;return ia(ra([`show`,n]),n)}function oa(e){return e.startsWith(`@coreframe/`)}function sa(e){return e.startsWith(`file:`)||e.startsWith(`link:`)||e.startsWith(`workspace:`)}function ca(e){return e.startsWith(`file:`)||e.startsWith(`link:`)}function la(e,t){let n=e.indexOf(`:`),r=e.slice(n+1),i=ce.normalize(ce.join(`template`,r,`package.json`));if(r.length===0||ce.isAbsolute(r)||i===`..`||i.startsWith(`../`))throw Error(`Invalid local template dependency for ${t}: ${e}`);return i}function ua(e){let t=aa(e,`template/package.json`),n=[],r=new Set;for(let i of na)for(let[a,o]of Object.entries(t[i]??{})){if(!oa(a)||!ca(o))continue;if(r.has(a))throw Error(`Target template declares ${a} more than once.`);let t=la(o,a),s=aa(e,t);if(s.name!==a||typeof s.version!=`string`)throw Error(`${Pr(e)}:${t} must declare ${a} with a version.`);n.push({group:i,name:a,spec:`^${s.version}`}),r.add(a)}return n}function da(e,t){for(let n of na){let r=e[n]?.[t];if(r)return{group:n,spec:r}}}function fa(e,t,n){let r=t.match(/\n([\t ]+)"/u)?.[1]??` `,i=t.endsWith(`
7
+ `)}\nApply and verify ${n} before continuing.`)}}function ai(e,t){if(!e)throw Error(`Required recipe does not declare a verifier.`);if(e===`tauri`)return ei(t);if(e===`flutter`)return Yr(t);throw Error(`Unknown recipe verifier ${JSON.stringify(e)}.`)}function oi({cwd:e=process.cwd(),fetch:t=!0,name:n,remote:r=`template`,target:i}){Sr(n);let a=Lr({cwd:e,fetch:t,remote:r,target:i}),{projectRoot:o,ref:s,repositoryRoot:c}=a,l=`recipes/${n}`,u=`${l}/recipe.yaml`,d=xr(Rr(c,s,u),u);ii(d.requires,a);let f=Rr(c,s,`${l}/RECIPE.md`),p=Br(c,s,`${l}/files`),m=Br(c,s,`${l}/patches`),h=Br(c,s,`${l}/.agents`),g=new Map,_=new Map,v=[],y=[],b=[],x=[],S=[],C=[];for(let e of p){let t=e.slice(`${l}/files/`.length);if(pi(t,`Recipe file ${e}`),t.startsWith(`.agents/`))throw Error(`Recipe file ${e} must be stored in the recipe's .agents directory.`);g.set(t,zr(c,s,e)),_.set(t,e)}for(let e of h){let t=e.slice(`${l}/`.length);if(ui(t,`Recipe asset ${e}`),g.has(t))throw Error(`Recipe declares ${t} as both a file and an agent asset.`);g.set(t,zr(c,s,e)),_.set(t,e)}for(let e of m){let t=mi(e,l);if(g.has(t))throw Error(`Recipe declares ${t} as both a file and a patch.`);let n=zr(c,s,e);hi(n.toString(`utf8`),t,e),fi(o,t),gi(o,n,!1)?(v.push({contents:n,destinationPath:t}),x.push(t)):gi(o,n,!0)?S.push(t):b.push({destination:t,source:e})}let w=new Map;for(let[e,t]of g){let r=yi(fi(o,e));if(r===void 0)w.set(e,t),y.push(e);else if(r.equals(t))S.push(e);else if(e.startsWith(`.agents/`))throw Error(`Recipe ${n} cannot replace modified ${e}. Reconcile that agent asset manually.`);else b.push({destination:e,source:_.get(e)})}let T=new Map;for(let e of d.routes){if(ui(e.router,`Recipe route router`),di(e.path,`Recipe route path`),g.has(e.router))throw Error(`Recipe cannot replace its destination router ${e.router}.`);if(!g.has(e.path)&&!q(fi(o,e.path)))throw Error(`Recipe route target ${e.path} does not exist.`);let t=T.get(e.router)??ci(bi(fi(o,e.router),e.router),e.router);T.set(e.router,t);let r=t.routes.find(t=>t.path===e.path);if(r){if(r.when!==e.when)throw Error(`Recipe ${n} route ${e.path} conflicts with the existing trigger in ${e.router}.`);continue}t.routes.push({path:e.path,when:e.when})}for(let[e,t]of T){t.routes.sort((e,t)=>e.path<t.path?-1:+(e.path>t.path));let n=bi(fi(o,e),e),r=qe(t,{lineWidth:0});r===n?S.push(e):(w.set(e,r),C.push(e))}for(let{destinationPath:e}of v)if(w.has(e))throw Error(`Recipe cannot both write and patch ${e}.`);for(let[e,t]of w){let n=fi(o,e);Be(F(n),{recursive:!0}),Ge(n,t)}return v.length>0&&_i(o,v.map(({contents:e})=>e)),{created:y.sort(),instructions:f,mergeRequired:b.sort((e,t)=>e.destination.localeCompare(t.destination)),name:n,patched:x.sort(),ref:s,unchanged:[...new Set(S)].sort(),updated:C.sort()}}function si(e){console.log(`Prepared Coreframe recipe ${e.name} from ${e.ref}.`);for(let t of e.created)console.log(`created: ${t}`);for(let t of e.updated)console.log(`updated: ${t}`);for(let t of e.patched)console.log(`patched: ${t}`);for(let t of e.mergeRequired)console.log(`merge-required: ${t.destination} (source: ${e.ref}:${t.source})`);for(let t of e.unchanged)console.log(`unchanged: ${t}`);console.log(`\nContinue by following ${e.ref}:recipes/${e.name}/RECIPE.md:\n`),console.log(e.instructions.trimEnd())}function ci(e,t){let n=li(e,t);if(!xi(n)||!Si(n,[`routes`,`rules`])||!Array.isArray(n.rules)||!n.rules.every(Ci)||!Array.isArray(n.routes))throw Error(`${t} must contain only string rules and a routes array.`);let r=n.routes.map((e,n)=>{if(!xi(e)||!Si(e,[`path`,`when`])||!Ci(e.path)||!Ci(e.when))throw Error(`${t} route ${n+1} must contain path and when strings.`);return{path:e.path,when:e.when}}),i=r.map(e=>e.path);if(new Set(i).size!==i.length)throw Error(`${t} contains duplicate route paths.`);return{rules:n.rules,routes:r}}function li(e,t){try{return Ke(e)}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}}function ui(e,t){if(!e.startsWith(`.agents/`))throw Error(`${t} must be a normalized project-relative path beneath .agents/.`);pi(e,t)}function di(e,t){if(pi(e,t),!/(?:^|\/)\.agents\/rules\/.+\.md$/u.test(e))throw Error(`${t} must point to a Markdown rule beneath an .agents/rules directory.`)}function fi(e,t){pi(t,`Recipe destination`);let n=I(e,t),r=e;for(let e of t.split(`/`))if(r=I(r,e),q(r)&&ze(r).isSymbolicLink())throw Error(`Recipe destination ${t} crosses symbolic link ${r}.`);return n}function pi(e,t){if(e.length===0||ce(e)||e===`..`||e.startsWith(`../`)||e.includes(`\\`)||le.normalize(e)!==e)throw Error(`${t} must be a normalized project-relative path.`)}function mi(e,t){let n=e.slice(`${t}/patches/`.length);if(!n.endsWith(`.patch`))throw Error(`Recipe patch ${e} must use a .patch suffix.`);let r=n.slice(0,-6);return pi(r,`Recipe patch ${e}`),r}function hi(e,t,n){let r=e.match(/^diff --git .+$/gmu)??[],i=e.match(/^--- .+$/gmu)??[],a=e.match(/^\+\+\+ .+$/gmu)??[];if(r.length!==1||r[0]!==`diff --git a/${t} b/${t}`||i.length!==1||a.length!==1||i[0]!==`--- a/${t}`||a[0]!==`+++ b/${t}`||/^(?:deleted file mode |GIT binary patch$|new file mode |rename from |rename to )/mu.test(e))throw Error(`Recipe patch ${n} must modify only ${t}.`)}function gi(e,t,n){let r=[`apply`,`--check`,`--whitespace=nowarn`];return n&&r.push(`--reverse`),r.push(`-`),K(`git`,r,{cwd:e,input:t}).status===0}function _i(e,t){let n=K(`git`,[`apply`,`--whitespace=nowarn`,`-`],{cwd:e,input:Buffer.concat(t.flatMap(e=>[e,Buffer.from(e.at(-1)===10?``:`
8
+ `)])),encoding:`utf8`});if(n.status!==0){let e=n.stderr.trim()||n.stdout.trim();throw Error(`Could not apply recipe patches.${e?`\n${e}`:``}`)}}function vi(e){return yi(e)?.toString(`utf8`)}function yi(e){try{return J(e)}catch(e){if(wi(e)&&e.code===`ENOENT`)return;throw e}}function bi(e,t){let n=vi(e);if(n===void 0)throw Error(`Required file ${t} does not exist.`);return n}function xi(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Si(e,t){let n=Object.keys(e).sort();return n.length===t.length&&n.every((e,n)=>e===t[n])}function Ci(e){return typeof e==`string`&&e.length>0}function wi(e){return e instanceof Error&&`code`in e}function Ti(e={}){let{ref:t,repositoryRoot:n}=Lr(e),r=Br(n,t,`recipes`).filter(e=>/^recipes\/[^/]+\/recipe\.yaml$/u.test(e)).map(e=>{let r=e.split(`/`)[1];return Sr(r),{description:xr(Rr(n,t,e),e).description,name:r}});return r.sort((e,t)=>e.name.localeCompare(t.name)),{recipes:r,ref:t}}function Ei(e){console.log(`Coreframe recipes at ${e.ref}:`);for(let t of e.recipes)console.log(`${t.name} — ${t.description}`)}const Di=`.agents/skills/coreframe-upgrade/SKILL.md`;function Oi(e,t={}){return K(`git`,e,t)}function ki(e){return e.stderr.toString(`utf8`).trim()||e.stdout.toString(`utf8`).trim()}function Ai(e,t){let n=Ir(e,t),r=Oi([`show`,n],{encoding:`utf8`});if(r.status!==0){let e=ki(r);throw Error(`Could not read ${n}.${e?` ${e}`:``}`)}return r.stdout.toString()}function ji(){let e=Oi([`rev-parse`,`--show-toplevel`],{encoding:`utf8`});if(e.status!==0){let t=ki(e);throw Error(`Could not find git repository root.${t?` ${t}`:``}`)}return e.stdout.toString().trim()}function Mi(e,t){let n=Ve(I(je(),`coreframe-upgrade-skill-`)),r=I(n,`SKILL.md`);try{Ge(r,t);let n=ki(Oi([`--no-pager`,`diff`,`--no-index`,`--color=never`,`--`,e,r]));n&&console.log(n)}finally{Ue(n,{force:!0,recursive:!0})}}function Ni({apply:e,target:t}){let n=I(ji(),Di),r=Pr(t);if(!q(n))throw Error(`Local ${Di} does not exist.`);let i=J(n,`utf8`),a=Ai(t,Di);return i===a?(console.log(`Coreframe upgrade skill matches ${r}:template/${Di}.`),0):e?(Ge(n,a),console.error(`Updated ${Di} from ${r}:template. Reread it before continuing the upgrade.`),20):(console.error(`Coreframe upgrade skill differs from ${r}:template/${Di}.`),console.error(`Run again with --apply to update it, then reread ${Di} before continuing.`),Mi(n,a),20)}const Pi=[{matches:e=>e===`drizzle`||e.startsWith(`drizzle/`),reason:`project-owned migration history`},{matches:e=>e===`drizzle-hold`||e.startsWith(`drizzle-hold/`),reason:`project-owned migration history`},{matches:e=>e===`src/web/routes.ts`||e.startsWith(`src/web/app/routes/`),reason:`downstream-owned demonstration routes`},{matches:e=>e===`pnpm-lock.yaml`||e===`src-tauri/Cargo.lock`,reason:`downstream-owned dependency lockfile`}],Fi=new Set([`100644`,`100755`,`120000`]);function Ii(e,t={}){return K(`git`,e,t)}function Li(e){let t=Ii(e,{encoding:`utf8`});if(t.status!==0){let n=t.stderr.toString().trim()||t.stdout.toString().trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout.toString()}function Ri(e){let t=Ii(e);if(t.status!==0){let n=t.stderr.toString(`utf8`).trim()||t.stdout.toString(`utf8`).trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout}function zi(){return Li([`rev-parse`,`--show-toplevel`]).trim()}function Bi(e){let t=I(e,`package.json`);if(!q(t))throw Error(`Missing --base <git-ref>, and package.json does not exist.`);let n=JSON.parse(J(t,`utf8`)).engines?.coreframe;if(typeof n!=`string`||n.length===0)throw Error(`Missing --base <git-ref>, and package.json engines.coreframe is not set.`);return n}function Vi(e){let t=[],n=0;for(let r=0;r<e.length;r+=1)e[r]===0&&(t.push(e.subarray(n,r).toString(`utf8`)),n=r+1);return t.filter(e=>e.length>0)}function Hi(e,t){let n=Vi(Ri([`diff`,`--name-status`,`-z`,`--no-renames`,Fr(e),Fr(t),`--`])),r=[];for(let e=0;e<n.length;e+=2){let t=n[e],i=n[e+1];if(!t||!i)throw Error(`Could not parse git diff --name-status output.`);r.push({path:i,status:t})}return r}function Ui(e,t){let n=Ri([`ls-tree`,`-z`,Fr(e),`--`,t]);if(n.length===0)return null;let r=Vi(n)[0],i=r.indexOf(` `);if(i===-1)throw Error(`Could not parse git ls-tree output for ${e}:${t}.`);let[a,o,s]=r.slice(0,i).split(` `);if(!a||!o||!s)throw Error(`Could not parse git ls-tree metadata for ${e}:${t}.`);return{mode:a,object:s,path:t,type:o}}function Wi(e){return Ri([`cat-file`,`blob`,e.object])}function Gi(e,t){let n=L(e,t),r=e.endsWith(ue)?e:`${e}${ue}`;if(n!==e&&!n.startsWith(r))throw Error(`Refusing to access path outside repository: ${t}`);return n}function Ki(e){try{return ze(e),!0}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return!1;throw e}}function qi(e){return(e.mode&73)!=0}function Ji(e){return e===null||e.type===`blob`&&Fi.has(e.mode)}function Yi(e){return Pi.find(t=>t.matches(e))?.reason}function Xi(e,t,n){let r=Gi(e,t);if(n===null)return{matches:!Ki(r)};if(!Ji(n))return{matches:!1,reason:`unsupported template entry mode ${n.mode} ${n.type}`};let i;try{i=ze(r)}catch(e){if(e instanceof Error&&`code`in e&&e.code===`ENOENT`)return{matches:!1,reason:`path is missing from worktree`};throw e}let a=Wi(n);return n.mode===`120000`?i.isSymbolicLink()?{matches:Buffer.from(He(r),`utf8`).equals(a)}:{matches:!1,reason:`worktree path is not a symlink`}:i.isFile()?(n.mode===`100755`?qi(i):!qi(i))?{matches:J(r).equals(a)}:{matches:!1,reason:`worktree executable bit differs from template`}:{matches:!1,reason:`worktree path is not a regular file`}}function Zi(e){Ki(e)&&Ue(e,{force:!0,recursive:!1})}function Qi(e,t,n){let r=Gi(e,t);if(n===null){Zi(r);return}if(Be(F(r),{recursive:!0}),n.mode===`120000`){Zi(r),We(Wi(n).toString(`utf8`),r);return}let i=Ki(r)?ze(r):null;i&&!i.isFile()&&Zi(r),Ge(r,Wi(n)),Re(r,n.mode===`100755`?493:420)}function $i(e,t){return e===null&&t!==null?`add`:e!==null&&t===null?`delete`:`update`}function ea(e,t){if(t.length!==0){console.log(`${e}:`);for(let e of t){let t=e.reason?` (${e.reason})`:``;console.log(` ${e.action}: ${e.path}${t}`)}console.log(``)}}function ta(e){let t=zi(),n=Pr(e.base??Bi(t)),r=Pr(e.target),i=Hi(n,r),a=[],o=[],s=[],c=[];for(let e of i){let i=Yi(e.path);if(i){o.push({action:`ignored`,path:e.path,reason:i});continue}let l=Ui(n,e.path),u=Ui(r,e.path),d=$i(l,u);if(!Ji(l)||!Ji(u)){s.push({action:d,path:e.path,reason:`unsupported template entry type`});continue}if(Xi(t,e.path,u).matches){c.push({action:`unchanged`,path:e.path});continue}let f=Xi(t,e.path,l);if(!f.matches){s.push({action:d,path:e.path,reason:f.reason??`downstream differs from base template`});continue}a.push({action:d,path:e.path,targetEntry:u})}if(e.apply)for(let e of a)Qi(t,e.path,e.targetEntry??null);console.log(`Coreframe template fast-forward: ${n} -> ${r}`),console.log(``),ea(e.apply?`Applied clean template updates`:`Would apply clean template updates`,a),ea(`Ignored downstream-owned paths`,o),ea(`Skipped for agent review`,s),c.length>0&&console.log(`${c.length} changed template path(s) already matched the target state.`),i.length===0&&console.log(`No template file changes found in the requested range.`),!e.apply&&a.length>0&&(console.log(``),console.log(`Run with --apply to write the ${a.length} clean update(s).`))}const na=[`dependencies`,`devDependencies`];function ra(e){let t=K(`git`,e,{encoding:`utf8`});if(t.status!==0){let n=t.stderr.trim()||t.stdout.trim();throw Error(`Git command failed: git ${e.join(` `)}${n?`\n${n}`:``}`)}return t.stdout}function ia(e,t){try{return JSON.parse(e)}catch(e){throw Error(`Could not parse ${t}: ${e instanceof Error?e.message:e}`)}}function aa(e,t){let n=`${Pr(e)}:${t}`;return ia(ra([`show`,n]),n)}function oa(e){return e.startsWith(`@coreframe/`)}function sa(e){return e.startsWith(`file:`)||e.startsWith(`link:`)||e.startsWith(`workspace:`)}function ca(e){return e.startsWith(`file:`)||e.startsWith(`link:`)}function la(e,t){let n=e.indexOf(`:`),r=e.slice(n+1),i=le.normalize(le.join(`template`,r,`package.json`));if(r.length===0||le.isAbsolute(r)||i===`..`||i.startsWith(`../`))throw Error(`Invalid local template dependency for ${t}: ${e}`);return i}function ua(e){let t=aa(e,`template/package.json`),n=[],r=new Set;for(let i of na)for(let[a,o]of Object.entries(t[i]??{})){if(!oa(a)||!ca(o))continue;if(r.has(a))throw Error(`Target template declares ${a} more than once.`);let t=la(o,a),s=aa(e,t);if(s.name!==a||typeof s.version!=`string`)throw Error(`${Pr(e)}:${t} must declare ${a} with a version.`);n.push({group:i,name:a,spec:`^${s.version}`}),r.add(a)}return n}function da(e,t){for(let n of na){let r=e[n]?.[t];if(r)return{group:n,spec:r}}}function fa(e,t,n){let r=t.match(/\n([\t ]+)"/u)?.[1]??` `,i=t.endsWith(`
9
9
  `)?`
10
- `:``;Ge(e,`${JSON.stringify(n,null,r)}${i}`)}function pa(e,t){if(t.length!==0){console.log(`${e}:`);for(let e of t)console.log(` ${e}`);console.log(``)}}function ma(e){let t=R(ra([`rev-parse`,`--show-toplevel`]).trim(),`package.json`),n=J(t,`utf8`),r=ia(n,t),i=Pr(e.target),a=ua(i),o=new Set(a.map(({name:e})=>e)),s=[],c=[],l=[],u=0;for(let e of a){let t=da(r,e.name);if(!t){c.push(`missing: ${e.name} ${e.spec} (${e.group})`);continue}if(sa(t.spec)){l.push(`linked: ${e.name} ${t.spec}`);continue}if(t.spec===e.spec){u+=1;continue}s.push({...e,currentGroup:t.group,currentSpec:t.spec})}let d=na.flatMap(e=>Object.entries(r[e]??{}).filter(([e])=>oa(e)&&!o.has(e)).map(([t,n])=>`review: ${t} ${n} (${e})`));if(e.apply&&s.length>0){for(let e of s)r[e.currentGroup][e.name]=e.spec;fa(t,n,r)}console.log(`Coreframe package sync: ${i}`),console.log(``),pa(e.apply?`Updated Coreframe packages`:`Would update Coreframe packages`,s.map(({currentSpec:e,name:t,spec:n})=>`update: ${t} ${e} -> ${n}`)),pa(`Missing target Coreframe packages`,c),pa(`Locally linked Coreframe packages`,l),pa(`Downstream-only Coreframe packages`,d),u>0&&console.log(`${u} Coreframe package(s) already match the target versions.`),s.length===0?console.log(`No Coreframe package version updates found.`):e.apply||(console.log(``),console.log(`Run with --apply to write the ${s.length} package update(s).`))}const ha={...f,displayName:`recipe`,description:`Coreframe recipe name, such as yam-db.`,async from(e){return Sr(e)}},ga=p({name:`upgrade`,cmds:{"ensure-template-remote":n({name:`ensure-template-remote`,args:{remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Remote name to ensure.`}),noFetch:i({long:`no-fetch`,description:`Do not fetch the remote after ensuring it exists.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t})=>Mr({fetch:!e,remote:t})}),"check-skill-current":n({name:`check-skill-current`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),apply:i({long:`apply`,description:`Replace the local upgrade skill with the target version when it differs.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>{process.exitCode=Ni({apply:e,target:t})}}),"fast-forward-template-files":n({name:`fast-forward-template-files`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),base:c({long:`base`,type:l(f),description:`Previous Coreframe template git ref. Defaults to package.json engines.coreframe.`}),apply:i({long:`apply`,description:`Write clean fast-forwards to the worktree.`,defaultValue:()=>!1})},handler:({apply:e,base:t,target:n})=>ta({apply:e,base:t,target:n})}),"sync-coreframe-packages":n({name:`sync-coreframe-packages`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),apply:i({long:`apply`,description:`Update existing published Coreframe dependency specifications.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>ma({apply:e,target:t})})}}),_a=p({name:`recipes`,cmds:{apply:n({name:`apply`,args:{recipe:u({type:ha,displayName:`recipe`,description:`Recipe to prepare and apply.`}),target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,recipe:t,remote:n,target:r})=>si(oi({fetch:!e,name:t,remote:n,target:r}))}),list:n({name:`list`,args:{target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t,target:n})=>Ei(Ti({fetch:!e,remote:t,target:n}))}),verify:n({name:`verify`,args:{recipe:u({type:ha,displayName:`recipe`,description:`Recipe adoption to verify.`}),target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,recipe:t,remote:n,target:r})=>ri(ni({fetch:!e,name:t,remote:n,target:r}))})}}),va=p({name:`db`,cmds:{ensure:n({name:`ensure`,args:{},handler:y}),generate:n({name:`generate`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit generate.`})},handler:({args:e})=>D(`generate`,e)}),migrate:n({name:`migrate`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit migrate.`})},handler:({args:e})=>D(`migrate`,e)}),"migrate-held":n({name:`migrate-held`,args:{confirm:c({long:`confirm`,type:l(s([`run-held-migrations`])),description:`Required confirmation value for held migrations.`})},handler:({confirm:e})=>w({argv:e?[`--confirm=${e}`]:[]})}),"migrate-local":n({name:`migrate-local`,args:{},handler:T}),"migrations-check":n({name:`migrations-check`,args:{},handler:h}),reset:n({name:`reset`,args:{},handler:E}),seed:n({name:`seed`,args:{},handler:()=>te()}),"schema-check":n({name:`schema-check`,args:{seed:i({long:`seed`,description:`Run the configured project seed against the throwaway database.`,defaultValue:()=>!1})},handler:({seed:e})=>g({seed:e})}),setup:n({name:`setup`,args:{},handler:()=>ne()}),studio:n({name:`studio`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit studio.`})},handler:({args:e})=>D(`studio`,e)})}}),ya=`package.json`;async function ba(e=process.argv.slice(2),t=process.env){let n=xa(e);ka(n);let{packageJson:r,source:i}=await lt(ya),a=await Pe(),o=pt(a.deploy??{},n.environment,t);Pa(t,[`POSTHOG_API_KEY`,`POSTHOG_PROJECT_ID`]);let s=await Aa(o,n.environment,()=>Qe({env:t})),c=ht({args:n,config:n.environment===`production`?o.tauriRelease:{},env:t});Na(n.environment,c.enabled),await St(c);let l=await ut({environment:n.environment}),u=l.values.DASHBOARD_PASSWORD??await Fa(t,n.environment);Ct(await $e({environment:n.environment}),n.environment,{availableNames:[...Object.keys(l.values),...u?[`DASHBOARD_PASSWORD`]:[]]});let d=await it({environment:n.environment}),f=await Oa();await Gn({env:t,revision:f});let p=f.slice(0,12),m=mt(n.environment,r.version,p),h=ft(r.name,m),g={...Ra(t,n.environment,h,r.name,m),COREFRAME_I18N_RELEASE_REVISION:f},_=n.environment===`production`,y=!1,b={files:[]};B.intro(`Deploy ${h} to ${n.environment}`);let x=Object.keys(l.values).sort();x.length>0&&B.note(x.join(`
11
- `),`Pending Worker secret updates`),d.provisioned&&B.log.info(`Provisioning Coreframe-managed access-token signing material.`),await Ma(n);let S=await Ta(await v({config:a.database,env:t})),w=await O(S);if(w.length>0)throw Error(`Pending deploy migrations contain unsafe SQL. Move unsafe statements to held migrations.\n${C(w)}`);let T=await Da(n,S);try{_&&(await Tt(ya,r,m),b=await Et(c,m)),B.log.step(`Running pre-deploy build`),await z(`pnpm`,[`build`],{env:za(g),stdio:`inherit`});let e=c.enabled?await at({env:za(g),plan:c,releaseName:h,version:m}):void 0;B.log.step(`Running release build and uploading PostHog source maps`),y=!0,await z(`pnpm`,[`build`],{env:g,stdio:`inherit`}),T&&(B.log.step(`Running deploy-safe database migrations`),await z(`pnpm`,[`db`,`migrate`],{env:g,stdio:`inherit`})),B.log.step(`Deploying Worker and static assets to Cloudflare`);let t={...u?{DASHBOARD_PASSWORD:u}:{},...d.value?{[Je]:d.value}:{},...l.values},i=Object.keys(t).length>0?await Ia(t):void 0,f=await et({coreframeConfig:a,environment:n.environment,contributions:{generatedValues:{DEPLOY_ENV:n.environment,POSTHOG_RELEASE:h}}});try{await z(`pnpm`,[`exec`,`wrangler`,`deploy`,`--config`,f.path,`--env`,n.environment,`--strict`,`--keep-vars`,`--tag`,h,`--message`,`Deploy ${h}`,...i?[`--secrets-file`,i.path]:[]],{env:g,stdio:`inherit`}),await Ye(l),await wt({environment:n.environment})}finally{await f.dispose(),await i?.dispose()}let p={environment:n.environment,releaseName:h,url:s,version:m};o.afterWorkerDeploy&&(B.log.step(`Running required after-Worker deploy hook`),await vt(o,p)),n.skipPostDeployChecks||(B.log.step(`Running post-deploy checks`),await yt(o,p)),e&&(B.log.step(`Uploading Tauri release artifacts to Backblaze B2`),await xt(c,e)),B.outro(`Deployed ${h} to ${n.environment}`)}catch(e){throw!y&&_&&(await W(ya,i),await gt(b)),e}}function xa(e){return{environment:Sa(e[0]),runMigrations:e.includes(`--run-migrations`),skipMigrations:e.includes(`--skip-migrations`),skipPostDeployChecks:e.includes(`--skip-post-deploy-checks`),tauriLocalPlatforms:Ca(e,`--tauri-local-platform`).map(e=>rt(e)),tauriWorkflowName:wa(e,`--tauri-workflow-name`),tauriWorkflowPlatforms:Ca(e,`--tauri-workflow-platform`).map(e=>rt(e)),tauriWorkflowRef:wa(e,`--tauri-workflow-ref`),yes:e.includes(`--yes`)}}function Sa(e){if(e&&Xe.includes(e))return e;throw Error(`Deploy environment must be one of: ${Xe.join(`, `)}.`)}function Ca(e,t){let n=[];for(let r=0;r<e.length;r+=1){let i=e[r];if(i===t){let i=e[r+1];if(!i||i.startsWith(`--`))throw Error(`${t} requires a value.`);n.push(...i.split(`,`).filter(Boolean)),r+=1;continue}i.startsWith(`${t}=`)&&n.push(...i.slice(t.length+1).split(`,`).filter(Boolean))}return n}function wa(e,t){let n=Ca(e,t);if(n.length>1)throw Error(`${t} can only be provided once.`);return n[0]}async function Ta(e){try{return await Ea(e)}finally{await e.close?.()}}async function Ea(e){return b(await _(),await ee(e))}async function Da(e,t){if(t.length===0)return B.log.info(`No pending deploy migrations.`),!1;if(B.note(S(t),`Pending deploy migrations`),e.runMigrations)return!0;if(e.skipMigrations)return!1;if(!process.stdout.isTTY)throw Error(`Pending migrations require --run-migrations or --skip-migrations in noninteractive deploys.`);let n=await B.confirm({initialValue:!0,message:`Run these deploy-safe database migrations before Cloudflare deploy?`});if(B.isCancel(n))throw B.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`);return n}async function Oa(){let{stdout:e}=await z(`git`,[`status`,`--porcelain`],{stdin:`ignore`});if(e.trim().length>0)throw Error(`Deploy requires a clean git tree.`);let{stdout:t}=await z(`git`,[`rev-parse`,`HEAD`],{stdin:`ignore`});return t.trim()}function ka(e){if(e.runMigrations&&e.skipMigrations)throw Error(`Use only one of --run-migrations or --skip-migrations.`)}async function Aa(e,t,n=Qe){return e.url?ja(e.url,t):t===`staging`&&e.stagingHostname?ja(await n(),t):ja(void 0,t)}function ja(e,t){if(!e)throw Error(`Missing ${t} deploy URL. Set DEPLOY_URL or deploy.environments.${t}.url in coreframe.config.ts.`);let n;try{n=new URL(e)}catch{throw Error(`Invalid ${t} deploy URL "${e}". Expected an HTTP(S) URL.`)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw Error(`Invalid ${t} deploy URL "${e}". Expected an HTTP(S) URL.`);return n.toString()}async function Ma(e){if(e.environment!==`production`||e.yes)return;if(!process.stdout.isTTY)throw Error(`Production deploys require --yes in noninteractive environments.`);let t=await B.confirm({initialValue:!1,message:`Deploy to production?`});if(B.isCancel(t)||!t)throw B.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`)}function Na(e,t){if(e===`staging`&&t)throw Error(`Tauri releases can only be published from production deploys.`)}function Pa(e,t){let n=t.filter(t=>!e[t]);if(n.length>0)throw Error(`Missing required deploy environment variables: ${n.join(`, `)}`);return Object.fromEntries(t.map(t=>[t,e[t]]))}async function Fa(e,t){let n=e.DASHBOARD_PASSWORD?.trim();if(n)return n;let r;try{r=It(await H(`.env`,`utf8`))}catch(e){throw La(e)&&e.code===`ENOENT`?Error(`Missing ${t} dashboard password. Set DASHBOARD_PASSWORD in ".env".`):e}let i=r.DASHBOARD_PASSWORD?.trim();if(!i)throw Error(`Missing ${t} dashboard password. Set DASHBOARD_PASSWORD in ".env".`);return i}async function Ia(e){let t=await Ce(L(Ae(),`coreframe-deploy-secrets-`)),n=L(t,`secrets.json`);return await W(n,JSON.stringify(e),{mode:384}),{path:n,dispose:()=>U(t,{force:!0,recursive:!0})}}function La(e){return e instanceof Error&&`code`in e}function Ra(e,t,n,r,i){return{...e,CLOUDFLARE_ENV:t,DEPLOY_ENV:t,POSTHOG_RELEASE:n,POSTHOG_RELEASE_NAME:e.POSTHOG_RELEASE_NAME??r,POSTHOG_RELEASE_VERSION:e.POSTHOG_RELEASE_VERSION??i}}function za(e){let{POSTHOG_API_KEY:t,POSTHOG_PROJECT_ID:n,...r}=e;return r}const $={access:ve,chmod:ye,mkdir:V,mkdtemp:Ce,readFile:H,readFileSync:J,rm:U,writeFile:W},Ba={getAvailablePort:Ha},Va={homedir:Oe,kill:G.kill,networkInterfaces:ke,tmpdir:Ae};async function Ha(){let e=Wt();try{await new Promise((t,n)=>{e.once(`error`,n),e.listen(0,`127.0.0.1`,t)});let t=e.address();if(!t||typeof t==`string`)throw Error(`Could not allocate an available TCP port.`);return t.port}finally{e.listening&&await new Promise((t,n)=>{e.close(e=>e?n(e):t())})}}async function Ua(){let e=await Ga();return typeof e.mobileDevHost==`string`?{mobileDevHost:e.mobileDevHost}:{}}async function Wa(e){let t=await Ga(),n=Ka();await $.mkdir(F.dirname(n),{recursive:!0}),await $.writeFile(n,`${JSON.stringify({...t,...e},void 0,2)}\n`)}async function Ga(){try{let e=await $.readFile(Ka(),`utf8`),t=JSON.parse(e);return qa(t)?t:{}}catch{return{}}}function Ka(){return F.join(Va.homedir(),`.coreframe`,`preferences.json`)}function qa(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function Ja({env:e=G.env,interactive:t=G.stdin.isTTY===!0,platform:n,target:r}){let i=await $a(n,e).catch(()=>[]),a=r?_o(i,r):void 0;if(a)return a;if(!r&&i.length>0)return Qa(i,n,t);let o=r?_o(await to(e).catch(()=>[]),r):void 0;if(o&&o.platform===n)return no(o,n,e,t);let s=await eo(n,e),c=r?_o(s,r):void 0;if(c)return c;if(!r&&s.length>0)return Qa(s,n,t);let l=n===`ios`?`iOS`:`Android`;throw Error(r?`Could not find a ${l} device matching "${r}".`:`No connected ${l} devices or available ${l} ${n===`ios`?`simulators`:`emulators`} were detected.`)}async function Ya(e){let{device:t,host:n,interactive:r=G.stdin.isTTY===!0}=e;if(!t.physical&&n===void 0)return;if(typeof n==`string`&&n!==`0.0.0.0`&&n!==`::`)return n;let i=yo();if(i.length===0)throw Error(`No external IP address was detected. Pass one explicitly with --host.`);let a=await Xa();if(a&&i.includes(a))return a;if(i.length===1)return await Za(i[0]),i[0];if(!r)throw Error(`Multiple external IP addresses were detected (${i.join(`, `)}). Pass one explicitly with --host.`);let o=await B.select({message:`Which IP address should the mobile device use to reach the development server?`,options:i.map(e=>({label:e,value:e}))});if(B.isCancel(o))throw Error(`Mobile development IP selection was cancelled.`);return await Za(o),o}async function Xa(){return(await Ua()).mobileDevHost}async function Za(e){try{await Wa({mobileDevHost:e})}catch(e){B.log.warn(`Could not remember the mobile development IP address: ${e instanceof Error?e.message:String(e)}`)}}async function Qa(e,t,n){if(e.length===1)return e[0];if(!n)throw Error(`Multiple ${t===`ios`?`iOS`:`Android`} devices were detected. Pass a device name explicitly.`);let r=await B.select({message:`Which ${t===`ios`?`iOS`:`Android`} device should Coreframe use?`,options:e.map(e=>({label:e.label,value:e,hint:e.id}))});if(B.isCancel(r))throw Error(`Mobile development device selection was cancelled.`);return r}async function $a(e,t){return e===`android`?io(t):oo(t)}async function eo(e,t){return e===`android`?ao(t):so(t)}async function to(e){let{stdout:t}=await z(`flutter`,[`emulators`],{env:e});return t.split(/\r?\n/).flatMap(e=>{let[t,n,,r]=e.split(/\s*•\s*/).map(e=>e.trim());return t&&n&&(r===`android`||r===`ios`)?[{id:t,label:n,name:n,physical:!1,platform:r}]:[]})}async function no(e,t,n,r){let i=await ro(t,n).catch(()=>[]),{stdout:a}=await z(`flutter`,[`emulators`,`--launch`,e.id],{env:n});if(/No emulator found|More than one emulator matches/i.test(a))throw Error(a.trim());let o=Date.now()+3e4;do{let a=await ro(t,n).catch(()=>[]),o=_o(a,e.id);if(o)return o;let s=a.filter(e=>!i.some(t=>t.id===e.id));if(s.length>0)return Qa(s,t,r);if(a.length===1)return a[0];await Gt(250)}while(Date.now()<o);let s=t===`ios`?`iOS simulator`:`Android emulator`;throw Error(`Flutter launched "${e.id}", but no ${s} became available.`)}async function ro(e,t){return e===`ios`?so(t,`booted`):(await io(t)).filter(e=>!e.physical)}async function io(e){let t=await lo(e,`platform-tools`,G.platform===`win32`?`adb.exe`:`adb`),{stdout:n}=await z(t,[`devices`],{env:e}),r=n.split(/\r?\n/).map(e=>e.match(/^(\S+)\s+device(?:\s|$)/)?.[1]).filter(e=>e!==void 0);return(await Promise.all(r.map(async n=>{let r=await fo(t,e,n,`ro.product.model`),i=n.startsWith(`emulator-`),a=i?await mo(t,e,n,r):await ho(t,e,n,r);return{id:n,label:a===r?a:`${a} (${r})`,name:a,physical:!i}}))).sort(bo)}async function ao(e){let{stdout:t}=await z(await lo(e,`emulator`,G.platform===`win32`?`emulator.exe`:`emulator`),[`-list-avds`],{env:e});return t.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0&&!/^(INFO|WARNING|ERROR)\s+\|/.test(e)).map(e=>({id:e,label:e,name:e,physical:!1}))}async function oo(e){let t=await $.mkdtemp(F.join(Va.tmpdir(),`coreframe-ios-devices-`)),n=F.join(t,`devices.json`);try{return await $.writeFile(n,``),await z(`xcrun`,[`devicectl`,`list`,`devices`,`--json-output`,n],{env:e}),(JSON.parse(await $.readFile(n,`utf8`)).result?.devices??[]).filter(co).map(e=>({id:e.hardwareProperties.udid,label:`${e.deviceProperties.name} (${e.hardwareProperties.productType})`,name:e.deviceProperties.name,physical:!0})).sort(bo)}finally{await $.rm(t,{force:!0,recursive:!0})}}async function so(e,t=`available`){let{stdout:n}=await z(`xcrun`,[`simctl`,`list`,`--json`,`devices`,t],{env:e}),r=JSON.parse(n);return Object.entries(r.devices??{}).filter(([e])=>e.includes(`iOS-`)).flatMap(([,e])=>e).flatMap(e=>e.name&&e.udid?[{id:e.udid,label:e.name,name:e.name,physical:!1}]:[]).sort(bo)}function co(e){return e.connectionProperties?.tunnelState!==`unavailable`&&typeof e.hardwareProperties?.platform==`string`&&(e.hardwareProperties.platform.includes(`iOS`)||e.hardwareProperties.platform.includes(`xrOS`))&&typeof e.deviceProperties?.name==`string`&&typeof e.hardwareProperties.productType==`string`&&typeof e.hardwareProperties.udid==`string`}async function lo(e,t,n){let r=e.ANDROID_HOME??e.ANDROID_SDK_ROOT,i=r?[r]:uo(e);for(let e of i){let r=F.join(e,t,n);try{return await $.access(r),r}catch{}}return n}function uo(e){return G.platform===`darwin`?[F.join(Va.homedir(),`Library`,`Android`,`sdk`)]:G.platform===`win32`&&e.LOCALAPPDATA?[F.join(e.LOCALAPPDATA,`Android`,`Sdk`)]:[F.join(Va.homedir(),`Android`,`Sdk`)]}async function fo(e,t,n,r){return(await po(e,t,[`-s`,n,`shell`,`getprop`,r])).trim()}async function po(e,t,n){return(await z(e,n,{env:t,timeout:3e3})).stdout}async function mo(e,t,n,r){return po(e,t,[`-s`,n,`emu`,`avd`,`name`]).then(e=>e.split(/\r?\n/)[0]?.trim()||r).catch(()=>r)}async function ho(e,t,n,r){return po(e,t,[`-s`,n,`shell`,`dumpsys`,`bluetooth_manager`]).then(e=>go(e)||r).catch(()=>r)}function go(e){return e.match(/\bname: (.+)/)?.[1]?.trim()}function _o(e,t){let n=e.map(e=>({device:e,score:Math.max(vo(t,e.name),vo(t,e.id))})).sort((e,t)=>t.score-e.score)[0];return n&&n.score>0?n.device:void 0}function vo(e,t){let n=e.toLowerCase(),r=t.toLowerCase();if(r===n)return 1e4;let i=r.indexOf(n);if(i>=0)return 5e3-i;let a=0,o=0;for(let e of n){let t=r.indexOf(e,o);if(t<0)return 0;a+=t===o?2:1,o=t+1}return a}function yo(){return[...new Set(Object.values(Va.networkInterfaces()).flatMap(e=>e??[]).filter(e=>!e.internal&&e.family===`IPv4`).map(e=>e.address))].sort()}function bo(e,t){return e.label.localeCompare(t.label)}function xo({host:e=`127.0.0.1`,port:t,start:n}){let r,i=!1,a=!1,o=!1,s,c,l,u,d,f=new Set,p=new Promise((e,t)=>{u=e,d=t}),m=e=>{a||o||(o=!0,d(e))},h=()=>(s||=Promise.resolve().then(n).catch(e=>{throw m(e),e}),s),g=e=>{f.add(e),e.once(`close`,()=>f.delete(e)),e.pause(),_(e).catch(t=>{m(t),e.destroy()})},_=async e=>{let t=await h();if(a||e.destroyed)return;let n=await So(t,()=>a);if(a||e.destroyed){n.destroy();return}f.add(n),n.once(`close`,()=>f.delete(n)),n.on(`error`,()=>e.destroy()),n.once(`close`,()=>e.destroy()),e.on(`error`,()=>n.destroy()),e.once(`close`,()=>n.destroy()),e.pipe(n),n.pipe(e)};return{close:async()=>l||(l=(async()=>{a=!0,o||(o=!0,u());for(let e of f)e.destroy();f.clear(),c&&!i&&await Promise.allSettled([c]),!(!r||!i)&&(await new Promise(e=>{r.close(()=>e())}),i=!1)})(),l),fail:m,listen:async()=>c||(r=Wt(g),c=new Promise((n,a)=>{let o=e=>{if(i){m(e);return}a(e)};r.once(`error`,o),r.once(`listening`,()=>{i=!0,r.off(`error`,o),r.on(`error`,m),n()}),r.listen(t,e)}),c),wait:()=>p}}async function So(e,t){let n=Date.now()+1e4,r;for(;!t();)try{return await Co(e)}catch(e){if(r=e,Date.now()>=n)break;await new Promise(e=>setTimeout(e,50))}throw r instanceof Error?r:Error(`Could not connect to the dashboard.`)}function Co({host:e=`127.0.0.1`,port:t}){return new Promise((n,r)=>{let i=Ut({host:e,port:t}),a=e=>{i.off(`connect`,o),i.destroy(),r(e)},o=()=>{i.off(`error`,a),n(i)};i.once(`error`,a),i.once(`connect`,o)})}const wo={command:Bo,isRunning:jo,stop(e){try{G.kill(e,`SIGTERM`)}catch(e){if(!Po(e))throw e}},waitForExit:Mo};async function To({confirmStop:e=Oo,cwd:t=G.cwd(),interactive:n=G.stdin.isTTY===!0,pid:r=G.pid,platform:i=`web`,processes:a=wo}={}){let o=await Uo(t,i),s=o.file,c={pid:r,platform:i,repository:o.repository,token:Le()},l=`${JSON.stringify(c)}\n`,u=`${s}.${c.token}.tmp`,d=await Io({confirmStop:e,file:F.resolve(t,`.coreframe/dev.lock`),interactive:n,owner:c,processes:a});if(d===void 0)return;let f=d;await V(F.dirname(s),{recursive:!0}),await W(u,l,{flag:`wx`,mode:384});try{for(;;){try{return await Se(u,s),{owner:c,async release(){await Ao(s,l)},takeoverApproved:f}}catch(e){if(!No(e))throw e}let t=await Do({confirmStop:e,file:s,interactive:n,owner:c,processes:a});if(t===void 0)return;f||=t}}finally{await De(u).catch(()=>void 0)}}async function Eo({cwd:e=G.cwd(),platform:t=`web`}={}){let{file:n}=await Uo(e,t);return(await ko(n))?.owner}async function Do({confirmStop:e,file:t,interactive:n,owner:r,processes:i}){let a=await ko(t);if(!a||!qo(a.owner,r)||!i.isRunning(a.owner.pid))return await Ao(t,a?.source),!1;if(!n)throw Error(`Coreframe dev is already running for this project (PID ${a.owner.pid}). Stop it before starting another.`);if(await e(a.owner.pid))return i.stop(a.owner.pid),await i.waitForExit(a.owner.pid),await Ao(t,a.source),!0}async function Oo(e){let t=await B.confirm({initialValue:!1,message:`Coreframe dev is already running for this project (PID ${e}). Stop it and start here?`});return B.isCancel(t)||!t?(B.cancel(`Keeping the existing Coreframe dev process.`),!1):!0}async function ko(e){try{let t=await H(e,`utf8`),n=JSON.parse(t);return!Number.isSafeInteger(n.pid)||Number(n.pid)<=0||typeof n.platform!=`string`||n.platform.length===0||typeof n.repository!=`string`||n.repository.length===0||typeof n.token!=`string`||n.token.length===0?void 0:{owner:n,source:t}}catch{return}}async function Ao(e,t){let n=await H(e,`utf8`).catch(()=>void 0);(t===void 0||n===t)&&await De(e).catch(()=>void 0)}function jo(e){try{return G.kill(e,0),!0}catch(e){return!Po(e)}}async function Mo(e){let t=Date.now()+1e4;for(;jo(e);){if(Date.now()>=t)throw Error(`Coreframe dev process ${e} did not stop within 10 seconds.`);await new Promise(e=>setTimeout(e,50))}}function No(e){return Fo(e)&&e.code===`EEXIST`}function Po(e){return Fo(e)&&e.code===`ESRCH`}function Fo(e){return e instanceof Error}async function Io({confirmStop:e,file:t,interactive:n,owner:r,processes:i}){let a=await Lo(t);if(!a||!i.isRunning(a.owner.pid))return await Ao(t,a?.source),!1;let o=i.command?.(a.owner.pid);if(!o||!Ro(o,r.platform))return!1;if(!n)throw Error(`Coreframe dev is already running for this project (PID ${a.owner.pid}). Stop it before starting another.`);if(await e(a.owner.pid))return i.stop(a.owner.pid),await i.waitForExit(a.owner.pid),await Ao(t,a.source),!0}async function Lo(e){try{let t=await H(e,`utf8`),n=JSON.parse(t);return!Number.isSafeInteger(n.pid)||Number(n.pid)<=0||typeof n.token!=`string`||n.token.length===0?void 0:{owner:n,source:t}}catch{return}}function Ro(e,t){let n=e.trim().split(/\s+/u),r=n.findIndex(e=>{let t=e.split(/[\\/]/u).at(-1);return t===`coreframe`||t===`coreframe.js`||t===`coreframe.ts`});if(r<0)return!1;let i=n.indexOf(`dev`,r+1);return i<0?!1:zo(n.slice(i+1))===t}function zo(e){let t=new Set([`android`,`desktop`,`ios`,`macos`,`web`]),n=new Set([`--debug`,`--host`,`--port`]),r=!1;for(let i of e){if(r){r=!1;continue}if(n.has(i)){r=!0;continue}if(!i.startsWith(`-`))return t.has(i)?i:`web`}return`web`}function Bo(e){let t=G.platform===`win32`?Ho(e):Vo(e);if(t.status===0)return t.stdout.trim()||void 0}function Vo(e){return K(`ps`,[`-p`,String(e),`-o`,`command=`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]})}function Ho(e){return K(`powershell.exe`,[`-NoProfile`,`-NonInteractive`,`-Command`,`(Get-CimInstance Win32_Process -Filter 'ProcessId = ${e}').CommandLine`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]})}async function Uo(e,t){let n=await Wo(F.resolve(e)),r=n.gitCommonDir?F.join(n.path,`coreframe-dev`):F.join(n.path,`.coreframe`);return{file:F.join(r,`dev.${t}.lock`),repository:n.path}}async function Wo(e){let t=Go(e);return t?{gitCommonDir:!0,path:await Ko(F.resolve(e,t))}:{gitCommonDir:!1,path:await Ko(e)}}function Go(e){let t=K(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]});if(t.status===0)return t.stdout.trim()||void 0}async function Ko(e){return we(e).catch(()=>F.resolve(e))}function qo(e,t){return e.platform===t.platform&&e.repository===t.repository}function Jo(e,t){let n={...e};return t===`desktop`?delete n.COREFRAME_PLATFORM:t===`web`||t===`webext`?n.COREFRAME_PLATFORM=`web`:n.COREFRAME_PLATFORM=t,n}async function Yo({cwd:e=G.cwd(),platform:t}){let n=await Xo({cwd:e});if(!n||!as(n.platform)||!os(n.platform,t)||!cs(n.owner.pid))return;let r=await Eo({cwd:e,platform:n.platform});if(!(!r||!ls(n.owner,r))&&!(n.postgres?.pid!==void 0&&!cs(n.postgres.pid)))return n}async function Xo({cwd:e=G.cwd()}={}){let t;try{t=JSON.parse(await H($o(e),`utf8`))}catch{return}return es(t)&&t.cwd===F.resolve(e)?t:void 0}async function Zo({cwd:e=G.cwd(),owner:t,platform:n,postgres:r,vitePort:i}){let a=$o(e),o=F.dirname(a),s=`${a}.${Le()}.tmp`,c={cwd:F.resolve(e),owner:t,platform:n,...r?{postgres:r}:void 0,version:1,vite:{port:i}};await V(o,{recursive:!0});try{await W(s,`${JSON.stringify(c)}\n`,{flag:`wx`,mode:384}),await Te(s,a)}finally{await De(s).catch(()=>void 0)}}async function Qo({cwd:e=G.cwd(),owner:t}){let n=$o(e),r=await Xo({cwd:e});!r||!ls(r.owner,t)||await De(n).catch(()=>void 0)}function $o(e){return F.resolve(e,`.coreframe/dev.session.json`)}function es(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.version===1&&typeof t.cwd==`string`&&ts(t.owner)&&rs(t.platform)&&ss(t.vite?.port)&&(t.postgres===void 0||ns(t.postgres))}function ts(e){if(!e||typeof e!=`object`)return!1;let t=e,n=t.pid;return typeof n==`number`&&Number.isSafeInteger(n)&&n>0&&typeof t.token==`string`}function ns(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.dataDir==`string`&&(t.pid===void 0||Number.isSafeInteger(t.pid)&&t.pid>0)}function rs(e){return e===`android`||e===`desktop`||e===`ios`||e===`macos`||e===`web`}function is(e){return e===`android`||e===`ios`||e===`macos`}function as(e){return e===`web`||is(e)}function os(e,t){return t===void 0?is(e):e===t}function ss(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0&&e<=65535}function cs(e){try{return G.kill(e,0),!0}catch(e){return e instanceof Error&&e.code===`EPERM`}}function ls(e,t){return e.pid===t.pid&&e.token===t.token}const us=G.platform===`win32`?`pnpm.cmd`:`pnpm`,ds=G.platform===`win32`?`portless.cmd`:`portless`,fs=G.platform===`win32`?`react-router.cmd`:`react-router`,ps=G.platform===`win32`?`turso.cmd`:`turso`;async function ms({cwd:e=G.cwd(),debug:t,device:n,env:r=G.env,host:i,https:a=!1,interactive:o=G.stdin.isTTY===!0,managed:s=!1,noManaged:c=!1,platform:l=`web`,fresh:u=!1,reuseVite:d=!1,verbose:f=!1,webPort:p,supervisor:m}){let h=Ot({env:r}),g=bs(l)?l:void 0,_=xs(l),v=l===`ios`||l===`android`?l:void 0,y=v?await Ja({env:r,interactive:o,platform:v,target:n}):void 0,b=v&&y?await Ya({device:y,host:i,interactive:o,platform:v}):void 0,x=g?!0:i,S=await h.measure(`config`,()=>Pe({cwd:e})),C=await h.measure(`managed`,async()=>t!==`managed-dev-overlay`&&(s||o&&!c)&&await jt(e));await h.measure(`i18n`,()=>Un({cwd:e,projectConfig:S}));let w=await h.measure(`routing`,async()=>l===`web`&&r.PORTLESS!==`0`&&r.TAURI_ENV_PLATFORM===void 0&&!(await Vt()).isAgent&&await Mt(e)),T=await h.measure(`https`,async()=>a&&!w?Nt({cwd:e}):void 0),ee=Jo(r,l),E={...ee,...h.environment,...C?{[zt]:`1`,[Bt]:`1`}:void 0,...t===`managed-dev-overlay`?{VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG:`1`}:void 0,...g?{COREFRAME_PLATFORM:g}:void 0,...T?{[kt]:T.cert,[At]:T.key}:void 0},D=!1,O,te,ne,k,A,j,M,ie=new Map,N=[`postgres`,_];for(let e of N){let t=e===`postgres`?`postgres`:e.startsWith(`vite:flutter`)?`flutter`:`web`,n=Y({label:t}),r=Y({color:`red`,label:t});n.pipe(G.stdout,{end:!1}),r.pipe(G.stderr,{end:!1}),ie.set(e,{stderr:r,stdout:n})}let ae=m.onEvent(e=>{e.event===`log`?(ie.get(e.resource)?.[e.stream])?.write(e.data):e.event===`service`&&e.resource===_&&e.state===`failed`&&(M=Error(e.error??`${_} development failed.`),P())}),P=()=>{D||(D=!0,ne?.kill(`SIGTERM`),k?.kill(`SIGTERM`),te?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0))},oe=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>{O??=e,P()};return G.on(e,t),{handler:t,signal:e}}),I=async e=>{let t=Ht(e);ne=t;try{await t.expectSuccess()}catch(e){if(!D)throw e}finally{ne===t&&(ne=void 0)}};try{if(await m.subscribe(N),ys(S)){let e=await m.acquirePostgres({config:S,env:E});A=e.leaseId,E={...E,...e.env}}if(S.database?.dialect===`sqlite`){let t=await Ba.getAvailablePort(),n=F.resolve(e,`.coreframe`),r=F.join(n,`turso.db`);await $.mkdir(n,{recursive:!0}),E={...E,TURSO_DATABASE_URL:`http://127.0.0.1:${t}`,TURSO_AUTH_TOKEN:`dev`},k=Ht({name:`turso`,command:ps,args:[`dev`,`--port`,String(t),`--db-file`,r],cwd:e,env:E}),await k.waitFor(`listening`)}(ys(S)||S.database?.dialect===`sqlite`)&&await h.measure(`schema`,()=>I({name:`db`,command:us,args:[`db`,`ensure`],cwd:e,env:E,prefix:!1}));let t=vs(p??r.COREFRAME_WEB_PORT),n=await m.status(),i=n.resources?.find(e=>e.resource===_),s=i!==void 0&&!u&&t===void 0?void 0:t??5173,c=s??i?.endpoint?.port??5173;if(s!==void 0&&n.resources?.some(e=>e.resource!==_&&e.endpoint?.port===c)){if(t!==void 0)throw Error(`Port ${c} is already used by another Coreframe development shell.`);c=await Ba.getAvailablePort()}if(!d){let t={...E,CLOUDFLARE_ENV:`development`,NODE_OPTIONS:[E.NODE_OPTIONS,`--conditions=development`].filter(Boolean).join(` `),PATH:F.join(e,`node_modules`,`.bin`)+F.delimiter+(E.PATH??``)},n=[{args:w?[`run`,`--app-port`,String(c),`react-router`,`dev`,...x===void 0?[]:[`--host`,x===!0?`0.0.0.0`:x]]:[`dev`,...x===void 0?[]:[`--host`,x===!0?`0.0.0.0`:x],`--port`,String(c),...g?[`--strictPort`]:[]],command:w?ds:fs,cwd:e,env:t},{args:[`exec`,`panda`,`dev`,`--no-color`],command:us,cwd:e,env:E}],r=await m.acquireVite({configFingerprint:_s({cwd:e,host:x,https:a,portless:w,resource:_}),endpoint:{host:x===!0?`0.0.0.0`:x??`127.0.0.1`,port:c},processes:n,resource:_},u);j=r.leaseId,c=r.endpoint.port}if(h.report(),D)return;if(l===`web`?await gs(m,_,()=>M):(await re({cwd:e}),await hs({cwd:e,env:ee,interactive:o,mobileHost:b,platform:l,port:c,requestStop:P,selectedDevice:y,isStopping:()=>D,setActiveNative:e=>{te=e},verbose:f})),M)throw M}finally{P(),j&&await m.release(j).catch(()=>void 0),A&&await m.release(A).catch(()=>void 0),ae();for(let{handler:e,signal:t}of oe)G.off(t,e);for(let e of ie.values())e.stdout.end(),e.stderr.end();O&&(G.exitCode??=O===`SIGINT`?130:143),m.close()}}async function hs({cwd:e,env:t,interactive:n,mobileHost:r,platform:i,port:a,requestStop:o,selectedDevice:s,isStopping:c,setActiveNative:l,verbose:u}){for(;;){let d=i===`android`&&!u?await ae():void 0,f=z(`flutter`,[`run`,`-d`,s?.id??`macos`,`--dart-define=COREFRAME_DEV_SERVER_URL=${Ss(i,r,a)}`,...u?[`--verbose`]:[]],{cwd:F.join(e,`src-flutter`),env:t,stdio:d?[`inherit`,`pipe`,`pipe`]:`inherit`});l(f);try{await Promise.all([f,d?.capture(f)]);return}catch(e){if(c()||i===`desktop`||!n)throw e;let t=await B.confirm({initialValue:!0,message:`Flutter failed. Retry?`});if(B.isCancel(t)||!t){o();return}}finally{l(void 0)}}}async function gs(e,t,n){await e.waitForServiceExit(t);let r=n();if(r)throw r}function _s({cwd:e,host:t,https:n,portless:r,resource:i}){return Ie(`sha256`).update(JSON.stringify({cwd:F.resolve(e),host:t??null,https:n,portless:r,resource:i})).digest(`hex`)}function vs(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}function ys(e){return(e.database?.dialect??`postgres`)===`postgres`}function bs(e){return e===`android`||e===`ios`||e===`macos`}function xs(e){if(e===`web`)return`vite:web`;if(bs(e))return`vite:flutter:${e}`;throw Error(`Unsupported supervised development platform: ${e}.`)}function Ss(e,t,n){let r=t??(e===`android`?`10.0.2.2`:`127.0.0.1`);return`http://${r.includes(`:`)&&!r.startsWith(`[`)?`[${r}]`:r}:${n}`}const Cs=`extension:dev`;function ws(e){if(!q(L(e,`src-webext/wxt.config.ts`)))throw Error("No WXT configuration found at src-webext/wxt.config.ts. Apply the wxt recipe or add that convention before running `coreframe dev webext`.");let t=L(e,`package.json`),n;try{n=JSON.parse(J(t,`utf8`))}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}if(!n||typeof n!=`object`||!(`scripts`in n)||!n.scripts||typeof n.scripts!=`object`||!(`extension:dev`in n.scripts)||typeof n.scripts[`extension:dev`]!=`string`)throw Error(`package.json must define scripts.${Cs} for \`coreframe dev webext\`. Apply the wxt recipe and add its named extension lifecycle scripts.`)}function Ts({host:e,port:t}){let n=[...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)]];return[`run`,Cs,...n.length>0?[`--`,...n]:[]]}const Es=[`web`,`webext`,`desktop`,`ios`,`android`,`macos`],Ds=[`managed-dev-overlay`],Os=F.resolve(`node_modules`,`.bin`),ks=G.platform===`win32`?`pnpm.cmd`:`pnpm`,As=G.platform===`win32`?`portless.cmd`:`portless`,js=G.platform===`win32`?`react-router.cmd`:`react-router`,Ms=G.platform===`win32`?`turso.cmd`:`turso`;async function Ns({cwd:e=G.cwd(),debug:t,device:n,env:r=G.env,host:i,https:a=!1,interactive:o=G.stdin.isTTY===!0,managed:s=!1,noManaged:c=!1,platform:l=`web`,fresh:u=!1,reuseVite:d=!1,supervisor:f,verbose:p=!1,webPort:m}={}){let h=Ot({env:r}),g=r.PATH??r.Path??``,_=l===`ios`||l===`android`||l===`macos`?l:void 0,v=l===`web`||_!==void 0;if(u&&d)throw Error(`Cannot use --fresh and --reuse-vite together.`);let y=!u&&(_||l===`web`)?await h.measure(`dev-session`,()=>Yo({cwd:e,platform:l})):void 0,b=d||y!==void 0,x=l===`desktop`?void 0:Ks(m??r.COREFRAME_WEB_PORT);if(y&&x!==void 0&&x!==y.vite.port)throw Error(`The active development session uses port ${y.vite.port}. Omit --port or use that port when reusing it.`);let S=l===`ios`||l===`android`||l===`macos`?y?.vite.port??x??5173:l===`web`||l===`webext`?y?.vite.port??x:void 0,C,w,T,ee,E,D,O,te,ne,k=!1,A,j=r,M,ie;if(s&&c)throw Error(`Cannot use --managed and --no-managed together.`);if(t===`managed-dev-overlay`&&s)throw Error(`Cannot use --managed with --debug managed-dev-overlay.`);if(d&&_===void 0)throw Error(`The --reuse-vite option is only supported for Flutter development platforms (iOS, Android, and macOS).`);if(l===`webext`){if(s||c||t!==void 0||p)throw Error(`Managed development, debug features, and verbose native output are only supported for the main web or native development platforms.`);ws(e)}if(a&&l!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);if(n!==void 0&&l!==`ios`&&l!==`android`)throw Error(`A device name or ID is only supported for iOS or Android development.`);if(l===`web`&&r.TAURI_ENV_PLATFORM!==void 0&&r.COREFRAME_TAURI_DEV!==`1`)throw Error("Direct Tauri development is not supported. Run `pnpm dev desktop` instead.");if(v&&r.COREFRAME_DEV_SUPERVISOR!==`0`){let h=f??await Dt({cwd:e,env:r});if(h)return ms({cwd:e,debug:t,device:n,env:r,fresh:u,host:i,https:a,interactive:o,managed:s,noManaged:c,platform:l,reuseVite:d,supervisor:h,verbose:p,webPort:m})}let N=b?void 0:await h.measure(`dev-lock`,()=>To({cwd:e,interactive:o,platform:l}));if(!b&&!N)return;let P=()=>{k||(k=!0,w?.kill(`SIGTERM`),ee?.kill(`SIGTERM`),D?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),O?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),ne?.close().catch(()=>void 0),te?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),C?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),E?.kill(`SIGTERM`))},oe=e=>{A??=e,P()},I=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>oe(e);return G.on(e,t),{handler:t,signal:e}}),se=async e=>{let t=Ht(e);w=t;try{await t.expectSuccess()}catch(e){if(!k)throw e}finally{w===t&&(w=void 0)}};try{let u=l===`ios`||l===`android`?l:void 0,d=u?await Ja({env:r,interactive:o,platform:u,target:n}):void 0,f=u&&d?await Ya({device:d,host:i,interactive:o,platform:u}):void 0,m=_?!0:i,v={},y=!1,x=!1,w;b||([v,y,x]=await Promise.all([h.measure(`config`,()=>Pe({cwd:e})),h.measure(`routing`,async()=>l===`web`&&r.PORTLESS!==`0`&&r.TAURI_ENV_PLATFORM===void 0&&!(await Vt()).isAgent&&await Mt(e)),h.measure(`managed`,async()=>t!==`managed-dev-overlay`&&(s||o&&!c)&&await jt(e))]),await h.measure(`i18n`,()=>Un({cwd:e,projectConfig:v})),w=l!==`webext`&&Ps(e)?await Ba.getAvailablePort():void 0);let A=b?void 0:await h.measure(`https`,async()=>a&&!y?Nt({cwd:e}):void 0),oe=Jo(r,l);j={...oe,...h.environment,...x?{[zt]:`1`}:void 0,...t===`managed-dev-overlay`?{VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG:`1`}:void 0,...l===`desktop`?{COREFRAME_TAURI_DEV:`1`,TAURI_ENV_PLATFORM:Us()}:void 0,..._?{COREFRAME_PLATFORM:_}:void 0,...A?{[kt]:A.cert,[At]:A.key}:void 0,...w?{COREFRAME_DASHBOARD_ORIGIN:`http://127.0.0.1:${w}`}:void 0};let I=async()=>{if(!w)return;let t,n=async(e,n)=>{try{await e,k||t?.fail(Error(`The dashboard development server stopped unexpectedly.`))}catch(e){k||t?.fail(e)}finally{await n.outputTasks,n.stdout.end(),n.stderr.end(),await Promise.allSettled([Rt(n.stdout),Rt(n.stderr)]),te===e&&(te=void 0)}};t=xo({port:w,start:async()=>{if(k)throw Error(`The dashboard development server was stopped before it started.`);let t=await Ba.getAvailablePort();if(k)throw Error(`The dashboard development server was stopped before it started.`);let r=Y({label:`dashboard`}),i=Y({color:`red`,label:`dashboard`});r.pipe(G.stdout,{end:!1}),i.pipe(G.stderr,{end:!1});let a=z(js,[`dev`,`--host`,`127.0.0.1`,`--port`,String(t)],{cwd:F.resolve(e,`dashboard`),env:{...j,PATH:F.resolve(e,`node_modules/.bin`)+F.delimiter+g},stdin:`inherit`});te=a;let o=Promise.allSettled([Fs(a.stdout,r),Fs(a.stderr,i)]);return n(a,{outputTasks:o,stderr:i,stdout:r}),{host:`127.0.0.1`,port:t}}}),ne=t;try{await t.listen(),await t.wait()}finally{await t.close(),ne===t&&(ne=void 0)}},L=async()=>{let t=Y({label:`web`}),n=Y({color:`red`,label:`web`});t.pipe(G.stdout,{end:!1}),n.pipe(G.stderr,{end:!1}),D=z(y?As:js,y?Gs({host:m,port:S}):Ws({host:m,port:S,strictPort:_!==void 0}),{cwd:e,env:{...j,CLOUDFLARE_ENV:`development`,NODE_OPTIONS:[j.NODE_OPTIONS,`--conditions=development`].filter(Boolean).join(` `),PATH:Os+F.delimiter+g},stdin:`inherit`});let r=Promise.allSettled([Fs(D.stdout,t),Fs(D.stderr,n)]);try{await D;let e=(await r).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!k)throw e}finally{await r,t.end(),n.end(),await Promise.allSettled([Rt(t),Rt(n)]),D=void 0}},ce=async()=>{let t=Y({label:`webext`}),n=Y({color:`red`,label:`webext`});t.pipe(G.stdout,{end:!1}),n.pipe(G.stderr,{end:!1}),O=z(ks,Ts({host:i,port:S}),{cwd:e,env:j,stdin:`inherit`});let r=Promise.allSettled([Fs(O.stdout,t),Fs(O.stderr,n)]);try{await O;let e=(await r).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!k)throw e}finally{await r,t.end(),n.end(),await Promise.allSettled([Rt(t),Rt(n)]),O=void 0}},R=async t=>{for(;!k;){let n=l===`android`&&!p?await ae():void 0,r=l===`desktop`?z(ks,Bs(),{cwd:e,env:oe,stdio:`inherit`}):z(`flutter`,Vs({device:d??{id:`macos`},serverUrl:Hs(l,f,S),verbose:p}),{cwd:F.join(e,`src-flutter`),env:oe,stdio:n?[`inherit`,`pipe`,`pipe`]:`inherit`});C=r;try{await Promise.all([r,n?.capture(r)]);return}catch(e){if(l===`desktop`||k||!o)throw e;let n=await B.confirm({initialValue:!0,message:`Flutter failed. Retry?`});if(B.isCancel(n)||!n){B.log.warn(t?`Flutter stopped. Web development is still running.`:`Flutter stopped.`),t&&await t;return}}finally{C===r&&(C=void 0)}}},le=async()=>{if(b){if(l===`web`)return;await re({cwd:e}),await R();return}if(l===`web`){await L();return}let t=L().then(()=>{if(!k)throw Error(`The Vite development server stopped while ${l===`desktop`?`Tauri`:`Flutter`} was still running.`)});l!==`desktop`&&await re({cwd:e});try{await Promise.race([t,R(t)])}finally{P(),await Promise.allSettled([t,C]),C=void 0}},ue=async()=>{let t=Ht({name:`panda`,command:ks,args:[`exec`,`panda`,`dev`,`--no-color`],cwd:e,env:j});ee=t;try{if(await t.expectSuccess(),!k)throw Error(`The Panda CSS watcher stopped while development was still running.`)}catch(e){if(!k)throw e}finally{ee===t&&(ee=void 0)}},de=async()=>{if(l===`webext`){await ce();return}if(b){await le();return}let e=ue(),t=le(),n=w?I():void 0;try{await Promise.race([e,t,n].filter(e=>e!==void 0)),k&&await t}finally{P(),await Promise.allSettled([e,t,n].filter(e=>e!==void 0))}},fe=async()=>{b||!N?.owner||S===void 0||(await Zo({cwd:e,owner:N.owner,platform:l,postgres:ie,vitePort:S}),M=N.owner)};if(x&&(j={...j,[Bt]:`1`}),k)return;if(l===`webext`){h.report(),await de();return}if(b){h.report(),await de();return}if(v.database?.dialect===`sqlite`&&(await h.measure(`database`,async()=>{let t=await Ba.getAvailablePort(),n=F.resolve(e,`.coreframe`),i=F.join(n,`turso.db`);await $.mkdir(n,{recursive:!0}),j={...j,TURSO_DATABASE_URL:`http://127.0.0.1:${t}`,TURSO_AUTH_TOKEN:`dev`},E=Ht({name:`turso`,command:Ms,args:[`dev`,`--port`,String(t),`--db-file`,i],cwd:e,env:r}),await E.waitFor(`listening`)}),await h.measure(`schema`,()=>se({name:`db`,command:ks,args:[`db`,`ensure`],cwd:e,env:j,prefix:!1})),k))return;if(zs(v)){let t=Y({label:`postgres`});t.pipe(G.stdout,{end:!1});try{let n=await h.measure(`database`,()=>Rs({config:v,cwd:e,env:j,failIfRunning:!0,interactive:o,isStopping:()=>k,postgresOutput:t,takeoverApproved:N?.takeoverApproved??!1}));if(!n)return;T=n,j=n.env,ie=await Ls(n.env);try{k||await h.measure(`schema`,()=>se({name:`db`,command:ks,args:[`db`,`ensure`],cwd:e,env:j,prefix:!1})),k||(await fe(),h.report(),await de())}finally{await n[Symbol.asyncDispose](),T===n&&(T=void 0)}}finally{t.end()}return}await fe(),h.report(),await de()}finally{P(),M&&=(await Qo({cwd:e,owner:M}),void 0);let t;try{await T?.[Symbol.asyncDispose]()}catch(e){t=e}finally{for(let{handler:e,signal:t}of I)G.off(t,e);A&&(G.exitCode??=A===`SIGINT`?130:143)}Is(t),await N?.release()}}function Ps(e){return q(F.resolve(e,`dashboard/dashboard.config.ts`))}async function Fs(e,t){for await(let n of e)t.write(`${n}\n`)||await Lt(t,`drain`)}function Is(e){if(e)throw e}async function Ls(e){let t=e.PGDATA;if(!t)return;let n=Number((await $.readFile(F.join(t,`postmaster.pid`),`utf8`).catch(()=>``)).split(/\r?\n/,1)[0]);return{dataDir:F.resolve(t),...Number.isSafeInteger(n)&&n>0?{pid:n}:void 0}}async function Rs({interactive:e,isStopping:t,takeoverApproved:n,...r}){try{return await k(r)}catch(i){if(!(i instanceof m)||!e)throw i;if(!n){let e=await B.confirm({initialValue:!1,message:`PostgreSQL is already running for this project (PID ${i.pid}). Stop it and start here?`});if(B.isCancel(e)||!e){B.cancel(`Keeping the existing PostgreSQL process.`);return}}return await A(i),t()?void 0:k(r)}}function zs(e){return(e.database?.dialect??`postgres`)===`postgres`}function Bs(){return[`exec`,`tauri`,`dev`,`--config`,JSON.stringify({build:{beforeDevCommand:``}})]}function Vs({device:e,serverUrl:t,verbose:n}){return[`run`,`-d`,e.id,`--dart-define=COREFRAME_DEV_SERVER_URL=${t}`,...n?[`--verbose`]:[]]}function Hs(e,t,n){let r=t??(e===`android`?`10.0.2.2`:`127.0.0.1`);return`http://${r.includes(`:`)&&!r.startsWith(`[`)?`[${r}]`:r}:${n}`}function Us(){return G.platform===`win32`?`windows`:G.platform}function Ws({host:e,port:t,strictPort:n=!1}){return[`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)],...n?[`--strictPort`]:[]]}function Gs({host:e,port:t}){return[`run`,...t===void 0?[]:[`--app-port`,String(t)],`react-router`,...Ws({host:e,port:void 0})]}function Ks(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}async function qs(e={}){let t=e.cwd??G.cwd(),n=await Me(`scripts/preview.ts`,t);if(typeof n.default!=`function`)throw Error(`scripts/preview.ts must export a default preview function.`);return Kt({...e,cwd:t},n.default)}const Js=F.resolve(`node_modules`,`.bin`);G.env.PATH=Js+F.delimiter+G.env.PATH;const Ys=G.platform===`win32`?`tsc.cmd`:`tsc`,Xs=[{name:`scripts`,path:`scripts/tsconfig.json`},{name:`shared`,path:`src/shared/tsconfig.json`},{name:`api`,path:`src/api/tsconfig.json`},{name:`worker`,path:`src/api/worker/tsconfig.json`},{name:`web`,path:`src/web/tsconfig.json`},{name:`dashboard`,path:`dashboard/tsconfig.json`}];async function Zs(){let e=[];for(let t of Xs)try{await ve(t.path),e.push(t)}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e}let t=e.map(e=>Ht({name:e.name,command:Ys,args:[`-p`,e.path]})),n=(await Promise.all(t.map(e=>e.wait()))).filter(e=>e.exitCode!==0);n.length>0&&(G.exitCode=n[0].exitCode)}const Qs=`worker-configuration.d.ts`;async function $s({check:e=!1,cwd:t=process.cwd()}={}){let n=await Pe({cwd:t}),r=await tt({coreframeConfig:n,cwd:t}),i=R(t,Qs),a=R(t,`.coreframe-worker-types-${Le()}.d.ts`);try{await z(`pnpm`,[`exec`,`wrangler`,`types`,a,`--config`,r.path,`--strict-vars=false`,`--include-runtime=false`],{cwd:t,stdio:`inherit`});let o=ec(await H(a,`utf8`)),s=Fe(r.config),c=Ne(n.worker?.environment).filter(e=>!s.has(e.name)),l=`${o.trimEnd()}\n\n${tc(c)}\n`;if(e){if(await H(i,`utf8`).catch(()=>``)!==l)throw Error(`${Qs} is stale. Run "coreframe worker typegen" and commit the result.`);return{changed:!1,path:i}}let u=await H(i,`utf8`).catch(()=>``);return u!==l&&await W(i,l),{changed:u!==l,path:i}}finally{await r.dispose(),await U(a,{force:!0})}}function ec(e){return e.split(/\r?\n/).filter(e=>!e.startsWith(`// Generated by Wrangler by running `)).join(`
12
- `)}function tc(e){return[`// Coreframe application string inventory declaration-merges with Wrangler's generated Env.`,`interface Env {`,...e.map(e=>` /** ${e.description.replaceAll(`*/`,`*\\/`)} */\n ${JSON.stringify(e.name)}?: string`),`}`].join(`
13
- `)}const nc=r(s(Ds),{displayName:`feature`,from:async e=>e}),rc=[`Cookies and sessions are origin-scoped.`,`Exact-host passkeys may require re-registration unless a stable eligible parent RP ID was configured in advance.`,`External OAuth callbacks such as Google may need updating.`,`Database data and private backend resources are unchanged.`],ic=n({name:`deploy`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Deploy to the staging or production environment.`}),runMigrations:i({long:`run-migrations`,description:`Run pending deploy-safe database migrations before deploying.`,defaultValue:()=>!1}),skipMigrations:i({long:`skip-migrations`,description:`Deploy without running pending deploy-safe database migrations.`,defaultValue:()=>!1}),skipPostDeployChecks:i({long:`skip-post-deploy-checks`,description:`Skip post-deploy checks after Cloudflare deployment.`,defaultValue:()=>!1}),tauriLocalPlatforms:a({long:`tauri-local-platform`,type:t(s(bt)),description:`Build one Tauri release platform locally. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowName:c({long:`tauri-workflow-name`,type:l(f),description:`GitHub Actions workflow file or name for remote Tauri release builds.`}),tauriWorkflowPlatforms:a({long:`tauri-workflow-platform`,type:t(s(bt)),description:`Build one Tauri release platform with GitHub Actions. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowRef:c({long:`tauri-workflow-ref`,type:l(f),description:`Git ref used when dispatching remote Tauri release builds.`}),yes:i({long:`yes`,short:`y`,description:`Approve the production deployment confirmation.`,defaultValue:()=>!1})},handler:({environment:e,runMigrations:t,skipMigrations:n,skipPostDeployChecks:r,tauriLocalPlatforms:i,tauriWorkflowName:a,tauriWorkflowPlatforms:o,tauriWorkflowRef:s,yes:c})=>ba([e,...t?[`--run-migrations`]:[],...n?[`--skip-migrations`]:[],...r?[`--skip-post-deploy-checks`]:[],...i.flatMap(e=>[`--tauri-local-platform`,e]),...a?[`--tauri-workflow-name`,a]:[],...o.flatMap(e=>[`--tauri-workflow-platform`,e]),...s?[`--tauri-workflow-ref`,s]:[],...c?[`--yes`]:[]])}),ac=p({name:`staging`,cmds:{reassign:n({name:`reassign`,args:{json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await dt();if(e){console.log(JSON.stringify({...t,notices:rc}));return}console.log(t.url),console.error(`Staging hostname reassigned. ${rc.join(` `)}`)}}),url:n({name:`url`,args:{json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await Qe();console.log(e?JSON.stringify({url:t}):t)}})}}),oc=p({name:`secrets`,cmds:{"rotate-access-token":n({name:`rotate-access-token`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment whose access JWTs should be invalidated.`}),yes:i({long:`yes`,short:`y`,description:`Confirm immediate signing-secret replacement and invalidation of outstanding access JWTs.`,defaultValue:()=>!1})},handler:async({environment:e,yes:t})=>{if(!t)throw Error(`Access-token signing-secret rotation requires --yes because it immediately invalidates outstanding access JWTs.`);await _t({environment:e}),console.log(`Rotated Coreframe access-token signing material for ${e}. Clients must remint outstanding access JWTs.`)}}),status:n({name:`status`,args:{environment:u({type:l(s(Xe)),displayName:`environment`,description:`Inspect staging, production, or both when omitted.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({environment:e,json:t})=>{let n=await $e({environment:e});console.log(t?JSON.stringify(n):dc(n))}}),set:n({name:`set`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment to update on its next deploy.`}),name:u({type:l(f),displayName:`name`,description:`Declared Worker secret name; omit to configure known secrets.`}),bulk:i({long:`bulk`,description:`Queue known secrets from pasted or piped dotenv-formatted contents.`,defaultValue:()=>!1})},handler:async({environment:e,name:t,bulk:n})=>{if(n&&t)throw Error(`Use either a secret name or --bulk, not both.`);if(t){await ot({environment:e,name:t,value:await fc(t)}),console.log(`Queued ${t} for ${e}. Run coreframe deploy ${e} to apply.`);return}let r=await ct(),i=n?await mc(r):await pc(r,e);await st({environment:e,values:i});let a=Object.keys(i).sort();console.log(a.length>0?`Queued ${a.join(`, `)} for ${e}. Run coreframe deploy ${e} to apply.`:`No ${e} Worker secret updates were queued.`)}}),discard:n({name:`discard`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment with a queued secret update.`}),name:u({type:f,displayName:`name`,description:`Declared Worker secret name.`})},handler:async({environment:e,name:t})=>{let n=await Ze({environment:e,name:t});console.log(n?`Discarded the queued ${t} update for ${e}.`:`No ${t} update is queued for ${e}.`)}})}}),sc=n({name:`typecheck`,args:{},handler:Zs}),cc=p({name:`worker`,cmds:{typegen:n({name:`typegen`,args:{check:i({long:`check`,description:`Fail when the committed primary Worker declarations are stale.`,defaultValue:()=>!1})},handler:async({check:e})=>{let t=await $s({check:e});console.log(e?`${gc(t.path)} is current.`:`${gc(t.path)} ${t.changed?`generated`:`is unchanged`}.`)}})}}),lc=n({name:`dev`,args:{debug:c({long:`debug`,type:l(nc),description:`Launch a development feature in isolated debug mode.`}),https:i({long:`https`,description:`Serve the web app over locally trusted HTTPS.`,defaultValue:()=>!1}),fresh:i({long:`fresh`,description:`Start a new directory-scoped development session instead of attaching to one.`,defaultValue:()=>!1}),host:c({long:`host`,type:l(f),implicitValue:`0.0.0.0`,description:`Host address for the web development server. Pass without an address to use 0.0.0.0.`}),managed:i({long:`managed`,description:`Run managed checkout synchronization even without an interactive terminal.`,defaultValue:()=>!1}),noManaged:i({long:`no-managed`,description:`Run without managed checkout synchronization for this invocation.`,defaultValue:()=>!1}),reuseVite:i({long:`reuse-vite`,description:`Use an existing Vite development server instead of starting another one for Flutter.`,defaultValue:()=>!1}),stop:i({long:`stop`,description:`Stop the directory development supervisor and its managed services.`,defaultValue:()=>!1}),platform:u({type:l(s(Es)),displayName:`platform`,description:`Development target platform. Defaults to web.`}),device:u({type:l(f),displayName:`device`,description:`Device name or ID for iOS or Android development.`}),port:c({long:`port`,type:l(o),description:`Port for the web development server.`}),verbose:i({long:`verbose`,description:`Show the full native development output.`,defaultValue:()=>!1})},handler:({debug:e,device:t,fresh:n,host:r,https:i,managed:a,noManaged:o,platform:s,port:c,reuseVite:l,stop:u,verbose:d})=>u?Pt({cwd:G.cwd()}):Ns({debug:e,device:t,fresh:n,host:r,https:i,managed:a,noManaged:o,platform:s??`web`,reuseVite:l,verbose:d,webPort:c})}),uc=n({name:`preview`,args:{host:c({long:`host`,type:l(f),description:`Host address for the preview server.`}),port:c({long:`port`,type:l(o),description:`Port for the preview server.`})},handler:({host:e,port:t})=>qs({host:e,port:t})});function dc(e){if(e.entries.length===0)return`No Worker environment values are declared in coreframe.config.ts.`;let t=e.entries.map(e=>[e.name,e.kind,e.local===`override`?`override`:`built-in default`,e.deployed.staging.replaceAll(`_`,` `),e.deployed.production.replaceAll(`_`,` `)]),n=[`Name`,`Kind`,`Local`,`Staging`,`Production`],r=n.map((e,n)=>Math.max(e.length,...t.map(e=>e[n].length))),i=e=>e.map((e,t)=>e.padEnd(r[t])).join(` `).trimEnd();return[i(n),i(r.map(e=>`-`.repeat(e))),...t].join(`
14
- `)}async function fc(e){if(!G.stdin.isTTY){let e=``;for await(let t of G.stdin)e+=t.toString();return e.replace(/\r?\n$/,``)}let t=await B.password({message:`Enter the new value for ${e}`});if(B.isCancel(t))throw B.cancel(`Secret update cancelled.`),Error(`Secret update cancelled.`);return t}async function pc(e,t){if(!G.stdin.isTTY)throw Error(`Interactive secret setup requires a terminal. Provide a secret name or use --bulk with piped dotenv contents.`);if(e.length===0)throw Error(`No Worker secrets are declared in coreframe.config.ts.`);let n={};for(let r of e){let e=r.requiredIn.includes(t),i=await B.password({message:`${r.name}: ${r.description}${e?` (required)`:` (optional; leave blank to skip)`}`,validate:n=>e&&!n?.trim()?`${r.name} is required in ${t}.`:void 0});if(B.isCancel(i))throw B.cancel(`Secret setup cancelled.`),Error(`Secret setup cancelled.`);i.trim()&&(n[r.name]=i)}return n}async function mc(e){if(e.length===0)throw Error(`No Worker secrets are declared in coreframe.config.ts.`);let t=G.stdin.isTTY?await B.multiline({message:`Paste dotenv-formatted Worker secrets. Press Enter twice to submit.`,validate:e=>e?.trim()?void 0:`Paste at least one dotenv entry.`}):await hc();if(B.isCancel(t))throw B.cancel(`Secret setup cancelled.`),Error(`Secret setup cancelled.`);let{ignoredNames:n,values:r}=nt(t,e);return n.length>0&&B.log.info(`Ignored non-secret or undeclared names: ${n.join(`, `)}.`),r}async function hc(){let e=``;for await(let t of G.stdin)e+=t.toString();return e}function gc(e){return e.split(/[\\/]/).at(-1)??e}function _c(e,{formatMessage:t,temporaryDirectory:n=Ae(),write:r=e=>console.error(e)}={}){let i=Cc(e),a=Ec(yc(e,t),i);try{let t=L(Ve(L(n,`coreframe-error-`)),`error.log`);return Ge(t,`${Ec(bc(e),i)}\n`,{mode:384}),r(`Error: ${a}\nFull diagnostic: ${t}`),t}catch{r(`Error: ${a}\nThe full diagnostic could not be written to the temporary directory.`);return}}function vc(t,n={}){let r=typeof t==`function`?t:()=>e.run(e.binary(t),process.argv),i=!1,a=e=>{i||(i=!0,_c(e,n),process.exit(1))};process.once(`uncaughtException`,a),process.once(`unhandledRejection`,a),Promise.resolve().then(r).catch(a)}function yc(e,t){try{return t?.(e)||(e instanceof Error?e.message:String(e)).split(/\r?\n/,1)[0]||`Unknown error`}catch{return`Unknown error`}}function bc(e){try{let t=xc(e);if(!(e instanceof Error)||!Sc(t))return Ft(t,{customInspect:!1,depth:10});let n=typeof t.stack==`string`?t.stack:`${e.name}: ${e.message}`;return delete t.name,delete t.message,delete t.stack,`${n}${Reflect.ownKeys(t).length?`\n${Ft(t,{customInspect:!1,depth:10})}`:``}`}catch{return`The thrown value could not be inspected.`}}function xc(e,t=new WeakMap){if((typeof e!=`object`||!e)&&typeof e!=`function`)return e;let n=e,r=t.get(n);if(r)return r;if(typeof e==`function`)return`[Function${e.name?`: ${e.name}`:``}]`;let i=Array.isArray(e)?[]:{};t.set(n,i),e instanceof Error&&(i.name=e.name,i.message=e.message,i.stack=e.stack??`${e.name}: ${e.message}`);for(let r of Reflect.ownKeys(n)){if(typeof r!=`string`||r.toLowerCase()===`env`||Array.isArray(e)&&r===`length`||e instanceof Error&&(r===`name`||r===`message`||r===`stack`))continue;let a=Object.getOwnPropertyDescriptor(n,r);!a||!(`value`in a)||Object.defineProperty(i,r,{configurable:!0,enumerable:!0,value:xc(a.value,t),writable:!0})}return i}function Sc(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Cc(e,t=new WeakSet){let n=new Set;function r(e){if((typeof e!=`object`||!e)&&typeof e!=`function`)return;let i=e;if(!t.has(i)){t.add(i);for(let e of Reflect.ownKeys(i)){if(typeof e!=`string`)continue;let t=Object.getOwnPropertyDescriptor(i,e);!t||!(`value`in t)||(e.toLowerCase()===`env`?wc(t.value,n):r(t.value))}}}try{r(e)}catch{}return n}function wc(e,t){if(!(typeof e!=`object`||!e))for(let n of Reflect.ownKeys(e)){let r=Object.getOwnPropertyDescriptor(e,n);typeof n==`string`&&Tc(n)&&r&&`value`in r&&typeof r.value==`string`&&r.value&&t.add(r.value)}}function Tc(e){return/(?:^|_)(?:AUTH|CERT|COOKIE|CREDENTIALS?|DATABASE_URL|DSN|KEY|PASS(?:WORD)?|PRIVATE|SECRET|SESSION|TOKEN)(?:_|$)/i.test(e)}function Ec(e,t){return[...t].sort((e,t)=>t.length-e.length).reduce((e,t)=>e.replaceAll(t,`[redacted environment value]`),e)}const Dc=p({name:`coreframe`,cmds:{build:rn,dashboard:yr,assets:lr,flutter:ur,i18n:dr,deploy:ic,staging:ac,secrets:oc,typecheck:sc,worker:cc,dev:lc,preview:uc,upgrade:ga,recipes:_a,db:va}});import.meta.main&&vc(Dc,{formatMessage:process.argv[2]===`db`?x:void 0});export{Dc as coreframeCli};
10
+ `:``;Ge(e,`${JSON.stringify(n,null,r)}${i}`)}function pa(e,t){if(t.length!==0){console.log(`${e}:`);for(let e of t)console.log(` ${e}`);console.log(``)}}function ma(e){let t=L(ra([`rev-parse`,`--show-toplevel`]).trim(),`package.json`),n=J(t,`utf8`),r=ia(n,t),i=Pr(e.target),a=ua(i),o=new Set(a.map(({name:e})=>e)),s=[],c=[],l=[],u=0;for(let e of a){let t=da(r,e.name);if(!t){c.push(`missing: ${e.name} ${e.spec} (${e.group})`);continue}if(sa(t.spec)){l.push(`linked: ${e.name} ${t.spec}`);continue}if(t.spec===e.spec){u+=1;continue}s.push({...e,currentGroup:t.group,currentSpec:t.spec})}let d=na.flatMap(e=>Object.entries(r[e]??{}).filter(([e])=>oa(e)&&!o.has(e)).map(([t,n])=>`review: ${t} ${n} (${e})`));if(e.apply&&s.length>0){for(let e of s)r[e.currentGroup][e.name]=e.spec;fa(t,n,r)}console.log(`Coreframe package sync: ${i}`),console.log(``),pa(e.apply?`Updated Coreframe packages`:`Would update Coreframe packages`,s.map(({currentSpec:e,name:t,spec:n})=>`update: ${t} ${e} -> ${n}`)),pa(`Missing target Coreframe packages`,c),pa(`Locally linked Coreframe packages`,l),pa(`Downstream-only Coreframe packages`,d),u>0&&console.log(`${u} Coreframe package(s) already match the target versions.`),s.length===0?console.log(`No Coreframe package version updates found.`):e.apply||(console.log(``),console.log(`Run with --apply to write the ${s.length} package update(s).`))}const ha={...f,displayName:`recipe`,description:`Coreframe recipe name, such as yam-db.`,async from(e){return Sr(e)}},ga=p({name:`upgrade`,cmds:{"ensure-template-remote":n({name:`ensure-template-remote`,args:{remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Remote name to ensure.`}),noFetch:i({long:`no-fetch`,description:`Do not fetch the remote after ensuring it exists.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t})=>Mr({fetch:!e,remote:t})}),"check-skill-current":n({name:`check-skill-current`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),apply:i({long:`apply`,description:`Replace the local upgrade skill with the target version when it differs.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>{process.exitCode=Ni({apply:e,target:t})}}),"fast-forward-template-files":n({name:`fast-forward-template-files`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),base:c({long:`base`,type:l(f),description:`Previous Coreframe template git ref. Defaults to package.json engines.coreframe.`}),apply:i({long:`apply`,description:`Write clean fast-forwards to the worktree.`,defaultValue:()=>!1})},handler:({apply:e,base:t,target:n})=>ta({apply:e,base:t,target:n})}),"sync-coreframe-packages":n({name:`sync-coreframe-packages`,args:{target:c({long:`target`,type:f,description:`Target Coreframe template git ref.`}),apply:i({long:`apply`,description:`Update existing published Coreframe dependency specifications.`,defaultValue:()=>!1})},handler:({apply:e,target:t})=>ma({apply:e,target:t})})}}),_a=p({name:`recipes`,cmds:{apply:n({name:`apply`,args:{recipe:u({type:ha,displayName:`recipe`,description:`Recipe to prepare and apply.`}),target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,recipe:t,remote:n,target:r})=>si(oi({fetch:!e,name:t,remote:n,target:r}))}),list:n({name:`list`,args:{target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,remote:t,target:n})=>Ei(Ti({fetch:!e,remote:t,target:n}))}),verify:n({name:`verify`,args:{recipe:u({type:ha,displayName:`recipe`,description:`Recipe adoption to verify.`}),target:c({long:`target`,type:l(f),description:`Coreframe Git ref. Defaults to package.json engines.coreframe.`}),remote:c({long:`remote`,type:f,defaultValue:()=>`template`,description:`Coreframe Git remote name.`}),noFetch:i({long:`no-fetch`,description:`Use already-fetched recipe refs without fetching the remote.`,defaultValue:()=>!1})},handler:({noFetch:e,recipe:t,remote:n,target:r})=>ri(ni({fetch:!e,name:t,remote:n,target:r}))})}}),va=p({name:`db`,cmds:{ensure:n({name:`ensure`,args:{},handler:y}),generate:n({name:`generate`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit generate.`})},handler:({args:e})=>te(`generate`,e)}),migrate:n({name:`migrate`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit migrate.`})},handler:({args:e})=>te(`migrate`,e)}),"migrate-held":n({name:`migrate-held`,args:{confirm:c({long:`confirm`,type:l(s([`run-held-migrations`])),description:`Required confirmation value for held migrations.`})},handler:({confirm:e})=>w({argv:e?[`--confirm=${e}`]:[]})}),"migrate-local":n({name:`migrate-local`,args:{},handler:T}),"migrations-check":n({name:`migrations-check`,args:{},handler:h}),reset:n({name:`reset`,args:{},handler:ee}),seed:n({name:`seed`,args:{},handler:()=>O()}),"schema-check":n({name:`schema-check`,args:{seed:i({long:`seed`,description:`Run the configured project seed against the throwaway database.`,defaultValue:()=>!1})},handler:({seed:e})=>g({seed:e})}),setup:n({name:`setup`,args:{},handler:()=>ne()}),studio:n({name:`studio`,args:{args:d({displayName:`drizzle-kit args`,description:`Additional arguments passed to drizzle-kit studio.`})},handler:({args:e})=>te(`studio`,e)})}}),ya=`package.json`;async function ba(e=process.argv.slice(2),t=process.env){let n=xa(e);ka(n);let{packageJson:r,source:i}=await lt(ya),a=await Fe(),o=pt(a.deploy??{},n.environment,t);Pa(t,[`POSTHOG_API_KEY`,`POSTHOG_PROJECT_ID`]);let s=await Aa(o,n.environment,()=>Qe({env:t})),c=ht({args:n,config:n.environment===`production`?o.tauriRelease:{},env:t});Na(n.environment,c.enabled),await St(c);let l=await ut({environment:n.environment}),u=l.values.DASHBOARD_PASSWORD??await Fa(t,n.environment);Ct(await $e({environment:n.environment}),n.environment,{availableNames:[...Object.keys(l.values),...u?[`DASHBOARD_PASSWORD`]:[]]});let d=await it({environment:n.environment}),f=await Oa();await Gn({env:t,revision:f});let p=f.slice(0,12),m=mt(n.environment,r.version,p),h=ft(r.name,m),g={...Ra(t,n.environment,h,r.name,m),COREFRAME_I18N_RELEASE_REVISION:f},_=n.environment===`production`,y=!1,b={files:[]};z.intro(`Deploy ${h} to ${n.environment}`);let x=Object.keys(l.values).sort();x.length>0&&z.note(x.join(`
11
+ `),`Pending Worker secret updates`),d.provisioned&&z.log.info(`Provisioning Coreframe-managed access-token signing material.`),await Ma(n);let S=await Ta(await v({config:a.database,env:t})),w=await D(S);if(w.length>0)throw Error(`Pending deploy migrations contain unsafe SQL. Move unsafe statements to held migrations.\n${C(w)}`);let T=await Da(n,S);try{_&&(await Tt(ya,r,m),b=await Et(c,m)),z.log.step(`Running pre-deploy build`),await R(`pnpm`,[`build`],{env:za(g),stdio:`inherit`});let e=c.enabled?await at({env:za(g),plan:c,releaseName:h,version:m}):void 0;z.log.step(`Running release build and uploading PostHog source maps`),y=!0,await R(`pnpm`,[`build`],{env:g,stdio:`inherit`}),T&&(z.log.step(`Running deploy-safe database migrations`),await R(`pnpm`,[`db`,`migrate`],{env:g,stdio:`inherit`})),z.log.step(`Deploying Worker and static assets to Cloudflare`);let t={...u?{DASHBOARD_PASSWORD:u}:{},...d.value?{[Je]:d.value}:{},...l.values},i=Object.keys(t).length>0?await Ia(t):void 0,f=await et({coreframeConfig:a,environment:n.environment,contributions:{generatedValues:{DEPLOY_ENV:n.environment,POSTHOG_RELEASE:h}}});try{await R(`pnpm`,[`exec`,`wrangler`,`deploy`,`--config`,f.path,`--env`,n.environment,`--strict`,`--keep-vars`,`--tag`,h,`--message`,`Deploy ${h}`,...i?[`--secrets-file`,i.path]:[]],{env:g,stdio:`inherit`}),await Ye(l),await wt({environment:n.environment})}finally{await f.dispose(),await i?.dispose()}let p={environment:n.environment,releaseName:h,url:s,version:m};o.afterWorkerDeploy&&(z.log.step(`Running required after-Worker deploy hook`),await vt(o,p)),n.skipPostDeployChecks||(z.log.step(`Running post-deploy checks`),await yt(o,p)),e&&(z.log.step(`Uploading Tauri release artifacts to Backblaze B2`),await xt(c,e)),z.outro(`Deployed ${h} to ${n.environment}`)}catch(e){throw!y&&_&&(await U(ya,i),await gt(b)),e}}function xa(e){return{environment:Sa(e[0]),runMigrations:e.includes(`--run-migrations`),skipMigrations:e.includes(`--skip-migrations`),skipPostDeployChecks:e.includes(`--skip-post-deploy-checks`),tauriLocalPlatforms:Ca(e,`--tauri-local-platform`).map(e=>rt(e)),tauriWorkflowName:wa(e,`--tauri-workflow-name`),tauriWorkflowPlatforms:Ca(e,`--tauri-workflow-platform`).map(e=>rt(e)),tauriWorkflowRef:wa(e,`--tauri-workflow-ref`),yes:e.includes(`--yes`)}}function Sa(e){if(e&&Xe.includes(e))return e;throw Error(`Deploy environment must be one of: ${Xe.join(`, `)}.`)}function Ca(e,t){let n=[];for(let r=0;r<e.length;r+=1){let i=e[r];if(i===t){let i=e[r+1];if(!i||i.startsWith(`--`))throw Error(`${t} requires a value.`);n.push(...i.split(`,`).filter(Boolean)),r+=1;continue}i.startsWith(`${t}=`)&&n.push(...i.slice(t.length+1).split(`,`).filter(Boolean))}return n}function wa(e,t){let n=Ca(e,t);if(n.length>1)throw Error(`${t} can only be provided once.`);return n[0]}async function Ta(e){try{return await Ea(e)}finally{await e.close?.()}}async function Ea(e){return b(await _(),await E(e))}async function Da(e,t){if(t.length===0)return z.log.info(`No pending deploy migrations.`),!1;if(z.note(S(t),`Pending deploy migrations`),e.runMigrations)return!0;if(e.skipMigrations)return!1;if(!process.stdout.isTTY)throw Error(`Pending migrations require --run-migrations or --skip-migrations in noninteractive deploys.`);let n=await z.confirm({initialValue:!0,message:`Run these deploy-safe database migrations before Cloudflare deploy?`});if(z.isCancel(n))throw z.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`);return n}async function Oa(){let{stdout:e}=await R(`git`,[`status`,`--porcelain`],{stdin:`ignore`});if(e.trim().length>0)throw Error(`Deploy requires a clean git tree.`);let{stdout:t}=await R(`git`,[`rev-parse`,`HEAD`],{stdin:`ignore`});return t.trim()}function ka(e){if(e.runMigrations&&e.skipMigrations)throw Error(`Use only one of --run-migrations or --skip-migrations.`)}async function Aa(e,t,n=Qe){return e.url?ja(e.url,t):t===`staging`&&e.stagingHostname?ja(await n(),t):ja(void 0,t)}function ja(e,t){if(!e)throw Error(`Missing ${t} deploy URL. Set DEPLOY_URL or deploy.environments.${t}.url in coreframe.config.ts.`);let n;try{n=new URL(e)}catch{throw Error(`Invalid ${t} deploy URL "${e}". Expected an HTTP(S) URL.`)}if(n.protocol!==`http:`&&n.protocol!==`https:`)throw Error(`Invalid ${t} deploy URL "${e}". Expected an HTTP(S) URL.`);return n.toString()}async function Ma(e){if(e.environment!==`production`||e.yes)return;if(!process.stdout.isTTY)throw Error(`Production deploys require --yes in noninteractive environments.`);let t=await z.confirm({initialValue:!1,message:`Deploy to production?`});if(z.isCancel(t)||!t)throw z.cancel(`Deploy cancelled.`),Error(`Deploy cancelled.`)}function Na(e,t){if(e===`staging`&&t)throw Error(`Tauri releases can only be published from production deploys.`)}function Pa(e,t){let n=t.filter(t=>!e[t]);if(n.length>0)throw Error(`Missing required deploy environment variables: ${n.join(`, `)}`);return Object.fromEntries(t.map(t=>[t,e[t]]))}async function Fa(e,t){let n=e.DASHBOARD_PASSWORD?.trim();if(n)return n;let r;try{r=It(await V(`.env`,`utf8`))}catch(e){throw La(e)&&e.code===`ENOENT`?Error(`Missing ${t} dashboard password. Set DASHBOARD_PASSWORD in ".env".`):e}let i=r.DASHBOARD_PASSWORD?.trim();if(!i)throw Error(`Missing ${t} dashboard password. Set DASHBOARD_PASSWORD in ".env".`);return i}async function Ia(e){let t=await we(I(je(),`coreframe-deploy-secrets-`)),n=I(t,`secrets.json`);return await U(n,JSON.stringify(e),{mode:384}),{path:n,dispose:()=>H(t,{force:!0,recursive:!0})}}function La(e){return e instanceof Error&&`code`in e}function Ra(e,t,n,r,i){return{...e,CLOUDFLARE_ENV:t,DEPLOY_ENV:t,POSTHOG_RELEASE:n,POSTHOG_RELEASE_NAME:e.POSTHOG_RELEASE_NAME??r,POSTHOG_RELEASE_VERSION:e.POSTHOG_RELEASE_VERSION??i}}function za(e){let{POSTHOG_API_KEY:t,POSTHOG_PROJECT_ID:n,...r}=e;return r}const $={access:ye,chmod:be,mkdir:B,mkdtemp:we,readFile:V,readFileSync:J,rm:H,writeFile:U},Ba={getAvailablePort:Ha},Va={homedir:ke,kill:G.kill,networkInterfaces:Ae,tmpdir:je};async function Ha(){let e=Ut();try{await new Promise((t,n)=>{e.once(`error`,n),e.listen(0,`127.0.0.1`,t)});let t=e.address();if(!t||typeof t==`string`)throw Error(`Could not allocate an available TCP port.`);return t.port}finally{e.listening&&await new Promise((t,n)=>{e.close(e=>e?n(e):t())})}}async function Ua(){let e=await Ga();return typeof e.mobileDevHost==`string`?{mobileDevHost:e.mobileDevHost}:{}}async function Wa(e){let t=await Ga(),n=Ka();await $.mkdir(P.dirname(n),{recursive:!0}),await $.writeFile(n,`${JSON.stringify({...t,...e},void 0,2)}\n`)}async function Ga(){try{let e=await $.readFile(Ka(),`utf8`),t=JSON.parse(e);return qa(t)?t:{}}catch{return{}}}function Ka(){return P.join(Va.homedir(),`.coreframe`,`preferences.json`)}function qa(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}async function Ja({env:e=G.env,interactive:t=G.stdin.isTTY===!0,platform:n,target:r}){let i=await $a(n,e).catch(()=>[]),a=r?_o(i,r):void 0;if(a)return a;if(!r&&i.length>0)return Qa(i,n,t);let o=r?_o(await to(e).catch(()=>[]),r):void 0;if(o&&o.platform===n)return no(o,n,e,t);let s=await eo(n,e),c=r?_o(s,r):void 0;if(c)return c;if(!r&&s.length>0)return Qa(s,n,t);let l=n===`ios`?`iOS`:`Android`;throw Error(r?`Could not find a ${l} device matching "${r}".`:`No connected ${l} devices or available ${l} ${n===`ios`?`simulators`:`emulators`} were detected.`)}async function Ya(e){let{device:t,host:n,interactive:r=G.stdin.isTTY===!0}=e;if(!t.physical&&n===void 0)return;if(typeof n==`string`&&n!==`0.0.0.0`&&n!==`::`)return n;let i=yo();if(i.length===0)throw Error(`No external IP address was detected. Pass one explicitly with --host.`);let a=await Xa();if(a&&i.includes(a))return a;if(i.length===1)return await Za(i[0]),i[0];if(!r)throw Error(`Multiple external IP addresses were detected (${i.join(`, `)}). Pass one explicitly with --host.`);let o=await z.select({message:`Which IP address should the mobile device use to reach the development server?`,options:i.map(e=>({label:e,value:e}))});if(z.isCancel(o))throw Error(`Mobile development IP selection was cancelled.`);return await Za(o),o}async function Xa(){return(await Ua()).mobileDevHost}async function Za(e){try{await Wa({mobileDevHost:e})}catch(e){z.log.warn(`Could not remember the mobile development IP address: ${e instanceof Error?e.message:String(e)}`)}}async function Qa(e,t,n){if(e.length===1)return e[0];if(!n)throw Error(`Multiple ${t===`ios`?`iOS`:`Android`} devices were detected. Pass a device name explicitly.`);let r=await z.select({message:`Which ${t===`ios`?`iOS`:`Android`} device should Coreframe use?`,options:e.map(e=>({label:e.label,value:e,hint:e.id}))});if(z.isCancel(r))throw Error(`Mobile development device selection was cancelled.`);return r}async function $a(e,t){return e===`android`?io(t):oo(t)}async function eo(e,t){return e===`android`?ao(t):so(t)}async function to(e){let{stdout:t}=await R(`flutter`,[`emulators`],{env:e});return t.split(/\r?\n/).flatMap(e=>{let[t,n,,r]=e.split(/\s*•\s*/).map(e=>e.trim());return t&&n&&(r===`android`||r===`ios`)?[{id:t,label:n,name:n,physical:!1,platform:r}]:[]})}async function no(e,t,n,r){let i=await ro(t,n).catch(()=>[]),{stdout:a}=await R(`flutter`,[`emulators`,`--launch`,e.id],{env:n});if(/No emulator found|More than one emulator matches/i.test(a))throw Error(a.trim());let o=Date.now()+3e4;do{let a=await ro(t,n).catch(()=>[]),o=_o(a,e.id);if(o)return o;let s=a.filter(e=>!i.some(t=>t.id===e.id));if(s.length>0)return Qa(s,t,r);if(a.length===1)return a[0];await Wt(250)}while(Date.now()<o);let s=t===`ios`?`iOS simulator`:`Android emulator`;throw Error(`Flutter launched "${e.id}", but no ${s} became available.`)}async function ro(e,t){return e===`ios`?so(t,`booted`):(await io(t)).filter(e=>!e.physical)}async function io(e){let t=await lo(e,`platform-tools`,G.platform===`win32`?`adb.exe`:`adb`),{stdout:n}=await R(t,[`devices`],{env:e}),r=n.split(/\r?\n/).map(e=>e.match(/^(\S+)\s+device(?:\s|$)/)?.[1]).filter(e=>e!==void 0);return(await Promise.all(r.map(async n=>{let r=await fo(t,e,n,`ro.product.model`),i=n.startsWith(`emulator-`),a=i?await mo(t,e,n,r):await ho(t,e,n,r);return{id:n,label:a===r?a:`${a} (${r})`,name:a,physical:!i}}))).sort(bo)}async function ao(e){let{stdout:t}=await R(await lo(e,`emulator`,G.platform===`win32`?`emulator.exe`:`emulator`),[`-list-avds`],{env:e});return t.split(/\r?\n/).map(e=>e.trim()).filter(e=>e.length>0&&!/^(INFO|WARNING|ERROR)\s+\|/.test(e)).map(e=>({id:e,label:e,name:e,physical:!1}))}async function oo(e){let t=await $.mkdtemp(P.join(Va.tmpdir(),`coreframe-ios-devices-`)),n=P.join(t,`devices.json`);try{return await $.writeFile(n,``),await R(`xcrun`,[`devicectl`,`list`,`devices`,`--json-output`,n],{env:e}),(JSON.parse(await $.readFile(n,`utf8`)).result?.devices??[]).filter(co).map(e=>({id:e.hardwareProperties.udid,label:`${e.deviceProperties.name} (${e.hardwareProperties.productType})`,name:e.deviceProperties.name,physical:!0})).sort(bo)}finally{await $.rm(t,{force:!0,recursive:!0})}}async function so(e,t=`available`){let{stdout:n}=await R(`xcrun`,[`simctl`,`list`,`--json`,`devices`,t],{env:e}),r=JSON.parse(n);return Object.entries(r.devices??{}).filter(([e])=>e.includes(`iOS-`)).flatMap(([,e])=>e).flatMap(e=>e.name&&e.udid?[{id:e.udid,label:e.name,name:e.name,physical:!1}]:[]).sort(bo)}function co(e){return e.connectionProperties?.tunnelState!==`unavailable`&&typeof e.hardwareProperties?.platform==`string`&&(e.hardwareProperties.platform.includes(`iOS`)||e.hardwareProperties.platform.includes(`xrOS`))&&typeof e.deviceProperties?.name==`string`&&typeof e.hardwareProperties.productType==`string`&&typeof e.hardwareProperties.udid==`string`}async function lo(e,t,n){let r=e.ANDROID_HOME??e.ANDROID_SDK_ROOT,i=r?[r]:uo(e);for(let e of i){let r=P.join(e,t,n);try{return await $.access(r),r}catch{}}return n}function uo(e){return G.platform===`darwin`?[P.join(Va.homedir(),`Library`,`Android`,`sdk`)]:G.platform===`win32`&&e.LOCALAPPDATA?[P.join(e.LOCALAPPDATA,`Android`,`Sdk`)]:[P.join(Va.homedir(),`Android`,`Sdk`)]}async function fo(e,t,n,r){return(await po(e,t,[`-s`,n,`shell`,`getprop`,r])).trim()}async function po(e,t,n){return(await R(e,n,{env:t,timeout:3e3})).stdout}async function mo(e,t,n,r){return po(e,t,[`-s`,n,`emu`,`avd`,`name`]).then(e=>e.split(/\r?\n/)[0]?.trim()||r).catch(()=>r)}async function ho(e,t,n,r){return po(e,t,[`-s`,n,`shell`,`dumpsys`,`bluetooth_manager`]).then(e=>go(e)||r).catch(()=>r)}function go(e){return e.match(/\bname: (.+)/)?.[1]?.trim()}function _o(e,t){let n=e.map(e=>({device:e,score:Math.max(vo(t,e.name),vo(t,e.id))})).sort((e,t)=>t.score-e.score)[0];return n&&n.score>0?n.device:void 0}function vo(e,t){let n=e.toLowerCase(),r=t.toLowerCase();if(r===n)return 1e4;let i=r.indexOf(n);if(i>=0)return 5e3-i;let a=0,o=0;for(let e of n){let t=r.indexOf(e,o);if(t<0)return 0;a+=t===o?2:1,o=t+1}return a}function yo(){return[...new Set(Object.values(Va.networkInterfaces()).flatMap(e=>e??[]).filter(e=>!e.internal&&e.family===`IPv4`).map(e=>e.address))].sort()}function bo(e,t){return e.label.localeCompare(t.label)}function xo({host:e=`127.0.0.1`,port:t,start:n}){let r,i=!1,a=!1,o=!1,s,c,l,u,d,f=new Set,p=new Promise((e,t)=>{u=e,d=t}),m=e=>{a||o||(o=!0,d(e))},h=()=>(s||=Promise.resolve().then(n).catch(e=>{throw m(e),e}),s),g=e=>{f.add(e),e.once(`close`,()=>f.delete(e)),e.pause(),_(e).catch(t=>{m(t),e.destroy()})},_=async e=>{let t=await h();if(a||e.destroyed)return;let n=await So(t,()=>a);if(a||e.destroyed){n.destroy();return}f.add(n),n.once(`close`,()=>f.delete(n)),n.on(`error`,()=>e.destroy()),n.once(`close`,()=>e.destroy()),e.on(`error`,()=>n.destroy()),e.once(`close`,()=>n.destroy()),e.pipe(n),n.pipe(e)};return{close:async()=>l||(l=(async()=>{a=!0,o||(o=!0,u());for(let e of f)e.destroy();f.clear(),c&&!i&&await Promise.allSettled([c]),!(!r||!i)&&(await new Promise(e=>{r.close(()=>e())}),i=!1)})(),l),fail:m,listen:async()=>c||(r=Ut(g),c=new Promise((n,a)=>{let o=e=>{if(i){m(e);return}a(e)};r.once(`error`,o),r.once(`listening`,()=>{i=!0,r.off(`error`,o),r.on(`error`,m),n()}),r.listen(t,e)}),c),wait:()=>p}}async function So(e,t){let n=Date.now()+1e4,r;for(;!t();)try{return await Co(e)}catch(e){if(r=e,Date.now()>=n)break;await new Promise(e=>setTimeout(e,50))}throw r instanceof Error?r:Error(`Could not connect to the dashboard.`)}function Co({host:e=`127.0.0.1`,port:t}){return new Promise((n,r)=>{let i=Ht({host:e,port:t}),a=e=>{i.off(`connect`,o),i.destroy(),r(e)},o=()=>{i.off(`error`,a),n(i)};i.once(`error`,a),i.once(`connect`,o)})}const wo={command:Bo,isRunning:jo,stop(e){try{G.kill(e,`SIGTERM`)}catch(e){if(!Po(e))throw e}},waitForExit:Mo};async function To({confirmStop:e=Oo,cwd:t=G.cwd(),interactive:n=G.stdin.isTTY===!0,pid:r=G.pid,platform:i=`web`,processes:a=wo}={}){let o=await Uo(t,i),s=o.file,c={pid:r,platform:i,repository:o.repository,token:W()},l=`${JSON.stringify(c)}\n`,u=`${s}.${c.token}.tmp`,d=await Io({confirmStop:e,file:P.resolve(t,`.coreframe/dev.lock`),interactive:n,owner:c,processes:a});if(d===void 0)return;let f=d;await B(P.dirname(s),{recursive:!0}),await U(u,l,{flag:`wx`,mode:384});try{for(;;){try{return await Ce(u,s),{owner:c,async release(){await Ao(s,l)},takeoverApproved:f}}catch(e){if(!No(e))throw e}let t=await Do({confirmStop:e,file:s,interactive:n,owner:c,processes:a});if(t===void 0)return;f||=t}}finally{await Oe(u).catch(()=>void 0)}}async function Eo({cwd:e=G.cwd(),platform:t=`web`}={}){let{file:n}=await Uo(e,t);return(await ko(n))?.owner}async function Do({confirmStop:e,file:t,interactive:n,owner:r,processes:i}){let a=await ko(t);if(!a||!qo(a.owner,r)||!i.isRunning(a.owner.pid))return await Ao(t,a?.source),!1;if(!n)throw Error(`Coreframe dev is already running for this project (PID ${a.owner.pid}). Stop it before starting another.`);if(await e(a.owner.pid))return i.stop(a.owner.pid),await i.waitForExit(a.owner.pid),await Ao(t,a.source),!0}async function Oo(e){let t=await z.confirm({initialValue:!1,message:`Coreframe dev is already running for this project (PID ${e}). Stop it and start here?`});return z.isCancel(t)||!t?(z.cancel(`Keeping the existing Coreframe dev process.`),!1):!0}async function ko(e){try{let t=await V(e,`utf8`),n=JSON.parse(t);return!Number.isSafeInteger(n.pid)||Number(n.pid)<=0||typeof n.platform!=`string`||n.platform.length===0||typeof n.repository!=`string`||n.repository.length===0||typeof n.token!=`string`||n.token.length===0?void 0:{owner:n,source:t}}catch{return}}async function Ao(e,t){let n=await V(e,`utf8`).catch(()=>void 0);(t===void 0||n===t)&&await Oe(e).catch(()=>void 0)}function jo(e){try{return G.kill(e,0),!0}catch(e){return!Po(e)}}async function Mo(e){let t=Date.now()+1e4;for(;jo(e);){if(Date.now()>=t)throw Error(`Coreframe dev process ${e} did not stop within 10 seconds.`);await new Promise(e=>setTimeout(e,50))}}function No(e){return Fo(e)&&e.code===`EEXIST`}function Po(e){return Fo(e)&&e.code===`ESRCH`}function Fo(e){return e instanceof Error}async function Io({confirmStop:e,file:t,interactive:n,owner:r,processes:i}){let a=await Lo(t);if(!a||!i.isRunning(a.owner.pid))return await Ao(t,a?.source),!1;let o=i.command?.(a.owner.pid);if(!o||!Ro(o,r.platform))return!1;if(!n)throw Error(`Coreframe dev is already running for this project (PID ${a.owner.pid}). Stop it before starting another.`);if(await e(a.owner.pid))return i.stop(a.owner.pid),await i.waitForExit(a.owner.pid),await Ao(t,a.source),!0}async function Lo(e){try{let t=await V(e,`utf8`),n=JSON.parse(t);return!Number.isSafeInteger(n.pid)||Number(n.pid)<=0||typeof n.token!=`string`||n.token.length===0?void 0:{owner:n,source:t}}catch{return}}function Ro(e,t){let n=e.trim().split(/\s+/u),r=n.findIndex(e=>{let t=e.split(/[\\/]/u).at(-1);return t===`coreframe`||t===`coreframe.js`||t===`coreframe.ts`});if(r<0)return!1;let i=n.indexOf(`dev`,r+1);return i<0?!1:zo(n.slice(i+1))===t}function zo(e){let t=new Set([`android`,`desktop`,`ios`,`macos`,`web`]),n=new Set([`--debug`,`--host`,`--port`]),r=!1;for(let i of e){if(r){r=!1;continue}if(n.has(i)){r=!0;continue}if(!i.startsWith(`-`))return t.has(i)?i:`web`}return`web`}function Bo(e){let t=G.platform===`win32`?Ho(e):Vo(e);if(t.status===0)return t.stdout.trim()||void 0}function Vo(e){return K(`ps`,[`-p`,String(e),`-o`,`command=`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]})}function Ho(e){return K(`powershell.exe`,[`-NoProfile`,`-NonInteractive`,`-Command`,`(Get-CimInstance Win32_Process -Filter 'ProcessId = ${e}').CommandLine`],{encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]})}async function Uo(e,t){let n=await Wo(P.resolve(e)),r=n.gitCommonDir?P.join(n.path,`coreframe-dev`):P.join(n.path,`.coreframe`);return{file:P.join(r,`dev.${t}.lock`),repository:n.path}}async function Wo(e){let t=Go(e);return t?{gitCommonDir:!0,path:await Ko(P.resolve(e,t))}:{gitCommonDir:!1,path:await Ko(e)}}function Go(e){let t=K(`git`,[`rev-parse`,`--git-common-dir`],{cwd:e,encoding:`utf8`,stdio:[`ignore`,`pipe`,`ignore`]});if(t.status===0)return t.stdout.trim()||void 0}async function Ko(e){return Te(e).catch(()=>P.resolve(e))}function qo(e,t){return e.platform===t.platform&&e.repository===t.repository}function Jo(e,t){let n={...e};return t===`desktop`?delete n.COREFRAME_PLATFORM:t===`web`||t===`webext`?n.COREFRAME_PLATFORM=`web`:n.COREFRAME_PLATFORM=t,n}const Yo=G.platform===`win32`?`portless.cmd`:`portless`;async function Xo({cwd:e,env:t,platform:n}){return n!==`web`||t.PORTLESS===`0`||t.TAURI_ENV_PLATFORM!==void 0||(await Gt()).isAgent?!1:Mt(e)}async function Zo({cwd:e,env:t,lan:n=!1}){let r=P.join(`node_modules`,`.bin`,Yo),i=[`proxy`,`start`,...n?[`--lan`]:[]];await R(G.platform===`win32`?P.resolve(e,r):`sudo`,G.platform===`win32`?i:[r,...i],{cwd:e,env:t,stdio:`inherit`})}function Qo({host:e,lan:t=!1,port:n}){return[...t?[`--lan`]:[],`run`,...n===void 0?[]:[`--app-port`,String(n)],`react-router`,`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e]]}async function $o({cwd:e=G.cwd(),platform:t}){let n=await es({cwd:e});if(!n||!ls(n.platform)||!us(n.platform,t)||!fs(n.owner.pid))return;let r=await Eo({cwd:e,platform:n.platform});if(!(!r||!ps(n.owner,r))&&!(n.postgres?.pid!==void 0&&!fs(n.postgres.pid)))return n}async function es({cwd:e=G.cwd()}={}){let t;try{t=JSON.parse(await V(rs(e),`utf8`))}catch{return}return is(t)&&t.cwd===P.resolve(e)?t:void 0}async function ts({cwd:e=G.cwd(),owner:t,platform:n,postgres:r,vitePort:i}){let a=rs(e),o=P.dirname(a),s=`${a}.${W()}.tmp`,c={cwd:P.resolve(e),owner:t,platform:n,...r?{postgres:r}:void 0,version:1,vite:{port:i}};await B(o,{recursive:!0});try{await U(s,`${JSON.stringify(c)}\n`,{flag:`wx`,mode:384}),await Ee(s,a)}finally{await Oe(s).catch(()=>void 0)}}async function ns({cwd:e=G.cwd(),owner:t}){let n=rs(e),r=await es({cwd:e});!r||!ps(r.owner,t)||await Oe(n).catch(()=>void 0)}function rs(e){return P.resolve(e,`.coreframe/dev.session.json`)}function is(e){if(!e||typeof e!=`object`)return!1;let t=e;return t.version===1&&typeof t.cwd==`string`&&as(t.owner)&&ss(t.platform)&&ds(t.vite?.port)&&(t.postgres===void 0||os(t.postgres))}function as(e){if(!e||typeof e!=`object`)return!1;let t=e,n=t.pid;return typeof n==`number`&&Number.isSafeInteger(n)&&n>0&&typeof t.token==`string`}function os(e){if(!e||typeof e!=`object`)return!1;let t=e;return typeof t.dataDir==`string`&&(t.pid===void 0||Number.isSafeInteger(t.pid)&&t.pid>0)}function ss(e){return e===`android`||e===`desktop`||e===`ios`||e===`macos`||e===`web`}function cs(e){return e===`android`||e===`ios`||e===`macos`}function ls(e){return e===`web`||cs(e)}function us(e,t){return t===void 0?cs(e):e===t}function ds(e){return typeof e==`number`&&Number.isSafeInteger(e)&&e>0&&e<=65535}function fs(e){try{return G.kill(e,0),!0}catch(e){return e instanceof Error&&e.code===`EPERM`}}function ps(e,t){return e.pid===t.pid&&e.token===t.token}const ms=G.platform===`win32`?`pnpm.cmd`:`pnpm`,hs=G.platform===`win32`?`portless.cmd`:`portless`,gs=G.platform===`win32`?`react-router.cmd`:`react-router`,_s=G.platform===`win32`?`turso.cmd`:`turso`;async function vs({cwd:e=G.cwd(),debug:t,device:n,env:r=G.env,host:i,https:a=!1,interactive:o=G.stdin.isTTY===!0,lan:s=!1,managed:c=!1,noManaged:l=!1,platform:u=`web`,portless:d,fresh:f=!1,reuseVite:p=!1,verbose:m=!1,webPort:h,supervisor:g}){let _=Ot({env:r}),v=ws(u)?u:void 0,y=Ts(u),b=u===`ios`||u===`android`?u:void 0,x=b?await Ja({env:r,interactive:o,platform:b,target:n}):void 0,S=b&&x?await Ya({device:x,host:i,interactive:o,platform:b}):void 0,C=v?!0:i,w=await _.measure(`config`,()=>Fe({cwd:e})),T=await _.measure(`managed`,async()=>t!==`managed-dev-overlay`&&(c||o&&!l)&&await jt(e));await _.measure(`i18n`,()=>Un({cwd:e,projectConfig:w}));let E=await _.measure(`routing`,async()=>d??await Xo({cwd:e,env:r,platform:u})),ee=await _.measure(`https`,async()=>a&&!E?Nt({cwd:e}):void 0),te=Jo(r,u),D={...te,..._.environment,...T?{[zt]:`1`,[Bt]:`1`}:void 0,...t===`managed-dev-overlay`?{VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG:`1`}:void 0,...v?{COREFRAME_PLATFORM:v}:void 0,...ee?{[kt]:ee.cert,[At]:ee.key}:void 0},O=!1,ne,re,k,A,j,ae,M,oe=new Map,N=[`postgres`,y];for(let e of N){let t=e===`postgres`?`postgres`:e.startsWith(`vite:flutter`)?`flutter`:`web`,n=Y({label:t}),r=Y({color:`red`,label:t});n.pipe(G.stdout,{end:!1}),r.pipe(G.stderr,{end:!1}),oe.set(e,{stderr:r,stdout:n})}let se=g.onEvent(e=>{e.event===`log`?(oe.get(e.resource)?.[e.stream])?.write(e.data):e.event===`service`&&e.resource===y&&e.state===`failed`&&(M=Error(e.error??`${y} development failed.`),F())}),F=()=>{O||(O=!0,k?.kill(`SIGTERM`),A?.kill(`SIGTERM`),re?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0))},ce=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>{ne??=e,F()};return G.on(e,t),{handler:t,signal:e}}),I=async e=>{let t=Vt(e);k=t;try{await t.expectSuccess()}catch(e){if(!O)throw e}finally{k===t&&(k=void 0)}};try{if(await g.subscribe(N),Cs(w)){let e=await g.acquirePostgres({config:w,env:D});j=e.leaseId,D={...D,...e.env}}if(w.database?.dialect===`sqlite`){let t=await Ba.getAvailablePort(),n=P.resolve(e,`.coreframe`),r=P.join(n,`turso.db`);await $.mkdir(n,{recursive:!0}),D={...D,TURSO_DATABASE_URL:`http://127.0.0.1:${t}`,TURSO_AUTH_TOKEN:`dev`},A=Vt({name:`turso`,command:_s,args:[`dev`,`--port`,String(t),`--db-file`,r],cwd:e,env:D}),await A.waitFor(`listening`)}(Cs(w)||w.database?.dialect===`sqlite`)&&await _.measure(`schema`,()=>I({name:`db`,command:ms,args:[`db`,`ensure`],cwd:e,env:D,prefix:!1}));let t=Ss(h??r.COREFRAME_WEB_PORT),n=await g.status(),i=n.resources?.find(e=>e.resource===y),c=i!==void 0&&!f&&t===void 0?void 0:t??5173,l=c??i?.endpoint?.port??5173;if(c!==void 0&&n.resources?.some(e=>e.resource!==y&&e.endpoint?.port===l)){if(t!==void 0)throw Error(`Port ${l} is already used by another Coreframe development shell.`);l=await Ba.getAvailablePort()}if(!p){let t={...D,CLOUDFLARE_ENV:`development`,NODE_OPTIONS:[D.NODE_OPTIONS,`--conditions=development`].filter(Boolean).join(` `),PATH:P.join(e,`node_modules`,`.bin`)+P.delimiter+(D.PATH??``)},n=[{args:E?Qo({host:C,lan:s,port:l}):[`dev`,...C===void 0?[]:[`--host`,C===!0?`0.0.0.0`:C],`--port`,String(l),...v?[`--strictPort`]:[]],command:E?hs:gs,cwd:e,env:t},{args:[`exec`,`panda`,`dev`,`--no-color`],command:ms,cwd:e,env:D}],r=await g.acquireVite({configFingerprint:xs({cwd:e,host:C,lan:s,https:a,portless:E,resource:y}),endpoint:{host:C===!0?`0.0.0.0`:C??`127.0.0.1`,port:l},processes:n,resource:y},f);ae=r.leaseId,l=r.endpoint.port}if(_.report(),O)return;if(u===`web`?await bs(g,y,()=>M):(await ie({cwd:e}),await ys({cwd:e,env:te,interactive:o,mobileHost:S,platform:u,port:l,requestStop:F,selectedDevice:x,isStopping:()=>O,setActiveNative:e=>{re=e},verbose:m})),M)throw M}finally{F(),ae&&await g.release(ae).catch(()=>void 0),j&&await g.release(j).catch(()=>void 0),se();for(let{handler:e,signal:t}of ce)G.off(t,e);for(let e of oe.values())e.stdout.end(),e.stderr.end();ne&&(G.exitCode??=ne===`SIGINT`?130:143),g.close()}}async function ys({cwd:e,env:t,interactive:n,mobileHost:r,platform:i,port:a,requestStop:o,selectedDevice:s,isStopping:c,setActiveNative:l,verbose:u}){for(;;){let d=i===`android`&&!u?await oe():void 0,f=R(`flutter`,[`run`,`-d`,s?.id??`macos`,`--dart-define=COREFRAME_DEV_SERVER_URL=${Es(i,r,a)}`,...u?[`--verbose`]:[]],{cwd:P.join(e,`src-flutter`),env:t,stdio:d?[`inherit`,`pipe`,`pipe`]:`inherit`});l(f);try{await Promise.all([f,d?.capture(f)]);return}catch(e){if(c()||i===`desktop`||!n)throw e;let t=await z.confirm({initialValue:!0,message:`Flutter failed. Retry?`});if(z.isCancel(t)||!t){o();return}}finally{l(void 0)}}}async function bs(e,t,n){await e.waitForServiceExit(t);let r=n();if(r)throw r}function xs({cwd:e,host:t,lan:n,https:r,portless:i,resource:a}){return Le(`sha256`).update(JSON.stringify({cwd:P.resolve(e),host:t??null,lan:n,https:r,portless:i,resource:a})).digest(`hex`)}function Ss(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}function Cs(e){return(e.database?.dialect??`postgres`)===`postgres`}function ws(e){return e===`android`||e===`ios`||e===`macos`}function Ts(e){if(e===`web`)return`vite:web`;if(ws(e))return`vite:flutter:${e}`;throw Error(`Unsupported supervised development platform: ${e}.`)}function Es(e,t,n){let r=t??(e===`android`?`10.0.2.2`:`127.0.0.1`);return`http://${r.includes(`:`)&&!r.startsWith(`[`)?`[${r}]`:r}:${n}`}const Ds=`extension:dev`;function Os(e){if(!q(I(e,`src-webext/wxt.config.ts`)))throw Error("No WXT configuration found at src-webext/wxt.config.ts. Apply the wxt recipe or add that convention before running `coreframe dev webext`.");let t=I(e,`package.json`),n;try{n=JSON.parse(J(t,`utf8`))}catch(e){throw Error(`Could not parse ${t}.`,{cause:e})}if(!n||typeof n!=`object`||!(`scripts`in n)||!n.scripts||typeof n.scripts!=`object`||!(`extension:dev`in n.scripts)||typeof n.scripts[`extension:dev`]!=`string`)throw Error(`package.json must define scripts.${Ds} for \`coreframe dev webext\`. Apply the wxt recipe and add its named extension lifecycle scripts.`)}function ks({host:e,port:t}){let n=[...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)]];return[`run`,Ds,...n.length>0?[`--`,...n]:[]]}const As=[`web`,`webext`,`desktop`,`ios`,`android`,`macos`],js=[`managed-dev-overlay`],Ms=P.resolve(`node_modules`,`.bin`),Ns=G.platform===`win32`?`pnpm.cmd`:`pnpm`,Ps=G.platform===`win32`?`portless.cmd`:`portless`,Fs=G.platform===`win32`?`react-router.cmd`:`react-router`,Is=G.platform===`win32`?`turso.cmd`:`turso`;async function Ls({cwd:e=G.cwd(),debug:t,device:n,env:r=G.env,host:i,https:a=!1,interactive:o=G.stdin.isTTY===!0,lan:s=!1,managed:c=!1,noManaged:l=!1,platform:u=`web`,fresh:d=!1,reuseVite:f=!1,supervisor:p,verbose:m=!1,webPort:h}={}){let g=Ot({env:r}),_=r.PATH??r.Path??``,v=u===`ios`||u===`android`||u===`macos`?u:void 0,y=u===`web`||v!==void 0;if(d&&f)throw Error(`Cannot use --fresh and --reuse-vite together.`);let b=!d&&(v||u===`web`)?await g.measure(`dev-session`,()=>$o({cwd:e,platform:u})):void 0,x=f||b!==void 0,S=u===`desktop`?void 0:Ys(h??r.COREFRAME_WEB_PORT);if(b&&S!==void 0&&S!==b.vite.port)throw Error(`The active development session uses port ${b.vite.port}. Omit --port or use that port when reusing it.`);let C=u===`ios`||u===`android`||u===`macos`?b?.vite.port??S??5173:u===`web`||u===`webext`?b?.vite.port??S:void 0,w,T,E,ee,te,D,O,ne,re,k=!1,A,j=r,ae,M;if(c&&l)throw Error(`Cannot use --managed and --no-managed together.`);if(t===`managed-dev-overlay`&&c)throw Error(`Cannot use --managed with --debug managed-dev-overlay.`);if(f&&v===void 0)throw Error(`The --reuse-vite option is only supported for Flutter development platforms (iOS, Android, and macOS).`);if(u===`webext`){if(c||l||t!==void 0||m)throw Error(`Managed development, debug features, and verbose native output are only supported for the main web or native development platforms.`);Os(e)}if(a&&u!==`web`)throw Error(`Local HTTPS is only supported for the web development platform.`);if(n!==void 0&&u!==`ios`&&u!==`android`)throw Error(`A device name or ID is only supported for iOS or Android development.`);if(u===`web`&&r.TAURI_ENV_PLATFORM!==void 0&&r.COREFRAME_TAURI_DEV!==`1`)throw Error("Direct Tauri development is not supported. Run `pnpm dev desktop` instead.");let N=await g.measure(`routing`,()=>Xo({cwd:e,env:r,platform:u}));if(N&&await g.measure(`portless`,()=>Zo({cwd:e,env:r,lan:s})),y&&r.COREFRAME_DEV_SUPERVISOR!==`0`){let g=p??await Dt({cwd:e,env:r});if(g)return vs({cwd:e,debug:t,device:n,env:r,fresh:d,host:i,https:a,interactive:o,lan:s,managed:c,noManaged:l,platform:u,portless:N,reuseVite:f,supervisor:g,verbose:m,webPort:h})}let se=x?void 0:await g.measure(`dev-lock`,()=>To({cwd:e,interactive:o,platform:u}));if(!x&&!se)return;let F=()=>{k||(k=!0,T?.kill(`SIGTERM`),ee?.kill(`SIGTERM`),D?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),O?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),re?.close().catch(()=>void 0),ne?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),w?.nodeChildProcess.then(e=>e.kill(`SIGTERM`)).catch(()=>void 0),te?.kill(`SIGTERM`))},ce=e=>{A??=e,F()},I=[`SIGINT`,`SIGTERM`].map(e=>{let t=()=>ce(e);return G.on(e,t),{handler:t,signal:e}}),le=async e=>{let t=Vt(e);T=t;try{await t.expectSuccess()}catch(e){if(!k)throw e}finally{T===t&&(T=void 0)}};try{let d=u===`ios`||u===`android`?u:void 0,f=d?await Ja({env:r,interactive:o,platform:d,target:n}):void 0,p=d&&f?await Ya({device:f,host:i,interactive:o,platform:d}):void 0,h=v?!0:i,y={},b=!1,S;x||([y,b]=await Promise.all([g.measure(`config`,()=>Fe({cwd:e})),g.measure(`managed`,async()=>t!==`managed-dev-overlay`&&(c||o&&!l)&&await jt(e))]),await g.measure(`i18n`,()=>Un({cwd:e,projectConfig:y})),S=u!==`webext`&&Rs(e)?await Ba.getAvailablePort():void 0);let T=x?void 0:await g.measure(`https`,async()=>a&&!N?Nt({cwd:e}):void 0),A=Jo(r,u);j={...A,...g.environment,...b?{[zt]:`1`}:void 0,...t===`managed-dev-overlay`?{VITE_COREFRAME_MANAGED_DEV_OVERLAY_DEBUG:`1`}:void 0,...u===`desktop`?{COREFRAME_TAURI_DEV:`1`,TAURI_ENV_PLATFORM:qs()}:void 0,...v?{COREFRAME_PLATFORM:v}:void 0,...T?{[kt]:T.cert,[At]:T.key}:void 0,...S?{COREFRAME_DASHBOARD_ORIGIN:`http://127.0.0.1:${S}`}:void 0};let ce=async()=>{if(!S)return;let t,n=async(e,n)=>{try{await e,k||t?.fail(Error(`The dashboard development server stopped unexpectedly.`))}catch(e){k||t?.fail(e)}finally{await n.outputTasks,n.stdout.end(),n.stderr.end(),await Promise.allSettled([Rt(n.stdout),Rt(n.stderr)]),ne===e&&(ne=void 0)}};t=xo({port:S,start:async()=>{if(k)throw Error(`The dashboard development server was stopped before it started.`);let t=await Ba.getAvailablePort();if(k)throw Error(`The dashboard development server was stopped before it started.`);let r=Y({label:`dashboard`}),i=Y({color:`red`,label:`dashboard`});r.pipe(G.stdout,{end:!1}),i.pipe(G.stderr,{end:!1});let a=R(Fs,[`dev`,`--host`,`127.0.0.1`,`--port`,String(t)],{cwd:P.resolve(e,`dashboard`),env:{...j,PATH:P.resolve(e,`node_modules/.bin`)+P.delimiter+_},stdin:`inherit`});ne=a;let o=Promise.allSettled([zs(a.stdout,r),zs(a.stderr,i)]);return n(a,{outputTasks:o,stderr:i,stdout:r}),{host:`127.0.0.1`,port:t}}}),re=t;try{await t.listen(),await t.wait()}finally{await t.close(),re===t&&(re=void 0)}},I=async()=>{let t=Y({label:`web`}),n=Y({color:`red`,label:`web`});t.pipe(G.stdout,{end:!1}),n.pipe(G.stderr,{end:!1}),D=R(N?Ps:Fs,N?Qo({host:h,lan:s,port:C}):Js({host:h,port:C,strictPort:v!==void 0}),{cwd:e,env:{...j,CLOUDFLARE_ENV:`development`,NODE_OPTIONS:[j.NODE_OPTIONS,`--conditions=development`].filter(Boolean).join(` `),PATH:Ms+P.delimiter+_},stdin:`inherit`});let r=Promise.allSettled([zs(D.stdout,t),zs(D.stderr,n)]);try{await D;let e=(await r).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!k)throw e}finally{await r,t.end(),n.end(),await Promise.allSettled([Rt(t),Rt(n)]),D=void 0}},L=async()=>{let t=Y({label:`webext`}),n=Y({color:`red`,label:`webext`});t.pipe(G.stdout,{end:!1}),n.pipe(G.stderr,{end:!1}),O=R(Ns,ks({host:i,port:C}),{cwd:e,env:j,stdin:`inherit`});let r=Promise.allSettled([zs(O.stdout,t),zs(O.stderr,n)]);try{await O;let e=(await r).find(e=>e.status===`rejected`);if(e)throw e.reason}catch(e){if(!k)throw e}finally{await r,t.end(),n.end(),await Promise.allSettled([Rt(t),Rt(n)]),O=void 0}},ue=async t=>{for(;!k;){let n=u===`android`&&!m?await oe():void 0,r=u===`desktop`?R(Ns,Ws(),{cwd:e,env:A,stdio:`inherit`}):R(`flutter`,Gs({device:f??{id:`macos`},serverUrl:Ks(u,p,C),verbose:m}),{cwd:P.join(e,`src-flutter`),env:A,stdio:n?[`inherit`,`pipe`,`pipe`]:`inherit`});w=r;try{await Promise.all([r,n?.capture(r)]);return}catch(e){if(u===`desktop`||k||!o)throw e;let n=await z.confirm({initialValue:!0,message:`Flutter failed. Retry?`});if(z.isCancel(n)||!n){z.log.warn(t?`Flutter stopped. Web development is still running.`:`Flutter stopped.`),t&&await t;return}}finally{w===r&&(w=void 0)}}},de=async()=>{if(x){if(u===`web`)return;await ie({cwd:e}),await ue();return}if(u===`web`){await I();return}let t=I().then(()=>{if(!k)throw Error(`The Vite development server stopped while ${u===`desktop`?`Tauri`:`Flutter`} was still running.`)});u!==`desktop`&&await ie({cwd:e});try{await Promise.race([t,ue(t)])}finally{F(),await Promise.allSettled([t,w]),w=void 0}},fe=async()=>{let t=Vt({name:`panda`,command:Ns,args:[`exec`,`panda`,`dev`,`--no-color`],cwd:e,env:j});ee=t;try{if(await t.expectSuccess(),!k)throw Error(`The Panda CSS watcher stopped while development was still running.`)}catch(e){if(!k)throw e}finally{ee===t&&(ee=void 0)}},pe=async()=>{if(u===`webext`){await L();return}if(x){await de();return}let e=fe(),t=de(),n=S?ce():void 0;try{await Promise.race([e,t,n].filter(e=>e!==void 0)),k&&await t}finally{F(),await Promise.allSettled([e,t,n].filter(e=>e!==void 0))}},me=async()=>{x||!se?.owner||C===void 0||(await ts({cwd:e,owner:se.owner,platform:u,postgres:M,vitePort:C}),ae=se.owner)};if(b&&(j={...j,[Bt]:`1`}),k)return;if(u===`webext`){g.report(),await pe();return}if(x){g.report(),await pe();return}if(y.database?.dialect===`sqlite`&&(await g.measure(`database`,async()=>{let t=await Ba.getAvailablePort(),n=P.resolve(e,`.coreframe`),i=P.join(n,`turso.db`);await $.mkdir(n,{recursive:!0}),j={...j,TURSO_DATABASE_URL:`http://127.0.0.1:${t}`,TURSO_AUTH_TOKEN:`dev`},te=Vt({name:`turso`,command:Is,args:[`dev`,`--port`,String(t),`--db-file`,i],cwd:e,env:r}),await te.waitFor(`listening`)}),await g.measure(`schema`,()=>le({name:`db`,command:Ns,args:[`db`,`ensure`],cwd:e,env:j,prefix:!1})),k))return;if(Us(y)){let t=Y({label:`postgres`});t.pipe(G.stdout,{end:!1});try{let n=await g.measure(`database`,()=>Hs({config:y,cwd:e,env:j,failIfRunning:!0,interactive:o,isStopping:()=>k,postgresOutput:t,takeoverApproved:se?.takeoverApproved??!1}));if(!n)return;E=n,j=n.env,M=await Vs(n.env);try{k||await g.measure(`schema`,()=>le({name:`db`,command:Ns,args:[`db`,`ensure`],cwd:e,env:j,prefix:!1})),k||(await me(),g.report(),await pe())}finally{await n[Symbol.asyncDispose](),E===n&&(E=void 0)}}finally{t.end()}return}await me(),g.report(),await pe()}finally{F(),ae&&=(await ns({cwd:e,owner:ae}),void 0);let t;try{await E?.[Symbol.asyncDispose]()}catch(e){t=e}finally{for(let{handler:e,signal:t}of I)G.off(t,e);A&&(G.exitCode??=A===`SIGINT`?130:143)}Bs(t),await se?.release()}}function Rs(e){return q(P.resolve(e,`dashboard/dashboard.config.ts`))}async function zs(e,t){for await(let n of e)t.write(`${n}\n`)||await Lt(t,`drain`)}function Bs(e){if(e)throw e}async function Vs(e){let t=e.PGDATA;if(!t)return;let n=Number((await $.readFile(P.join(t,`postmaster.pid`),`utf8`).catch(()=>``)).split(/\r?\n/,1)[0]);return{dataDir:P.resolve(t),...Number.isSafeInteger(n)&&n>0?{pid:n}:void 0}}async function Hs({interactive:e,isStopping:t,takeoverApproved:n,...r}){try{return await re(r)}catch(i){if(!(i instanceof m)||!e)throw i;if(!n){let e=await z.confirm({initialValue:!1,message:`PostgreSQL is already running for this project (PID ${i.pid}). Stop it and start here?`});if(z.isCancel(e)||!e){z.cancel(`Keeping the existing PostgreSQL process.`);return}}return await k(i),t()?void 0:re(r)}}function Us(e){return(e.database?.dialect??`postgres`)===`postgres`}function Ws(){return[`exec`,`tauri`,`dev`,`--config`,JSON.stringify({build:{beforeDevCommand:``}})]}function Gs({device:e,serverUrl:t,verbose:n}){return[`run`,`-d`,e.id,`--dart-define=COREFRAME_DEV_SERVER_URL=${t}`,...n?[`--verbose`]:[]]}function Ks(e,t,n){let r=t??(e===`android`?`10.0.2.2`:`127.0.0.1`);return`http://${r.includes(`:`)&&!r.startsWith(`[`)?`[${r}]`:r}:${n}`}function qs(){return G.platform===`win32`?`windows`:G.platform}function Js({host:e,port:t,strictPort:n=!1}){return[`dev`,...e===void 0?[]:[`--host`,e===!0?`0.0.0.0`:e],...t===void 0?[]:[`--port`,String(t)],...n?[`--strictPort`]:[]]}function Ys(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}async function Xs(e={}){let t=e.cwd??G.cwd(),n=await Ne(`scripts/preview.ts`,t);if(typeof n.default!=`function`)throw Error(`scripts/preview.ts must export a default preview function.`);return Kt({...e,cwd:t},n.default)}const Zs=P.resolve(`node_modules`,`.bin`);G.env.PATH=Zs+P.delimiter+G.env.PATH;const Qs=G.platform===`win32`?`tsc.cmd`:`tsc`,$s=[{name:`scripts`,path:`scripts/tsconfig.json`},{name:`shared`,path:`src/shared/tsconfig.json`},{name:`api`,path:`src/api/tsconfig.json`},{name:`worker`,path:`src/api/worker/tsconfig.json`},{name:`web`,path:`src/web/tsconfig.json`},{name:`dashboard`,path:`dashboard/tsconfig.json`}];async function ec(){let e=[];for(let t of $s)try{await ye(t.path),e.push(t)}catch(e){if(!(e instanceof Error&&`code`in e&&e.code===`ENOENT`))throw e}let t=e.map(e=>Vt({name:e.name,command:Qs,args:[`-p`,e.path]})),n=(await Promise.all(t.map(e=>e.wait()))).filter(e=>e.exitCode!==0);n.length>0&&(G.exitCode=n[0].exitCode)}const tc=`worker-configuration.d.ts`;async function nc({check:e=!1,cwd:t=process.cwd()}={}){let n=await Fe({cwd:t}),r=await tt({coreframeConfig:n,cwd:t}),i=L(t,tc),a=L(t,`.coreframe-worker-types-${W()}.d.ts`);try{await R(`pnpm`,[`exec`,`wrangler`,`types`,a,`--config`,r.path,`--strict-vars=false`,`--include-runtime=false`],{cwd:t,stdio:`inherit`});let o=rc(await V(a,`utf8`)),s=Ie(r.config),c=Pe(n.worker?.environment).filter(e=>!s.has(e.name)),l=`${o.trimEnd()}\n\n${ic(c)}\n`;if(e){if(await V(i,`utf8`).catch(()=>``)!==l)throw Error(`${tc} is stale. Run "coreframe worker typegen" and commit the result.`);return{changed:!1,path:i}}let u=await V(i,`utf8`).catch(()=>``);return u!==l&&await U(i,l),{changed:u!==l,path:i}}finally{await r.dispose(),await H(a,{force:!0})}}function rc(e){return e.split(/\r?\n/).filter(e=>!e.startsWith(`// Generated by Wrangler by running `)).join(`
12
+ `)}function ic(e){return[`// Coreframe application string inventory declaration-merges with Wrangler's generated Env.`,`interface Env {`,...e.map(e=>` /** ${e.description.replaceAll(`*/`,`*\\/`)} */\n ${JSON.stringify(e.name)}?: string`),`}`].join(`
13
+ `)}const ac=r(s(js),{displayName:`feature`,from:async e=>e}),oc=[`Cookies and sessions are origin-scoped.`,`Exact-host passkeys may require re-registration unless a stable eligible parent RP ID was configured in advance.`,`External OAuth callbacks such as Google may need updating.`,`Database data and private backend resources are unchanged.`],sc=n({name:`deploy`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Deploy to the staging or production environment.`}),runMigrations:i({long:`run-migrations`,description:`Run pending deploy-safe database migrations before deploying.`,defaultValue:()=>!1}),skipMigrations:i({long:`skip-migrations`,description:`Deploy without running pending deploy-safe database migrations.`,defaultValue:()=>!1}),skipPostDeployChecks:i({long:`skip-post-deploy-checks`,description:`Skip post-deploy checks after Cloudflare deployment.`,defaultValue:()=>!1}),tauriLocalPlatforms:a({long:`tauri-local-platform`,type:t(s(bt)),description:`Build one Tauri release platform locally. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowName:c({long:`tauri-workflow-name`,type:l(f),description:`GitHub Actions workflow file or name for remote Tauri release builds.`}),tauriWorkflowPlatforms:a({long:`tauri-workflow-platform`,type:t(s(bt)),description:`Build one Tauri release platform with GitHub Actions. Repeat for multiple platforms.`,defaultValue:()=>[]}),tauriWorkflowRef:c({long:`tauri-workflow-ref`,type:l(f),description:`Git ref used when dispatching remote Tauri release builds.`}),yes:i({long:`yes`,short:`y`,description:`Approve the production deployment confirmation.`,defaultValue:()=>!1})},handler:({environment:e,runMigrations:t,skipMigrations:n,skipPostDeployChecks:r,tauriLocalPlatforms:i,tauriWorkflowName:a,tauriWorkflowPlatforms:o,tauriWorkflowRef:s,yes:c})=>ba([e,...t?[`--run-migrations`]:[],...n?[`--skip-migrations`]:[],...r?[`--skip-post-deploy-checks`]:[],...i.flatMap(e=>[`--tauri-local-platform`,e]),...a?[`--tauri-workflow-name`,a]:[],...o.flatMap(e=>[`--tauri-workflow-platform`,e]),...s?[`--tauri-workflow-ref`,s]:[],...c?[`--yes`]:[]])}),cc=p({name:`staging`,cmds:{reassign:n({name:`reassign`,args:{json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await dt();if(e){console.log(JSON.stringify({...t,notices:oc}));return}console.log(t.url),console.error(`Staging hostname reassigned. ${oc.join(` `)}`)}}),url:n({name:`url`,args:{json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({json:e})=>{let t=await Qe();console.log(e?JSON.stringify({url:t}):t)}})}}),lc=p({name:`secrets`,cmds:{"rotate-access-token":n({name:`rotate-access-token`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment whose access JWTs should be invalidated.`}),yes:i({long:`yes`,short:`y`,description:`Confirm immediate signing-secret replacement and invalidation of outstanding access JWTs.`,defaultValue:()=>!1})},handler:async({environment:e,yes:t})=>{if(!t)throw Error(`Access-token signing-secret rotation requires --yes because it immediately invalidates outstanding access JWTs.`);await _t({environment:e}),console.log(`Rotated Coreframe access-token signing material for ${e}. Clients must remint outstanding access JWTs.`)}}),status:n({name:`status`,args:{environment:u({type:l(s(Xe)),displayName:`environment`,description:`Inspect staging, production, or both when omitted.`}),json:i({long:`json`,description:`Print machine-readable JSON.`,defaultValue:()=>!1})},handler:async({environment:e,json:t})=>{let n=await $e({environment:e});console.log(t?JSON.stringify(n):mc(n))}}),set:n({name:`set`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment to update on its next deploy.`}),name:u({type:l(f),displayName:`name`,description:`Declared Worker secret name; omit to configure known secrets.`}),bulk:i({long:`bulk`,description:`Queue known secrets from pasted or piped dotenv-formatted contents.`,defaultValue:()=>!1})},handler:async({environment:e,name:t,bulk:n})=>{if(n&&t)throw Error(`Use either a secret name or --bulk, not both.`);if(t){await ot({environment:e,name:t,value:await hc(t)}),console.log(`Queued ${t} for ${e}. Run coreframe deploy ${e} to apply.`);return}let r=await ct(),i=n?await _c(r):await gc(r,e);await st({environment:e,values:i});let a=Object.keys(i).sort();console.log(a.length>0?`Queued ${a.join(`, `)} for ${e}. Run coreframe deploy ${e} to apply.`:`No ${e} Worker secret updates were queued.`)}}),discard:n({name:`discard`,args:{environment:u({type:s(Xe),displayName:`environment`,description:`Worker environment with a queued secret update.`}),name:u({type:f,displayName:`name`,description:`Declared Worker secret name.`})},handler:async({environment:e,name:t})=>{let n=await Ze({environment:e,name:t});console.log(n?`Discarded the queued ${t} update for ${e}.`:`No ${t} update is queued for ${e}.`)}})}}),uc=n({name:`typecheck`,args:{},handler:ec}),dc=p({name:`worker`,cmds:{typegen:n({name:`typegen`,args:{check:i({long:`check`,description:`Fail when the committed primary Worker declarations are stale.`,defaultValue:()=>!1})},handler:async({check:e})=>{let t=await nc({check:e});console.log(e?`${yc(t.path)} is current.`:`${yc(t.path)} ${t.changed?`generated`:`is unchanged`}.`)}})}}),fc=n({name:`dev`,args:{debug:c({long:`debug`,type:l(ac),description:`Launch a development feature in isolated debug mode.`}),https:i({long:`https`,description:`Serve the web app over locally trusted HTTPS.`,defaultValue:()=>!1}),fresh:i({long:`fresh`,description:`Start a new directory-scoped development session instead of attaching to one.`,defaultValue:()=>!1}),host:c({long:`host`,type:l(f),implicitValue:`0.0.0.0`,description:`Host address for the web development server. Pass without an address to use 0.0.0.0.`}),lan:i({long:`lan`,description:`Expose the Portless development proxy to devices on the local network.`,defaultValue:()=>!1}),managed:i({long:`managed`,description:`Run managed checkout synchronization even without an interactive terminal.`,defaultValue:()=>!1}),noManaged:i({long:`no-managed`,description:`Run without managed checkout synchronization for this invocation.`,defaultValue:()=>!1}),reuseVite:i({long:`reuse-vite`,description:`Use an existing Vite development server instead of starting another one for Flutter.`,defaultValue:()=>!1}),stop:i({long:`stop`,description:`Stop the directory development supervisor and its managed services.`,defaultValue:()=>!1}),platform:u({type:l(s(As)),displayName:`platform`,description:`Development target platform. Defaults to web.`}),device:u({type:l(f),displayName:`device`,description:`Device name or ID for iOS or Android development.`}),port:c({long:`port`,type:l(o),description:`Port for the web development server.`}),verbose:i({long:`verbose`,description:`Show the full native development output.`,defaultValue:()=>!1})},handler:({debug:e,device:t,fresh:n,host:r,https:i,lan:a,managed:o,noManaged:s,platform:c,port:l,reuseVite:u,stop:d,verbose:f})=>d?Pt({cwd:G.cwd()}):Ls({debug:e,device:t,fresh:n,host:r,https:i,lan:a,managed:o,noManaged:s,platform:c??`web`,reuseVite:u,verbose:f,webPort:l})}),pc=n({name:`preview`,args:{host:c({long:`host`,type:l(f),description:`Host address for the preview server.`}),port:c({long:`port`,type:l(o),description:`Port for the preview server.`})},handler:({host:e,port:t})=>Xs({host:e,port:t})});function mc(e){if(e.entries.length===0)return`No Worker environment values are declared in coreframe.config.ts.`;let t=e.entries.map(e=>[e.name,e.kind,e.local===`override`?`override`:`built-in default`,e.deployed.staging.replaceAll(`_`,` `),e.deployed.production.replaceAll(`_`,` `)]),n=[`Name`,`Kind`,`Local`,`Staging`,`Production`],r=n.map((e,n)=>Math.max(e.length,...t.map(e=>e[n].length))),i=e=>e.map((e,t)=>e.padEnd(r[t])).join(` `).trimEnd();return[i(n),i(r.map(e=>`-`.repeat(e))),...t].join(`
14
+ `)}async function hc(e){if(!G.stdin.isTTY){let e=``;for await(let t of G.stdin)e+=t.toString();return e.replace(/\r?\n$/,``)}let t=await z.password({message:`Enter the new value for ${e}`});if(z.isCancel(t))throw z.cancel(`Secret update cancelled.`),Error(`Secret update cancelled.`);return t}async function gc(e,t){if(!G.stdin.isTTY)throw Error(`Interactive secret setup requires a terminal. Provide a secret name or use --bulk with piped dotenv contents.`);if(e.length===0)throw Error(`No Worker secrets are declared in coreframe.config.ts.`);let n={};for(let r of e){let e=r.requiredIn.includes(t),i=await z.password({message:`${r.name}: ${r.description}${e?` (required)`:` (optional; leave blank to skip)`}`,validate:n=>e&&!n?.trim()?`${r.name} is required in ${t}.`:void 0});if(z.isCancel(i))throw z.cancel(`Secret setup cancelled.`),Error(`Secret setup cancelled.`);i.trim()&&(n[r.name]=i)}return n}async function _c(e){if(e.length===0)throw Error(`No Worker secrets are declared in coreframe.config.ts.`);let t=G.stdin.isTTY?await z.multiline({message:`Paste dotenv-formatted Worker secrets. Press Enter twice to submit.`,validate:e=>e?.trim()?void 0:`Paste at least one dotenv entry.`}):await vc();if(z.isCancel(t))throw z.cancel(`Secret setup cancelled.`),Error(`Secret setup cancelled.`);let{ignoredNames:n,values:r}=nt(t,e);return n.length>0&&z.log.info(`Ignored non-secret or undeclared names: ${n.join(`, `)}.`),r}async function vc(){let e=``;for await(let t of G.stdin)e+=t.toString();return e}function yc(e){return e.split(/[\\/]/).at(-1)??e}function bc(e,{formatMessage:t,temporaryDirectory:n=je(),write:r=e=>console.error(e)}={}){let i=Ec(e),a=kc(Sc(e,t),i);try{let t=I(Ve(I(n,`coreframe-error-`)),`error.log`);return Ge(t,`${kc(Cc(e),i)}\n`,{mode:384}),r(`Error: ${a}\nFull diagnostic: ${t}`),t}catch{r(`Error: ${a}\nThe full diagnostic could not be written to the temporary directory.`);return}}function xc(t,n={}){let r=typeof t==`function`?t:()=>e.run(e.binary(t),process.argv),i=!1,a=e=>{i||(i=!0,bc(e,n),process.exit(1))};process.once(`uncaughtException`,a),process.once(`unhandledRejection`,a),Promise.resolve().then(r).catch(a)}function Sc(e,t){try{return t?.(e)||(e instanceof Error?e.message:String(e)).split(/\r?\n/,1)[0]||`Unknown error`}catch{return`Unknown error`}}function Cc(e){try{let t=wc(e);if(!(e instanceof Error)||!Tc(t))return Ft(t,{customInspect:!1,depth:10});let n=typeof t.stack==`string`?t.stack:`${e.name}: ${e.message}`;return delete t.name,delete t.message,delete t.stack,`${n}${Reflect.ownKeys(t).length?`\n${Ft(t,{customInspect:!1,depth:10})}`:``}`}catch{return`The thrown value could not be inspected.`}}function wc(e,t=new WeakMap){if((typeof e!=`object`||!e)&&typeof e!=`function`)return e;let n=e,r=t.get(n);if(r)return r;if(typeof e==`function`)return`[Function${e.name?`: ${e.name}`:``}]`;let i=Array.isArray(e)?[]:{};t.set(n,i),e instanceof Error&&(i.name=e.name,i.message=e.message,i.stack=e.stack??`${e.name}: ${e.message}`);for(let r of Reflect.ownKeys(n)){if(typeof r!=`string`||r.toLowerCase()===`env`||Array.isArray(e)&&r===`length`||e instanceof Error&&(r===`name`||r===`message`||r===`stack`))continue;let a=Object.getOwnPropertyDescriptor(n,r);!a||!(`value`in a)||Object.defineProperty(i,r,{configurable:!0,enumerable:!0,value:wc(a.value,t),writable:!0})}return i}function Tc(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}function Ec(e,t=new WeakSet){let n=new Set;function r(e){if((typeof e!=`object`||!e)&&typeof e!=`function`)return;let i=e;if(!t.has(i)){t.add(i);for(let e of Reflect.ownKeys(i)){if(typeof e!=`string`)continue;let t=Object.getOwnPropertyDescriptor(i,e);!t||!(`value`in t)||(e.toLowerCase()===`env`?Dc(t.value,n):r(t.value))}}}try{r(e)}catch{}return n}function Dc(e,t){if(!(typeof e!=`object`||!e))for(let n of Reflect.ownKeys(e)){let r=Object.getOwnPropertyDescriptor(e,n);typeof n==`string`&&Oc(n)&&r&&`value`in r&&typeof r.value==`string`&&r.value&&t.add(r.value)}}function Oc(e){return/(?:^|_)(?:AUTH|CERT|COOKIE|CREDENTIALS?|DATABASE_URL|DSN|KEY|PASS(?:WORD)?|PRIVATE|SECRET|SESSION|TOKEN)(?:_|$)/i.test(e)}function kc(e,t){return[...t].sort((e,t)=>t.length-e.length).reduce((e,t)=>e.replaceAll(t,`[redacted environment value]`),e)}const Ac=p({name:`coreframe`,cmds:{build:rn,dashboard:yr,assets:lr,flutter:ur,i18n:dr,deploy:sc,staging:cc,secrets:lc,typecheck:uc,worker:dc,dev:fc,preview:pc,upgrade:ga,recipes:_a,db:va}});import.meta.main&&xc(Ac,{formatMessage:process.argv[2]===`db`?x:void 0});export{Ac as coreframeCli};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@coreframe/scripts",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "Coreframe project workflow CLI and automation scripts",
5
5
  "repository": {
6
6
  "type": "git",
@@ -28,15 +28,15 @@
28
28
  "nano-spawn": "^2.1.0",
29
29
  "procband": "^0.3.8",
30
30
  "yaml": "^2.9.0",
31
- "@coreframe/assets": "^0.1.3",
32
31
  "@coreframe/config": "^0.1.2",
33
- "@coreframe/db": "^0.1.2",
32
+ "@coreframe/assets": "^0.1.5",
33
+ "@coreframe/dev-contracts": "^0.1.2",
34
34
  "@coreframe/deploy": "^0.1.2",
35
- "@coreframe/dev": "^0.1.2",
36
- "@coreframe/flutter-tools": "^0.1.4",
37
- "@coreframe/object-storage": "^0.1.0",
35
+ "@coreframe/flutter-tools": "^0.1.6",
38
36
  "@coreframe/preview": "^0.1.0",
39
- "@coreframe/dev-contracts": "^0.1.1"
37
+ "@coreframe/db": "^0.1.2",
38
+ "@coreframe/object-storage": "^0.1.0",
39
+ "@coreframe/dev": "^0.1.4"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@types/node": "^26.1.0",
@@ -47,7 +47,8 @@
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsdown",
50
- "test": "vitest run --reporter=minimal",
50
+ "test": "vitest run --reporter=minimal --exclude src/recipes/list.test.ts --exclude src/recipes/apply.test.ts --exclude src/upgrade/fast-forward-template-files.test.ts",
51
+ "test:built": "vitest run --reporter=minimal src/recipes/list.test.ts src/recipes/apply.test.ts src/upgrade/fast-forward-template-files.test.ts",
51
52
  "typecheck": "tsc --noEmit -p tsconfig.json",
52
53
  "format": "oxlint --fix && oxfmt",
53
54
  "lint": "oxlint"