fimo 2.2.0-staging.1 → 2.2.0-staging.3

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "bundled": true,
3
3
  "bundler": "esbuild",
4
- "bundledAt": "2026-08-26T13:08:32.124Z",
4
+ "bundledAt": "2026-08-26T14:54:06.687Z",
5
5
  "cliVersion": "2.1.0",
6
6
  "external": [
7
7
  "oxc-parser",
package/dist/cli/index.js CHANGED
@@ -1258,8 +1258,8 @@ This breaks source tracking for inline editing. Translation keys must be statica
1258
1258
  `),process.exit(1)}}import fs25 from"node:fs";import path28 from"node:path";var SCAN_EXTENSIONS=[".ts",".tsx",".js",".jsx",".mjs"],SCAN_EXTENSIONS_SET=new Set(SCAN_EXTENSIONS),SKIP_DIRS=new Set(["node_modules","dist",".next",".fimo",".git","public"]),GLOBAL_PATTERNS=[/\.css$/,/\.scss$/,/tailwind\.config/,/postcss\.config/,/vite\.config/,/tsconfig/,/package\.json$/,/src\/main\.[tj]sx?$/,/src\/index\.[tj]sx?$/,/src\/root\.[tj]sx?$/,/react-router\.config/];function isGlobalFile(filePath){return GLOBAL_PATTERNS.some(p2=>p2.test(filePath))}__name(isGlobalFile,"isGlobalFile");function collectFiles(dir){let files=[];if(!fs25.existsSync(dir))return files;let entries2=fs25.readdirSync(dir,{withFileTypes:!0});for(let entry of entries2){if(SKIP_DIRS.has(entry.name))continue;let fullPath=path28.join(dir,entry.name);entry.isDirectory()?files.push(...collectFiles(fullPath)):SCAN_EXTENSIONS_SET.has(path28.extname(entry.name))&&files.push(fullPath)}return files}__name(collectFiles,"collectFiles");function extractImports(content2){let imports=[],staticRegex=/(?:import|export)\s+(?:[\s\S]*?)\s+from\s+['"]([^'"]+)['"]/g;for(let match of content2.matchAll(staticRegex))imports.push(match[1]);let dynamicRegex=/import\(\s*['"]([^'"]+)['"]\s*\)/g;for(let match of content2.matchAll(dynamicRegex))imports.push(match[1]);let requireRegex=/require\(\s*['"]([^'"]+)['"]\s*\)/g;for(let match of content2.matchAll(requireRegex))imports.push(match[1]);return imports.filter(s=>s.startsWith(".")||s.startsWith("@/"))}__name(extractImports,"extractImports");function resolveImport(specifier,fromDir,srcDir){let targetPath;if(specifier.startsWith("@/"))targetPath=path28.resolve(srcDir,specifier.slice(2));else if(specifier.startsWith("."))targetPath=path28.resolve(fromDir,specifier);else return null;if(fs25.existsSync(targetPath)&&fs25.statSync(targetPath).isFile())return targetPath;for(let ext of SCAN_EXTENSIONS){let withExt=targetPath+ext;if(fs25.existsSync(withExt))return withExt}for(let ext of SCAN_EXTENSIONS){let indexFile=path28.join(targetPath,"index"+ext);if(fs25.existsSync(indexFile))return indexFile}return null}__name(resolveImport,"resolveImport");function discoverRoutes(srcDir,root2){let routesFilePath=path28.resolve(srcDir,"routes.ts");if(!fs25.existsSync(routesFilePath))return new Map;let source=fs25.readFileSync(routesFilePath,"utf-8"),parsed=parseRoutesSource(source),fileToRoutes=new Map;for(let r of parsed){if(r.isLayout||!r.path||!r.file)continue;let resolved=resolveImport(r.file,srcDir,srcDir);if(!resolved)continue;let rel=path28.relative(root2,resolved);fileToRoutes.has(rel)||fileToRoutes.set(rel,new Set),fileToRoutes.get(rel).add(r.path)}return fileToRoutes}__name(discoverRoutes,"discoverRoutes");function buildReverseImportGraph(srcDir,root2){let fileToImporters=new Map,allFiles=collectFiles(srcDir);for(let filePath of allFiles){let content2;try{content2=fs25.readFileSync(filePath,"utf-8")}catch{continue}let imports=extractImports(content2);for(let specifier of imports){let resolved=resolveImport(specifier,path28.dirname(filePath),srcDir);if(!resolved)continue;let resolvedRel=path28.relative(root2,resolved),importerRel=path28.relative(root2,filePath);fileToImporters.has(resolvedRel)||fileToImporters.set(resolvedRel,new Set),fileToImporters.get(resolvedRel).add(importerRel)}}return fileToImporters}__name(buildReverseImportGraph,"buildReverseImportGraph");function resolveAffectedRoutes(file,fileToImporters,fileToRoutes){let visited=new Set,queue=[file],affectedRoutes=new Set;for(;queue.length>0;){let current=queue.shift();if(visited.has(current))continue;visited.add(current);let routes=fileToRoutes.get(current);if(routes)for(let route of routes)affectedRoutes.add(route);let importers=fileToImporters.get(current);if(importers)for(let importer of importers)visited.has(importer)||queue.push(importer)}return Array.from(affectedRoutes)}__name(resolveAffectedRoutes,"resolveAffectedRoutes");function resolveRoutes(changedFiles,options={}){let root2=options.cwd??process.cwd(),srcDir=path28.resolve(root2,"src"),normalizedChangedFiles=changedFiles.map(f=>f.replace(/^\/+/,""));if(normalizedChangedFiles.length===0)return{routeMap:{},routes:[],unresolvedFiles:[]};let fileToRoutes=discoverRoutes(srcDir,root2),fileToImporters=buildReverseImportGraph(srcDir,root2),routeMap={},unresolvedFiles=[];for(let file of normalizedChangedFiles){if(isGlobalFile(file)){routeMap[file]=["*"];continue}let routes=resolveAffectedRoutes(file,fileToImporters,fileToRoutes);routes.length>0?routeMap[file]=routes:unresolvedFiles.push(file)}let allRoutes=[...new Set(Object.values(routeMap).flat().filter(r=>r!=="*"))];return{routeMap,routes:allRoutes,unresolvedFiles}}__name(resolveRoutes,"resolveRoutes");init_sync_forms();init_sync_schemas();function resolveCwd(options){return options.cwd?resolve7(options.cwd):process.cwd()}__name(resolveCwd,"resolveCwd");function renderPrettyJson4(data2){return JSON.stringify(data2,null,2)}__name(renderPrettyJson4,"renderPrettyJson");async function syncSchemasCommand(options){let cwd=resolveCwd(options),framework=await detectProjectFramework(cwd),result=syncSchemas({cwd,framework:framework?.slug??null});ui.result({command:"scripts sync-schemas",data:result,render:__name(()=>renderPrettyJson4(result),"render")})}__name(syncSchemasCommand,"syncSchemasCommand");async function syncFormsCommand(options){let cwd=resolveCwd(options),framework=await detectProjectFramework(cwd),result=syncForms({cwd,framework:framework?.slug??null});ui.result({command:"scripts sync-forms",data:result,render:__name(()=>renderPrettyJson4(result),"render")})}__name(syncFormsCommand,"syncFormsCommand");async function exportStaticCommand(options){let result=await exportStatic({cwd:resolveCwd(options)});ui.result({command:"export-static",data:result??{ok:!0},render:__name(()=>renderPrettyJson4(result??{ok:!0}),"render")})}__name(exportStaticCommand,"exportStaticCommand");function validateRouteMetadataCommand(options){let result=validateRouteMetadata({cwd:resolveCwd(options)});result.errors.length>0&&(ui.error({command:"scripts validate-route-metadata",code:"ROUTE_METADATA_INVALID",message:`Route metadata validation failed (${result.errors.length} issue(s)):
1259
1259
  ${result.errors.map(e=>` - ${e}`).join(`
1260
1260
  `)}`}),process.exit(1)),ui.ok({command:"scripts validate-route-metadata",headline:`Route metadata validation passed (${result.routesChecked} route${result.routesChecked===1?"":"s"}).`,details:{routes_checked:result.routesChecked}})}__name(validateRouteMetadataCommand,"validateRouteMetadataCommand");function extractTranslationsCommand(options){let cwd=resolveCwd(options),data2={keys:extractTranslations({cwd}).keys.length};ui.result({command:"scripts extract-translations",data:data2,render:__name(()=>JSON.stringify(data2),"render")})}__name(extractTranslationsCommand,"extractTranslationsCommand");function resolveRoutesCommand(changedFiles,options){let cwd=resolveCwd(options),files=[];if(changedFiles.length===1&&changedFiles[0].startsWith("{"))try{files=JSON.parse(changedFiles[0]).files??[]}catch{files=[]}else files=changedFiles;let output=resolveRoutes(files,{cwd});ui.result({command:"resolve-routes",data:output,render:__name(()=>JSON.stringify(output),"render")})}__name(resolveRoutesCommand,"resolveRoutesCommand");function lintProject(opts){let files=opts.targetPath?[resolve7(opts.cwd,opts.targetPath)]:collectFiles2(resolve7(opts.cwd,"src")),errors=[],filesChecked=0;for(let file of files)if(/\.(tsx?|jsx?)$/.test(file))try{let code2=readFileSync8(file,"utf-8");errors.push(...lintTranslationKeys(file,code2)),filesChecked++}catch{}return{errors,filesChecked}}__name(lintProject,"lintProject");function lintCommand(targetPath,options){let cwd=resolveCwd(options),result=lintProject({cwd,targetPath});ui.result({command:"scripts lint",data:result,render:__name(()=>JSON.stringify(result),"render")}),result.errors.length>0&&process.exit(1)}__name(lintCommand,"lintCommand");function collectFiles2(root2){if(!existsSync8(root2))return[];let results=[];for(let name of readdirSync6(root2)){if(name==="node_modules"||name==="dist"||name===".git")continue;let full=join9(root2,name);statSync3(full).isDirectory()?results.push(...collectFiles2(full)):results.push(full)}return results}__name(collectFiles2,"collectFiles");async function validateCommand(options,cmd){let cwd=resolveProjectCwd(options.cwd),branchOverride2=branchOverrideFromCommand(cmd),dependencyWarnings=[],report=await runValidate({cwd,branchOverride:branchOverride2,onWarning:__name(warning=>dependencyWarnings.push(warning),"onWarning")}),packageManager=await resolvePackageManagerContract(cwd),warnings=[getDbLabelsRuntimeWarning(cwd),packageManager.status==="inferred"?packageManager.warning:null,...dependencyWarnings].filter(warning=>!!warning);ui.result({command:"validate",data:report,render:__name(()=>formatReportHuman(report),"render"),warnings:warnings.length>0?warnings:void 0}),report.ok||(process.exitCode=report.exitCode)}__name(validateCommand,"validateCommand");async function runValidate(opts){let{cwd,branchOverride:branchOverride2,onWarning}=opts,checks=await runChecksPhase({cwd,onWarning}),codegen,labelKeys=null;if(checks.errors.length>0)codegen=skippedPhase("Codegen","static checks failed");else{let codegenResult=await runCodegenPhase({cwd});codegen=codegenResult.phase,labelKeys=codegenResult.labelKeys}let sync;return checks.errors.length>0?sync=skippedPhase("Labels","static checks failed"):labelKeys===null?sync=skippedPhase("Labels","label key scan failed"):sync=await runLabelsPhase({cwd,labelKeys,branchOverride:branchOverride2}),finalizeReport({phases:{checks,codegen,sync}})}__name(runValidate,"runValidate");async function runChecksPhase(opts){let{cwd,onWarning}=opts,[lintResult,routeResult,agentsResult,schemasResult,configResult,packageManagerResult,dependencyResult]=await Promise.allSettled([Promise.resolve().then(()=>lintProject({cwd})),Promise.resolve().then(()=>runRouteMetadataCheck({cwd})),Promise.resolve().then(()=>runAgentsCheck({cwd})),Promise.resolve().then(()=>validateSchemas({cwd})),Promise.resolve().then(()=>validateFimoConfig(cwd)),Promise.resolve().then(()=>resolvePackageManagerContract(cwd)),Promise.resolve().then(()=>inspectDependencyLifecycleScripts(cwd))]),errors=[],stats={};if(lintResult.status==="fulfilled"){stats.filesLinted=lintResult.value.filesChecked;for(let err of lintResult.value.errors)errors.push(authorError({rule:`lint/${err.rule}`,message:err.message,file:err.file,line:err.line,column:err.column}))}else errors.push(infraErrorFromException("lint",lintResult.reason));if(routeResult.status==="fulfilled"){if(routeResult.value){stats.routesChecked=routeResult.value.routesChecked;for(let message of routeResult.value.errors)errors.push(authorError({rule:"route-metadata",message}))}}else errors.push(infraErrorFromException("route-metadata",routeResult.reason));if(agentsResult.status==="fulfilled"?(Object.assign(stats,agentsResult.value.stats),errors.push(...agentsResult.value.errors)):errors.push(infraErrorFromException("agents",agentsResult.reason)),schemasResult.status==="fulfilled"){stats.schemasChecked=schemasResult.value.schemasChecked;for(let err of schemasResult.value.errors)errors.push(authorError({rule:err.rule,message:err.message,file:err.file}))}else errors.push(infraErrorFromException("schemas",schemasResult.reason));if(configResult.status==="fulfilled"){stats.configsChecked=Number(configResult.value.configChecked);for(let message of configResult.value.errors)errors.push(authorError({rule:"fimo-config",message}))}else errors.push(infraErrorFromException("fimo-config",configResult.reason));if(packageManagerResult.status==="fulfilled"){let contract=packageManagerResult.value;contract.status==="unresolved"&&errors.push(authorError({rule:`package-manager/${contract.violation}`,message:contract.message,file:"package.json"}))}else errors.push(infraErrorFromException("package-manager",packageManagerResult.reason));return dependencyResult.status==="fulfilled"?dependencyResult.value.status==="warning"?onWarning?.(dependencyResult.value.message):dependencyResult.value.status==="blocked"&&errors.push(authorError({rule:"dependency-build-scripts",message:`${dependencyResult.value.packageManager} blocked lifecycle scripts for: ${dependencyResult.value.packages.join(", ")}. Add these packages to the project's explicit build-script approval policy, reinstall, and re-run validation.`})):onWarning?.(`Dependency lifecycle-script approval check skipped: inspection failed (${dependencyResult.reason instanceof Error?dependencyResult.reason.message:String(dependencyResult.reason)}).`),{name:"Checks",ok:errors.length===0,errors,stats}}__name(runChecksPhase,"runChecksPhase");async function runAgentsCheck(opts){let{cwd}=opts,report=await runValidateAgents({cwd,json:!0}),errors=[];if(report.policy&&!report.policy.ok)for(let issue of report.policy.issues)errors.push(authorError({rule:"agents/policy",message:issue.message,file:issue.pointer}));for(let bundle of report.bundles)for(let phase of["parse","capabilities","composition","semantics"])for(let issue of bundle.phases[phase].issues)errors.push(authorError({rule:`agents/${phase}`,message:`${bundle.name}: ${issue.message}`,file:issue.pointer}));return{errors,stats:{agentsChecked:report.bundles.length}}}__name(runAgentsCheck,"runAgentsCheck");async function runRouteMetadataCheck(opts){let framework=await detectProjectFramework(opts.cwd);return framework&&framework.slug!=="react-router"?null:validateRouteMetadata({cwd:opts.cwd})}__name(runRouteMetadataCheck,"runRouteMetadataCheck");async function runCodegenPhase(opts){let{cwd}=opts,frameworkResult=detectProjectFramework(cwd),[schemasResult,formsResult,labelsResult]=await Promise.allSettled([frameworkResult.then(framework=>syncSchemas({cwd,framework:framework?.slug??null,verbose:!1})),frameworkResult.then(framework=>syncForms({cwd,framework:framework?.slug??null,verbose:!1})),Promise.resolve().then(()=>extractLabelKeys({cwd}))]),errors=[],stats={};schemasResult.status==="fulfilled"?(stats.schemasCreated=schemasResult.value.created,stats.schemasUpdated=schemasResult.value.updated,stats.schemasDeleted=schemasResult.value.deleted):errors.push(infraErrorFromException("sync-schemas",schemasResult.reason)),formsResult.status==="fulfilled"?(stats.formsCreated=formsResult.value.created,stats.formsUpdated=formsResult.value.updated,stats.formsDeleted=formsResult.value.deleted):errors.push(infraErrorFromException("sync-forms",formsResult.reason));let labelKeys=null;return labelsResult.status==="fulfilled"?(labelKeys=labelsResult.value,stats.labelsDeclared=labelKeys.length):errors.push(infraErrorFromException("extract-label-keys",labelsResult.reason)),{phase:{name:"Codegen",ok:errors.length===0,errors,stats},labelKeys}}__name(runCodegenPhase,"runCodegenPhase");async function runLabelsPhase(opts){let{cwd,labelKeys,branchOverride:branchOverride2}=opts;if(labelKeys.length===0)return{name:"Labels",ok:!0,errors:[],stats:{labelsDeclared:0,labelsMissing:0}};let ctx;try{ctx=await getProjectContext({cwd,branchOverride:branchOverride2})}catch(error){return rethrowCliAuthError(error),{name:"Labels",ok:!1,errors:[infraErrorFromException("load-project-settings",error)]}}let api=new FimoApiClient(loadConfig()).withBranch(ctx.branch),locale=getConfigServer(cwd).i18n?.defaultLocale??"en";try{let labels2=await loadLabelsForValidation({cwd,locale,projectId:ctx.projectId,loadAuthenticatedLabels:__name(()=>api.listLabels(ctx.projectId,locale),"loadAuthenticatedLabels")}),existingKeys=new Set(Object.keys(labels2)),missing=labelKeys.filter(label=>!existingKeys.has(label.key));return{name:"Labels",ok:missing.length===0,errors:missing.map(label=>authorError({rule:"labels/missing",message:`Missing label "${label.key}" for locale "${locale}". Run: fimo labels set ${JSON.stringify(label.key)} --locale ${locale} --value "...".`,file:label.file})),stats:{labelsDeclared:labelKeys.length,labelsMissing:missing.length}}}catch(error){return rethrowCliAuthError(error),{name:"Labels",ok:!1,errors:[infraErrorFromException("labels-check",error)]}}}__name(runLabelsPhase,"runLabelsPhase");function labelsToRecord(labels2){return Object.fromEntries(labels2.map(label=>[label.key,label.value??label.defaultValue??""]))}__name(labelsToRecord,"labelsToRecord");async function loadPublicTenantLabels(cwd,locale){let env=await readProjectEnv(cwd),apiUrl=env.VITE_API_URL;if(!apiUrl)return null;try{let url=new URL("/labels",apiUrl);url.searchParams.set("locale",locale);let headers=env.FIMO_ENV?{"X-Fimo-Branch":env.FIMO_ENV}:{},response=await fetchWithTimeout(url,3e4,headers);if(!response.ok)return null;let body=await response.json();return Array.isArray(body.data)?labelsToRecord(body.data):body.data?.labels??null}catch{return null}}__name(loadPublicTenantLabels,"loadPublicTenantLabels");async function loadLabelsForValidation({cwd,locale,projectId,loadAuthenticatedLabels}){let env=await readProjectEnv(cwd);if(!env.VITE_API_URL)return labelsToRecord(await loadAuthenticatedLabels());let labels2=await loadPublicTenantLabels(cwd,locale);if(labels2==null)throw new Error(`Could not read labels from project "${projectId}" env "${env.FIMO_ENV??"main"}"`);return labels2}__name(loadLabelsForValidation,"loadLabelsForValidation");async function fetchWithTimeout(url,timeoutMs,headers){let controller=new AbortController,timeout=setTimeout(()=>controller.abort(),timeoutMs);try{return await fetch(url,{signal:controller.signal,headers})}finally{clearTimeout(timeout)}}__name(fetchWithTimeout,"fetchWithTimeout");async function readProjectEnv(cwd){let values={...await readEnvFile(path29.join(cwd,".env")),...await readEnvFile(path29.join(cwd,".env.local"))};if(process.env.VITE_API_URL&&(values.VITE_API_URL=process.env.VITE_API_URL),process.env.FIMO_ENV&&(values.FIMO_ENV=process.env.FIMO_ENV),!values.VITE_API_URL){let derived=resolveLocalRuntimeEnv({cwd});derived&&(values.VITE_API_URL=derived.tenantApiUrl,values.FIMO_ENV??=derived.env)}return values}__name(readProjectEnv,"readProjectEnv");async function readEnvFile(filePath){try{let content2=await readFile3(filePath,"utf8"),values={};for(let line of content2.split(/\r?\n/)){let trimmed=line.trim();if(!trimmed||trimmed.startsWith("#"))continue;let index2=trimmed.indexOf("=");if(index2===-1)continue;let key=trimmed.slice(0,index2).trim(),value=trimmed.slice(index2+1).trim().replace(/^['"]|['"]$/g,"");values[key]=value}return values}catch{return{}}}__name(readEnvFile,"readEnvFile");async function deployCommand(options,cmd){if(process.env.FIMO_MIGRATION_NO_DEPLOY==="1"){ui.error({command:"deploy",code:"MIGRATION_DEPLOY_BLOCKED",message:"Deployment is disabled while a migration is running.",hint:"Finish local migration and QA first, then request deployment separately."});return}let cwd=resolveProjectCwd(options.cwd),local;try{local=loadProjectSettings(cwd)}catch{ui.error({command:"deploy",code:"NOT_IN_PROJECT",message:"You are not in a Fimo project.",hint:"Run `fimo create` to start one, or cd into a linked project."});return}if(!await isGitRepo(cwd)){ui.error({command:"deploy",code:"NOT_A_GIT_REPO",message:"Not a git repository."});return}let isPretty2=currentMode().format==="pretty";isPretty2&&mt(options.publish?"Deploying and publishing":"Deploying to preview");let branchOverride2=branchOverrideFromCommand(cmd),ctx=await getProjectContext({cwd,branchOverride:branchOverride2});if(isPretty2&&process.stderr.write(`${branchSourceBanner(ctx)}
1261
- `),ctx.readOnly){ui.error({command:"deploy",code:"ENV_READONLY",message:`Refusing to deploy to read-only env '${ctx.branch}'.`,hint:"Switch off the release/* tag or pass --env <writable-env>."});return}if(options.publish&&ctx.branch!==DEFAULT_BRANCH){ui.error({command:"deploy",code:"PUBLISH_REQUIRES_DEFAULT_ENV",message:`Refusing to --publish from env '${ctx.branch}'. Publish only runs from '${DEFAULT_BRANCH}'.`,hint:`Drop --publish to deploy a preview, or switch to '${DEFAULT_BRANCH}' first.`});return}let devFimoSelection;try{devFimoSelection=resolveDevFimoDependencyForDeploy(cwd)}catch(error){ui.error({command:"deploy",code:"DEV_FIMO_VERSION_MISSING",message:errorMessage(error)});return}await requireOperation("fimo.deploy",{projectId:ctx.projectId,branch:ctx.branch});let cfg=loadConfig(),api=new FimoApiClient(cfg).withBranch(ctx.branch),studioUrl=buildProjectPreviewUrl(cfg.webUrl,local.projectId,ctx.branch),previewUrl=buildPreviewUrl(cfg.webUrl,local.projectId,ctx.branch),previewEnabled=(await api.getProject(local.projectId)).previewEnabled!==!1,remoteSp=spinner("Checking the Fimo branch"),remote;try{remote=await api.getGitRemote(local.projectId,ctx.branch),await ensureFimoRemote(cwd,remote.url);let preparation=await prepareDeployCheckout({cwd,remoteBranch:remote.branch});remoteSp.succeed(preparation==="missing-remote"?`Fimo branch ${remote.branch} will be created by this deploy`:`Checkout ready for fimo/${remote.branch}`)}catch(error){if(remoteSp.fail("Checkout is not ready to deploy"),error instanceof BranchCheckoutError){ui.error({command:"deploy",code:error.code,message:error.message,hint:error.hint});return}rethrowCliAuthError(error),ui.error({command:"deploy",code:"ENV_GIT_PREFLIGHT_FAILED",message:`Could not compare this checkout with the Fimo branch: ${errorMessage(error)}`});return}let validateSp=spinner("Validating project"),report=await runValidate({cwd,branchOverride:branchOverride2});if(report.ok){validateSp.succeed("Validation passed");let packageManagerWarning=getPackageManagerPinWarning(cwd);packageManagerWarning&&ui.warn({command:"deploy",message:packageManagerWarning})}else if(options.force)validateSp.fail("Validation failed \u2014 continuing anyway (--force)"),ui.warn({command:"deploy",message:"Bypassing validation errors because --force was passed. The deploy may still fail later in the sandbox."});else{validateSp.fail("Validation failed"),ui.result({command:"deploy",data:{stage:"validate",report},render:__name(()=>formatReportHuman(report),"render")}),process.exitCode=report.exitCode;return}let devFimoDependency=null;try{devFimoDependency=prepareDevFimoDependencyForDeploy(cwd,devFimoSelection)}catch(error){ui.error({command:"deploy",code:"DEV_FIMO_VERSION_MISSING",message:errorMessage(error)});return}devFimoDependency&&isPretty2&&O2.info(`Deploying with fimo ${devFimoDependency.version}; restoring local dependency state after push.`);try{if(await hasUncommittedChanges(cwd)){let message;if(options.message!==void 0)message=options.message;else{assertInteractive('Pass -m "<message>" or commit your changes manually.',"deploy"),isPretty2&&O2.warn("You have uncommitted changes. Commit them before deploying.");let answer=await Ot({message:"Commit message",placeholder:"Deploy",defaultValue:"Deploy"});if(q(answer)){ui.info({command:"deploy",message:"Cancelled."});return}message=String(answer)}let commitSp=spinner("Committing pending changes");await runGit(["add","-A"],cwd),await runGit(["commit","-m",message],cwd),commitSp.succeed("Changes committed")}let remoteBranch=remote.branch,pushSp=spinner(`Pushing to fimo/${remoteBranch}`);try{await runGit(["push","fimo",`HEAD:${remoteBranch}`],cwd),pushSp.succeed("Pushed to Fimo")}catch(error){pushSp.fail("Push failed");let failure=classifyPushError(error);emitPushFailure(failure,remoteBranch);return}}finally{devFimoDependency?.restore()}let stepLabel="",stepStartedAt=0,stepSp=null,finalizeStep=__name((status="ok",failMessage)=>{if(!stepSp)return;let elapsed=((Date.now()-stepStartedAt)/1e3).toFixed(1);status==="ok"?stepSp.succeed(`${stepLabel} (${elapsed}s)`):stepSp.fail(failMessage??`${stepLabel} failed`),stepSp=null},"finalizeStep"),readiness,timings;try{let pull=await api.sandboxPull(local.projectId,({message})=>{finalizeStep("ok"),stepLabel=message,stepStartedAt=Date.now(),stepSp=spinner(message)},ctx.branch,{noRestart:options.restart===!1,wait:options.wait!==!1});readiness=pull.readiness,timings=pull.timings,finalizeStep("ok")}catch(error){if(rethrowCliAuthError(error,()=>finalizeStep("fail","Authentication required")),error instanceof SandboxReadinessError){finalizeStep("fail",`Preview did not become ready: ${errorMessage(error)}`),ui.error({command:"deploy",code:"PREVIEW_NOT_READY",message:`The revision was synced, but the preview never served a page: ${errorMessage(error)}`,hint:"Run `fimo logs` to see what the dev server reported, fix it, then deploy again. Pass --no-wait to deploy without this check."});return}finalizeStep("fail",`Sandbox sync failed: ${errorMessage(error)}`),ui.error({command:"deploy",code:"SANDBOX_SYNC_FAILED",message:`Sandbox sync failed: ${errorMessage(error)}`});return}await syncDisplayNameIfRenamed({cwd,projectId:local.projectId,api});let sandboxUrl=null,sandboxExpiresAt=null;if(previewEnabled)try{let preview=await api.getPreviewUrl(local.projectId,ctx.branch);sandboxUrl=preview.url,sandboxExpiresAt=preview.expiresAt}catch(error){isPretty2&&O2.warn(`Could not fetch preview URL: ${errorMessage(error)}`)}if(!options.publish){ui.result({command:"deploy",data:{project_id:local.projectId,branch:ctx.branch,preview_enabled:previewEnabled,preview_url:previewEnabled?previewUrl:null,sandbox_url:sandboxUrl,sandbox_expires_at:sandboxExpiresAt,studio_url:studioUrl,dashboard_url:studioUrl,published:!1,...readinessData(readiness,timings,ctx.branch)},render:__name(context=>renderDeployResult({previewUrl:previewEnabled?previewUrl:null,studioUrl,appUrl:null,previewEnabled,published:!1,readiness,timings,branch:ctx.branch},context),"render")});return}let publishSp=spinner("Publishing (this can take a few minutes)"),publicationId;try{publicationId=await api.publishProject(local.projectId)}catch(error){rethrowCliAuthError(error,()=>publishSp.fail("Authentication required")),publishSp.fail();let failedPublicationId=publicationIdFromError(error);ui.error({command:"deploy",code:"PUBLISH_FAILED",message:`Publish failed: ${errorMessage(error)}`,...failedPublicationId?{details:{publication_id:failedPublicationId},hint:`Run \`fimo publish logs ${failedPublicationId}\` for the build output that failed.`}:{}});return}publishSp.succeed("Published");let appUrl=null;try{appUrl=(await api.getProject(local.projectId)).appUrl}catch(error){isPretty2&&O2.warn(`Could not fetch published URL: ${errorMessage(error)}`)}ui.result({command:"deploy",data:{project_id:local.projectId,branch:ctx.branch,preview_enabled:previewEnabled,preview_url:previewEnabled?previewUrl:null,sandbox_url:sandboxUrl,sandbox_expires_at:sandboxExpiresAt,studio_url:studioUrl,dashboard_url:studioUrl,published:!0,publication_id:publicationId,app_url:appUrl,...readinessData(readiness,timings,ctx.branch)},render:__name(context=>renderDeployResult({previewUrl:previewEnabled?previewUrl:null,studioUrl,appUrl,previewEnabled,published:!0,readiness,timings,branch:ctx.branch},context),"render")})}__name(deployCommand,"deployCommand");function readinessData(readiness,timings,branch){return{readiness:readiness.status,readiness_reason:readiness.reason??null,readiness_branch:branch,readiness_env:branch,readiness_path:readiness.path??null,dependency_install_ms:timings.dependencyInstallMs,server_start_ms:timings.serverStartMs,readiness_ms:timings.readinessMs,total_sandbox_ms:timings.totalSandboxMs}}__name(readinessData,"readinessData");function renderDeployResult(result,context){let lines=[];return result.previewUrl&&lines.push(`Preview: ${terminalLink("Open preview",result.previewUrl,context.hyperlinks)}`),result.appUrl&&lines.push(`Live: ${terminalLink("Open site",result.appUrl,context.hyperlinks)}`),lines.push(`Studio: ${terminalLink("Open in Studio",result.studioUrl,context.hyperlinks)}`),lines.push(renderReadiness(result.readiness,result.branch)),lines.push(renderTimings(result.timings)),result.published?lines.push(result.appUrl?"Your site is live.":"Publish completed. Check Fimo for the live URL."):lines.push(result.previewEnabled?"Deployed to preview. Run `fimo deploy --publish` or `fimo publish` to publish a new version.":"Changes synced. Preview is disabled for this project."),lines.join(`
1262
- `)}__name(renderDeployResult,"renderDeployResult");function renderTimings(timings){let seconds=__name(durationMs=>`${(durationMs/1e3).toFixed(1)}s`,"seconds");return`Timing: install ${seconds(timings.dependencyInstallMs)}, server ${seconds(timings.serverStartMs)}, readiness ${seconds(timings.readinessMs)}, sandbox ${seconds(timings.totalSandboxMs)}.`}__name(renderTimings,"renderTimings");function renderReadiness(readiness,env){let seconds=(readiness.durationMs/1e3).toFixed(1);if(readiness.status==="ready")return`Readiness: ${env} served ${readiness.path??"the preview"} in ${seconds}s.`;switch(readiness.reason){case"preview_disabled":return`Readiness: not checked on ${env}; preview is disabled for this project.`;case"not_reported":return`Readiness: not checked on ${env}; this Fimo API does not report it.`;default:return`Readiness: skipped on ${env} (--no-wait). The preview is not known to serve this revision.`}}__name(renderReadiness,"renderReadiness");function emitPushFailure(failure,env){switch(failure.kind){case"non-fast-forward":ui.error({command:"deploy",code:"PUSH_NON_FAST_FORWARD",message:`The remote \`fimo/${env}\` has commits your local branch does not.`,hint:`Fix it manually, then re-run \`fimo deploy\`:
1261
+ `),ctx.readOnly){ui.error({command:"deploy",code:"ENV_READONLY",message:`Refusing to deploy to read-only env '${ctx.branch}'.`,hint:"Switch off the release/* tag or pass --env <writable-env>."});return}if(options.publish&&ctx.branch!==DEFAULT_BRANCH){ui.error({command:"deploy",code:"PUBLISH_REQUIRES_DEFAULT_ENV",message:`Refusing to --publish from env '${ctx.branch}'. Publish only runs from '${DEFAULT_BRANCH}'.`,hint:`Drop --publish to deploy a preview, or switch to '${DEFAULT_BRANCH}' first.`});return}let devFimoSelection;try{devFimoSelection=resolveDevFimoDependencyForDeploy(cwd)}catch(error){ui.error({command:"deploy",code:"DEV_FIMO_VERSION_MISSING",message:errorMessage(error)});return}await requireOperation("fimo.deploy",{projectId:ctx.projectId,branch:ctx.branch});let cfg=loadConfig(),api=new FimoApiClient(cfg).withBranch(ctx.branch),studioUrl=buildProjectPreviewUrl(cfg.webUrl,local.projectId,ctx.branch),previewUrl=buildPreviewUrl(cfg.webUrl,local.projectId,ctx.branch),previewEnabled=(await api.getProject(local.projectId)).previewEnabled!==!1,remoteSp=spinner("Checking the Fimo branch"),remote;try{remote=await api.getGitRemote(local.projectId,ctx.branch),await ensureFimoRemote(cwd,remote.url);let preparation=await prepareDeployCheckout({cwd,remoteBranch:remote.branch});remoteSp.succeed(preparation==="missing-remote"?`Fimo branch ${remote.branch} will be created by this deploy`:`Checkout ready for fimo/${remote.branch}`)}catch(error){if(remoteSp.fail("Checkout is not ready to deploy"),error instanceof BranchCheckoutError){ui.error({command:"deploy",code:error.code,message:error.message,hint:error.hint});return}rethrowCliAuthError(error),ui.error({command:"deploy",code:"ENV_GIT_PREFLIGHT_FAILED",message:`Could not compare this checkout with the Fimo branch: ${errorMessage(error)}`});return}let validateSp=spinner("Validating project"),report=await runValidate({cwd,branchOverride:branchOverride2});if(report.ok){validateSp.succeed("Validation passed");let packageManagerWarning=getPackageManagerPinWarning(cwd);packageManagerWarning&&ui.warn({command:"deploy",message:packageManagerWarning})}else if(options.force)validateSp.fail("Validation failed \u2014 continuing anyway (--force)"),ui.warn({command:"deploy",message:"Bypassing validation errors because --force was passed. The deploy may still fail later in the sandbox."});else{validateSp.fail("Validation failed"),ui.result({command:"deploy",data:{stage:"validate",report},render:__name(()=>formatReportHuman(report),"render")}),process.exitCode=report.exitCode;return}let devFimoDependency=null;try{devFimoDependency=prepareDevFimoDependencyForDeploy(cwd,devFimoSelection)}catch(error){ui.error({command:"deploy",code:"DEV_FIMO_VERSION_MISSING",message:errorMessage(error)});return}devFimoDependency&&isPretty2&&O2.info(`Deploying with fimo ${devFimoDependency.version}; restoring local dependency state after push.`);try{if(await hasUncommittedChanges(cwd)){let message;if(options.message!==void 0)message=options.message;else{assertInteractive('Pass -m "<message>" or commit your changes manually.',"deploy"),isPretty2&&O2.warn("You have uncommitted changes. Commit them before deploying.");let answer=await Ot({message:"Commit message",placeholder:"Deploy",defaultValue:"Deploy"});if(q(answer)){ui.info({command:"deploy",message:"Cancelled."});return}message=String(answer)}let commitSp=spinner("Committing pending changes");await runGit(["add","-A"],cwd),await runGit(["commit","-m",message],cwd),commitSp.succeed("Changes committed")}let remoteBranch=remote.branch,pushSp=spinner(`Pushing to fimo/${remoteBranch}`);try{await runGit(["push","fimo",`HEAD:${remoteBranch}`],cwd),pushSp.succeed("Pushed to Fimo")}catch(error){pushSp.fail("Push failed");let failure=classifyPushError(error);emitPushFailure(failure,remoteBranch);return}}finally{devFimoDependency?.restore()}let stepLabel="",stepStartedAt=0,stepSp=null,finalizeStep=__name((status="ok",failMessage)=>{if(!stepSp)return;let elapsed=((Date.now()-stepStartedAt)/1e3).toFixed(1);status==="ok"?stepSp.succeed(`${stepLabel} (${elapsed}s)`):stepSp.fail(failMessage??`${stepLabel} failed`),stepSp=null},"finalizeStep"),readiness,timings;try{let pull=await api.sandboxPull(local.projectId,({message})=>{finalizeStep("ok"),stepLabel=message,stepStartedAt=Date.now(),stepSp=spinner(message)},ctx.branch,{noRestart:options.restart===!1,wait:options.wait!==!1});readiness=pull.readiness,timings=pull.timings,finalizeStep("ok")}catch(error){if(rethrowCliAuthError(error,()=>finalizeStep("fail","Authentication required")),error instanceof SandboxReadinessError){finalizeStep("fail",`Preview did not become ready: ${errorMessage(error)}`),ui.error({command:"deploy",code:"PREVIEW_NOT_READY",message:`The revision was synced, but the preview never became ready: ${errorMessage(error)}`,hint:"Run `fimo logs` to see what the dev server reported, fix it, then deploy again. Pass --no-wait to deploy without this check."});return}finalizeStep("fail",`Sandbox sync failed: ${errorMessage(error)}`),ui.error({command:"deploy",code:"SANDBOX_SYNC_FAILED",message:`Sandbox sync failed: ${errorMessage(error)}`});return}await syncDisplayNameIfRenamed({cwd,projectId:local.projectId,api});let sandboxUrl=null,sandboxExpiresAt=null;if(previewEnabled)try{let preview=await api.getPreviewUrl(local.projectId,ctx.branch);sandboxUrl=preview.url,sandboxExpiresAt=preview.expiresAt}catch(error){isPretty2&&O2.warn(`Could not fetch preview URL: ${errorMessage(error)}`)}if(!options.publish){ui.result({command:"deploy",data:{project_id:local.projectId,branch:ctx.branch,preview_enabled:previewEnabled,preview_url:previewEnabled?previewUrl:null,sandbox_url:sandboxUrl,sandbox_expires_at:sandboxExpiresAt,studio_url:studioUrl,dashboard_url:studioUrl,published:!1,...readinessData(readiness,timings,ctx.branch)},render:__name(context=>renderDeployResult({previewUrl:previewEnabled?previewUrl:null,studioUrl,appUrl:null,previewEnabled,published:!1,readiness,timings,branch:ctx.branch},context),"render")});return}let publishSp=spinner("Publishing (this can take a few minutes)"),publicationId;try{publicationId=await api.publishProject(local.projectId)}catch(error){rethrowCliAuthError(error,()=>publishSp.fail("Authentication required")),publishSp.fail();let failedPublicationId=publicationIdFromError(error);ui.error({command:"deploy",code:"PUBLISH_FAILED",message:`Publish failed: ${errorMessage(error)}`,...failedPublicationId?{details:{publication_id:failedPublicationId},hint:`Run \`fimo publish logs ${failedPublicationId}\` for the build output that failed.`}:{}});return}publishSp.succeed("Published");let appUrl=null;try{appUrl=(await api.getProject(local.projectId)).appUrl}catch(error){isPretty2&&O2.warn(`Could not fetch published URL: ${errorMessage(error)}`)}ui.result({command:"deploy",data:{project_id:local.projectId,branch:ctx.branch,preview_enabled:previewEnabled,preview_url:previewEnabled?previewUrl:null,sandbox_url:sandboxUrl,sandbox_expires_at:sandboxExpiresAt,studio_url:studioUrl,dashboard_url:studioUrl,published:!0,publication_id:publicationId,app_url:appUrl,...readinessData(readiness,timings,ctx.branch)},render:__name(context=>renderDeployResult({previewUrl:previewEnabled?previewUrl:null,studioUrl,appUrl,previewEnabled,published:!0,readiness,timings,branch:ctx.branch},context),"render")})}__name(deployCommand,"deployCommand");function readinessData(readiness,timings,branch){let skipped=readiness.status==="skipped";return{readiness:readiness.status,readiness_reason:readiness.reason??null,readiness_branch:branch,readiness_env:branch,readiness_path:readiness.path??null,readiness_depth:skipped?"none":readiness.depth??null,readiness_modules:skipped?0:readiness.graph?.modules??null,dependency_install_ms:timings.dependencyInstallMs,server_start_ms:timings.serverStartMs,readiness_ms:timings.readinessMs,total_sandbox_ms:timings.totalSandboxMs}}__name(readinessData,"readinessData");function renderDeployResult(result,context){let lines=[];return result.previewUrl&&lines.push(`Preview: ${terminalLink("Open preview",result.previewUrl,context.hyperlinks)}`),result.appUrl&&lines.push(`Live: ${terminalLink("Open site",result.appUrl,context.hyperlinks)}`),lines.push(`Studio: ${terminalLink("Open in Studio",result.studioUrl,context.hyperlinks)}`),lines.push(renderReadiness(result.readiness,result.branch)),lines.push(renderTimings(result.timings)),result.published?lines.push(result.appUrl?"Your site is live.":"Publish completed. Check Fimo for the live URL."):lines.push(result.previewEnabled?"Deployed to preview. Run `fimo deploy --publish` or `fimo publish` to publish a new version.":"Changes synced. Preview is disabled for this project."),lines.join(`
1262
+ `)}__name(renderDeployResult,"renderDeployResult");function renderTimings(timings){let seconds=__name(durationMs=>`${(durationMs/1e3).toFixed(1)}s`,"seconds");return`Timing: install ${seconds(timings.dependencyInstallMs)}, server ${seconds(timings.serverStartMs)}, readiness ${seconds(timings.readinessMs)}, sandbox ${seconds(timings.totalSandboxMs)}.`}__name(renderTimings,"renderTimings");function renderReadiness(readiness,env){let seconds=(readiness.durationMs/1e3).toFixed(1);if(readiness.status==="ready"){let page=`Readiness: ${env} served ${readiness.path??"the preview"}`;return readiness.graph?`${page} and verified ${readiness.graph.modules} public requests in ${seconds}s.`:`${page} in ${seconds}s.`}switch(readiness.reason){case"preview_disabled":return`Readiness: not checked on ${env}; preview is disabled for this project.`;case"not_reported":return`Readiness: not checked on ${env}; this Fimo API does not report it.`;default:return`Readiness: skipped on ${env} (--no-wait). The preview is not known to serve this revision.`}}__name(renderReadiness,"renderReadiness");function emitPushFailure(failure,env){switch(failure.kind){case"non-fast-forward":ui.error({command:"deploy",code:"PUSH_NON_FAST_FORWARD",message:`The remote \`fimo/${env}\` has commits your local branch does not.`,hint:`Fix it manually, then re-run \`fimo deploy\`:
1263
1263
  1. git pull --rebase fimo ${env}
1264
1264
  2. resolve any conflicts, then \`git add\` + \`git rebase --continue\`
1265
1265
  3. fimo deploy`});break;case"protected":ui.error({command:"deploy",code:"PUSH_PROTECTED_BRANCH",message:`Push to \`${env}\` was rejected \u2014 you don't have permission to push to this branch.`,hint:"It is likely protected (e.g. `prod` is updated by publishing, not by pushing). Push to a writable env, or publish with `fimo deploy --publish`."});break;case"auth":ui.error({command:"deploy",code:"PUSH_AUTH_FAILED",message:"Authentication failed while pushing.",hint:"Run `fimo login` and try again."});break;case"network":ui.error({command:"deploy",code:"PUSH_NETWORK_ERROR",message:"Network error while pushing.",hint:"Check your connection and try `fimo deploy` again."});break;default:ui.error({command:"deploy",code:"PUSH_FAILED",message:`Push failed:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "2.2.0-staging.1",
3
+ "version": "2.2.0-staging.3",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo projects",
5
5
  "keywords": [
6
6
  "astro-component"
@@ -184,12 +184,12 @@
184
184
  "devDependencies": {
185
185
  "@clack/core": "^1.2.0",
186
186
  "@clack/prompts": "^1.2.0",
187
- "@fimo/agents-bundle": "2.2.0-staging.1",
188
- "@fimo/api-contracts": "2.2.0-staging.1",
189
- "@fimo/cli-kit": "2.2.0-staging.1",
190
- "@fimo/framework-detect": "2.2.0-staging.1",
191
- "@fimo/routes": "2.2.0-staging.1",
192
- "@fimo/tsconfig": "2.2.0-staging.1",
187
+ "@fimo/agents-bundle": "2.2.0-staging.3",
188
+ "@fimo/api-contracts": "2.2.0-staging.3",
189
+ "@fimo/cli-kit": "2.2.0-staging.3",
190
+ "@fimo/framework-detect": "2.2.0-staging.3",
191
+ "@fimo/routes": "2.2.0-staging.3",
192
+ "@fimo/tsconfig": "2.2.0-staging.3",
193
193
  "@types/node": "22.18.6",
194
194
  "agent-install": "^0.0.5",
195
195
  "astro": "^7.1.6",
@@ -9,8 +9,8 @@
9
9
  "check": "astro sync && astro check"
10
10
  },
11
11
  "dependencies": {
12
- "fimo": "2.2.0-staging.1",
13
- "fimo-astro": "2.2.0-staging.1"
12
+ "fimo": "2.2.0-staging.3",
13
+ "fimo-astro": "2.2.0-staging.3"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@astrojs/check": "^0.9.10",
@@ -12,9 +12,9 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@tanstack/react-query": "^5.80.6",
15
- "fimo": "2.2.0-staging.1",
16
- "fimo-next": "2.2.0-staging.1",
17
- "fimo-react": "2.2.0-staging.1",
15
+ "fimo": "2.2.0-staging.3",
16
+ "fimo-next": "2.2.0-staging.3",
17
+ "fimo-react": "2.2.0-staging.3",
18
18
  "next": "^16.3.0",
19
19
  "react": "^19.2.7",
20
20
  "react-dom": "^19.2.7"
@@ -21,10 +21,10 @@
21
21
  "cmdk": "^1.1.1",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "2.2.0-staging.1",
25
- "fimo-react": "2.2.0-staging.1",
26
- "fimo-react-router": "2.2.0-staging.1",
27
- "fimo-vite": "2.2.0-staging.1",
24
+ "fimo": "2.2.0-staging.3",
25
+ "fimo-react": "2.2.0-staging.3",
26
+ "fimo-react-router": "2.2.0-staging.3",
27
+ "fimo-vite": "2.2.0-staging.3",
28
28
  "input-otp": "^1.4.2",
29
29
  "isbot": "^5",
30
30
  "lucide-react": "^0.577.0",
@@ -11,8 +11,8 @@
11
11
  "prepare": "svelte-kit sync"
12
12
  },
13
13
  "dependencies": {
14
- "fimo": "2.2.0-staging.1",
15
- "fimo-sveltekit": "2.2.0-staging.1"
14
+ "fimo": "2.2.0-staging.3",
15
+ "fimo-sveltekit": "2.2.0-staging.3"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@sveltejs/kit": "^2.70.2",
@@ -11,10 +11,10 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@tanstack/react-query": "^5.80.6",
14
- "fimo": "2.2.0-staging.1",
15
- "fimo-react": "2.2.0-staging.1",
16
- "fimo-react-router": "2.2.0-staging.1",
17
- "fimo-vite": "2.2.0-staging.1",
14
+ "fimo": "2.2.0-staging.3",
15
+ "fimo-react": "2.2.0-staging.3",
16
+ "fimo-react-router": "2.2.0-staging.3",
17
+ "fimo-vite": "2.2.0-staging.3",
18
18
  "react": "^19.2.7",
19
19
  "react-dom": "^19.2.7",
20
20
  "react-router": "^8.3.0"