fimo 2.9.0-staging.7 → 2.9.0-staging.8

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.
@@ -63,7 +63,7 @@ fimo vars unset STRIPE_SECRET_KEY
63
63
  - Private variables cannot use browser prefixes (`VITE_`, `PUBLIC_`, `NEXT_PUBLIC_`, `NUXT_PUBLIC_`). Read them only from server code.
64
64
  - Set one value per Environment: a test key for preview, the live key for production (`--env production`).
65
65
  - Public or private is chosen when the variable is created. To switch, unset it and add it again.
66
- - A changed or removed variable applies on the next deploy: run `fimo deploy` for previews (with no new commit, it restarts the preview and rebuilds the hosted preview when variables changed) and `fimo publish` for the live site. After changing variables for the user, offer that redeploy.
66
+ - A changed or removed Preview or custom Environment variable rebuilds that Environment's hosted previews on its own. The Studio preview picks it up on the next `fimo deploy`, even with no new commit. A Production variable reaches the live site only on `fimo publish`: after changing one for the user, offer to publish.
67
67
  - Names that control processes (`PATH`, `NODE_ENV`, `NODE_OPTIONS`, `HTTPS_PROXY`, `GIT_*`, `NPM_CONFIG_*` and similar) are refused for new private variables, and a public variable with such a name never reaches the site's processes or the `.env.local` written by `fimo vars pull`.
68
68
 
69
69
  ## Secrets
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "bundled": true,
3
3
  "bundler": "esbuild",
4
- "bundledAt": "2026-10-22T09:31:46.002Z",
4
+ "bundledAt": "2026-10-22T11:24:59.103Z",
5
5
  "cliVersion": "2.8.0",
6
6
  "external": [
7
7
  "oxc-parser",
package/dist/cli/index.js CHANGED
@@ -2770,7 +2770,7 @@ Run \`fimo mcp <command> --help\` for command-specific help.
2770
2770
  `)}
2771
2771
  `,changed:!0,created:!0}}__name(mergeManagedEnvBlock,"mergeManagedEnvBlock");function renderBlock(entries2,spec,notes){return[spec.start,...spec.header,...Object.entries(entries2).map(([key,value])=>`${key}=${quoteEnvValue(value)}`),...notes.map(note=>`# ${note}`),spec.end]}__name(renderBlock,"renderBlock");function keysOutsideManagedBlock(existing,spec){let keys=new Set,inside=!1;for(let line of existing.replace(/\r\n/g,`
2772
2772
  `).split(`
2773
- `)){let trimmed=line.trim();if(trimmed===spec.start)inside=!0;else if(trimmed===spec.end)inside=!1;else if(!inside){let match=/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(trimmed);match&&keys.add(match[1])}}return keys}__name(keysOutsideManagedBlock,"keysOutsideManagedBlock");function quoteEnvValue(value){return/^[A-Za-z0-9_./:@-]*$/.test(value)?value:JSON.stringify(value)}__name(quoteEnvValue,"quoteEnvValue");init_project_context();init_project2();var PRODUCTION={key:PRODUCTION_ENVIRONMENT_KEY,name:"Production"},PREVIEW={key:PREVIEW_ENVIRONMENT_KEY,name:"Preview"},ENV_OPTION="production, preview, or a custom Environment name or id (default: the Environment of the current branch)";function registerProjectSecretsCommands(program2){let vars=program2.command("vars").description("Manage site variables");vars.command("list").description("List site variables").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((opts,command)=>listCommand3("variable",opts,command)),vars.command("add <key> [value]").description("Add a site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Variable value").option("--private","Keep the value server-only: write-only, never pulled into local env files").action((key,value,opts,command)=>writeCommand("variable","add",key,opts.value??value,opts,command)),vars.command("update <key> [value]").description("Update an existing site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Variable value").action((key,value,opts,command)=>writeCommand("variable","update",key,opts.value??value,opts,command)),vars.command("unset <key>").alias("remove").description("Delete a site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((key,opts,command)=>unsetCommand("variable",key,opts,command)),vars.command("pull [file]").description("Write public site variables to a local env file").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((file,opts,command)=>pullVarsCommand(file,opts,command));let secrets=program2.command("secrets").description("Manage site secrets");secrets.command("list").description("List site secrets without revealing values").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((opts,command)=>listCommand3("secret",opts,command)),secrets.command("add <key> [value]").description("Add a site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Secret value (prefer --stdin in shells that record history)").action((key,value,opts,command)=>writeCommand("secret","add",key,opts.value??value,opts,command)),secrets.command("update <key> [value]").description("Update an existing site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Secret value (prefer --stdin in shells that record history)").action((key,value,opts,command)=>writeCommand("secret","update",key,opts.value??value,opts,command)),secrets.command("unset <key>").alias("remove").description("Delete a site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((key,opts,command)=>unsetCommand("secret",key,opts,command))}__name(registerProjectSecretsCommands,"registerProjectSecretsCommands");function commandName(kind,verb){return`${kind==="secret"?"secrets":"vars"} ${verb}`}__name(commandName,"commandName");async function listCommand3(kind,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command),rows=await fimo.execute("secrets.list",{projectId,kind,environment:environment.key});if(rows.length===0){ui.info({command:commandName(kind,"list"),message:`No site ${kind==="secret"?"secrets":"variables"} set in ${environment.name}.`,jsonData:{environment:environment.key}});return}ui.table({command:commandName(kind,"list"),headline:`${kind==="secret"?"Secrets":"Variables"} in ${environment.name}`,jsonData:{environment:environment.key},columns:[{key:"key",label:"KEY"},{key:"value",label:kind==="secret"?"VALUE (masked)":"VALUE"},...kind==="variable"?[{key:"exposure",label:"EXPOSURE"}]:[]],rows:rows.map(row2=>({key:row2.key,value:row2.value??row2.maskedValue??"",...kind==="variable"&&{exposure:row2.exposure}}))})}__name(listCommand3,"listCommand");async function writeCommand(kind,operation,key,valueArg,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command),value=opts.stdin||valueArg===void 0?await readStdinValue4(kind):valueArg,input={projectId,key,kind,value,environment:environment.key};operation==="add"?await fimo.execute("secrets.create",{...input,...opts.private&&{exposure:"private"}}):await fimo.execute("secrets.update",input);let envLocal=kind==="variable"&&environment.key!==PRODUCTION_ENVIRONMENT_KEY?await syncDefaultLocalVars(fimo,projectId,environment.key,opts):null,action=operation==="add"?"Added":"Updated";warnUntilPublished(kind,environment.key,commandName(kind,operation)),ui.ok({command:commandName(kind,operation),headline:`${action} site ${kind==="secret"?"secret":opts.private?"private variable":"variable"} ${key} in ${environment.name}`,details:{project_id:projectId,key,kind,...opts.private&&{exposure:"private"},environment:environment.key,...envLocal&&{env_local:envLocal}},...kind==="variable"&&{hint:redeployHint(environment.key)}})}__name(writeCommand,"writeCommand");async function unsetCommand(kind,key,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command);await fimo.execute("secrets.delete",{projectId,key,kind,environment:environment.key});let envLocal=kind==="variable"&&environment.key!==PRODUCTION_ENVIRONMENT_KEY?await syncDefaultLocalVars(fimo,projectId,environment.key,opts):null;warnUntilPublished(kind,environment.key,commandName(kind,"unset")),ui.ok({command:commandName(kind,"unset"),headline:`Removed site ${kind==="secret"?"secret":"variable"} ${key} from ${environment.name}`,details:{project_id:projectId,key,kind,environment:environment.key,...envLocal&&{env_local:envLocal}},...kind==="variable"&&{hint:redeployHint(environment.key)}})}__name(unsetCommand,"unsetCommand");async function pullVarsCommand(file,opts,command){let projectRoot=resolveProjectCwd(opts.cwd),{fimo,environment,projectId}=await resolveScope2(opts,command),result=await writePulledVars(fimo,projectRoot,projectId,environment.key,file??".env.local");ui.ok({command:"vars pull",headline:`Wrote ${result.written} ${environment.name} variable${result.written===1?"":"s"} to ${result.path}`,details:{project_id:projectId,environment:environment.key,file:result.path,written:result.written}})}__name(pullVarsCommand,"pullVarsCommand");async function syncDefaultLocalVars(fimo,projectId,environment,opts){let projectRoot=resolveProjectCwd(opts.cwd);try{if(loadProjectSettings(projectRoot).projectId!==projectId)return null}catch{return null}return writePulledVars(fimo,projectRoot,projectId,environment,".env.local")}__name(syncDefaultLocalVars,"syncDefaultLocalVars");async function writePulledVars(fimo,projectRoot,projectId,environment,file){let rows=await fimo.execute("secrets.list",{projectId,kind:"variable",environment}),target=path42.resolve(projectRoot,file),existing=fs42.existsSync(target)?fs42.readFileSync(target,"utf8"):"",body=mergeEnvFile(existing,rows);return fs42.writeFileSync(target,body),{path:target,written:rows.filter(isWrittenLocally).length}}__name(writePulledVars,"writePulledVars");function redeployHint(environment){return environment===PRODUCTION_ENVIRONMENT_KEY?"Applies to the live site on the next `fimo publish`.":"Applies to previews on the next `fimo deploy`."}__name(redeployHint,"redeployHint");function warnUntilPublished(kind,environment,command){kind==="variable"&&environment===PRODUCTION_ENVIRONMENT_KEY&&ui.warn({command,message:"The live site keeps its current variables until you publish again: run `fimo publish`."})}__name(warnUntilPublished,"warnUntilPublished");function resolveProjectId7(opts){if(opts.project)return opts.project;let cwd=resolveProjectCwd(opts.cwd);return loadProjectSettings(cwd).projectId}__name(resolveProjectId7,"resolveProjectId");async function resolveScope2(opts,command){let fimo=createCliFimoClient(loadConfig()),projectId=resolveProjectId7(opts);if(opts.env!==void 0)return{fimo,projectId,environment:await resolveEnvOption(fimo,projectId,opts.env)};let override=branchOverrideFromCommand(command);return override&&ui.warn({command:command?.name()??"vars",message:"--branch is deprecated for vars and secrets. Pass --env production, --env preview or --env <custom Environment name>."}),{fimo,projectId,environment:await environmentOfBranch(fimo,projectId,override??await currentBranch3(opts))}}__name(resolveScope2,"resolveScope");async function currentBranch3(opts){try{return(await getProjectContext({cwd:opts.cwd})).branch}catch(error){if(!opts.project)throw error;return DEFAULT_BRANCH}}__name(currentBranch3,"currentBranch");async function listEnvironments(fimo,projectId){let custom=(await fimo.execute("environments.list",{projectId})).filter(environment=>environment.kind==="custom").map(environment=>({key:environment.id,name:environment.name}));return[PRODUCTION,PREVIEW,...custom]}__name(listEnvironments,"listEnvironments");async function environmentOfBranch(fimo,projectId,branch){if(branch===PRODUCTION_BRANCH)return PRODUCTION;let{environment}=await fimo.execute("environments.resolve",{projectId,branch});return environment===PREVIEW_ENVIRONMENT_KEY?PREVIEW:environment===PRODUCTION_ENVIRONMENT_KEY?PRODUCTION:(await listEnvironments(fimo,projectId)).find(candidate=>candidate.key===environment)??{key:environment,name:environment}}__name(environmentOfBranch,"environmentOfBranch");async function resolveEnvOption(fimo,projectId,value){let trimmed=value.trim();if(!trimmed)throw new Error("--env needs an Environment: production, preview, or a custom Environment name or id.");let wanted=trimmed.toLowerCase();if(wanted===PRODUCTION_ENVIRONMENT_KEY)return PRODUCTION;if(wanted===PREVIEW_ENVIRONMENT_KEY)return PREVIEW;let environments=await listEnvironments(fimo,projectId),match=environments.find(environment=>environment.key.toLowerCase()===wanted)??environments.find(environment=>environment.name===trimmed);if(match)return match;let sameName=environments.filter(environment=>environment.name.toLowerCase()===wanted);if(sameName.length>1){let candidates=sameName.map(environment=>`${environment.name} (${environment.key})`).join(", ");throw new Error(`'${value}' matches several Environments: ${candidates}. Pass the exact name or the id.`)}if(sameName.length===0){let names=environments.map(environment=>environment.name).join(", ");throw new Error(`No Environment named '${value}'. This site has: ${names}.`)}return sameName[0]}__name(resolveEnvOption,"resolveEnvOption");async function readStdinValue4(kind){if(process.stdin.isTTY)throw new Error(`Pass a ${kind} value or pipe one with --stdin.`);let chunks=[];for await(let chunk of process.stdin)chunks.push(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk));return Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/,"")}__name(readStdinValue4,"readStdinValue");var VARS_BLOCK={start:"# fimo:vars:start",end:"# fimo:vars:end",header:["# Generated by fimo vars pull. Do not put secrets in this block."]};function isWrittenLocally(row2){return row2.exposure==="public"&&!isProcessControlEnvKey(row2.key)}__name(isWrittenLocally,"isWrittenLocally");function mergeEnvFile(existing,rows){let entries2=Object.fromEntries(rows.filter(isWrittenLocally).map(row2=>[row2.key,row2.value??""])),setLocally=keysOutsideManagedBlock(existing,VARS_BLOCK),notes=rows.filter(row2=>!isWrittenLocally(row2)&&!setLocally.has(row2.key)).map(row2=>row2.exposure==="private"?`${row2.key} is a private variable: add a local value outside this block`:`${row2.key} controls the shell or toolchain, so Fimo does not apply it: rename the variable`);return mergeManagedEnvBlock(existing,entries2,VARS_BLOCK,notes).content}__name(mergeEnvFile,"mergeEnvFile");import fs43 from"node:fs";init_dist();init_auth();init_config();init_sdk_transport();init_project_services();init_project2();function resolveCwd2(options){return resolveProjectCwd(options.cwd)}__name(resolveCwd2,"resolveCwd");function readLocalConfig(options){let cwd=resolveCwd2(options);try{return loadProjectSettings(cwd)}catch{return null}}__name(readLocalConfig,"readLocalConfig");function resolveProjectId8(argv,options,command){if(argv)return argv;let local=readLocalConfig(options);return local?local.projectId:(ui.error({command,code:"NOT_IN_PROJECT",message:"No site ID and no Fimo site link found in the current directory.",hint:"Pass a site ID explicitly, or cd into a linked site."}),null)}__name(resolveProjectId8,"resolveProjectId");async function projectsListCommand(options){let cfg=loadConfig(),fimo=createCliFimoClient(cfg),creds=requireAccountCredentials(cfg),organizationId=options.org??creds?.activeOrganization?.id;if(!organizationId){ui.error({command:"projects list",code:"NO_ORGANIZATION_SPECIFIED",message:"No organization specified and no active organization set.",hint:"Run `fimo switch` or pass --org <id>."});return}let{data:projects2}=await fimo.execute("projects.list",{organizationId});if(projects2.length===0){ui.info({command:"projects list",message:"No sites in this organization yet."});return}ui.table({command:"projects list",columns:[{key:"published",label:"PUB"},{key:"id",label:"ID"},{key:"name",label:"NAME"},{key:"displayName",label:"DISPLAY NAME"}],rows:projects2.map(p2=>({published:p2.appUrl?"\u{1F7E2}":"\u26AA",id:p2.id,name:p2.name,displayName:p2.displayName??""}))})}__name(projectsListCommand,"projectsListCommand");async function projectsUnclaimedCommand(){let cfg=loadConfig(),entries2=readUnclaimedIndex(cfg);if(entries2.length===0){ui.info({command:"projects unclaimed",message:"No projects were created without an account on this machine.",jsonData:{projects:[]}});return}let claims=await createUnclaimedProjectsService(cfg).claimStates(entries2.map(entry=>claimSecretFromUrl(entry.claimUrl))),projects2=entries2.flatMap((entry,index)=>{let claim=claims[index];return claim?.state!=="claimable"?[]:[{project_id:entry.projectId,name:entry.name,dir:entry.dir,state:claim.state,expires_at:new Date(claim.expiresAt??entry.expiresAt).toISOString(),claim_url:entry.claimUrl}]});if(projects2.length===0){ui.info({command:"projects unclaimed",message:"No site created on this machine is waiting for a claim.",jsonData:{projects:[]}});return}ui.result({command:"projects unclaimed",data:{projects:projects2},render:__name(()=>projects2.map(project=>[`${project.name} claim by ${formatClaimDeadline(project.expires_at)}`,` ${project.dir}`,` ${project.claim_url}`].join(`
2773
+ `)){let trimmed=line.trim();if(trimmed===spec.start)inside=!0;else if(trimmed===spec.end)inside=!1;else if(!inside){let match=/^(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=/.exec(trimmed);match&&keys.add(match[1])}}return keys}__name(keysOutsideManagedBlock,"keysOutsideManagedBlock");function quoteEnvValue(value){return/^[A-Za-z0-9_./:@-]*$/.test(value)?value:JSON.stringify(value)}__name(quoteEnvValue,"quoteEnvValue");init_project_context();init_project2();var PRODUCTION={key:PRODUCTION_ENVIRONMENT_KEY,name:"Production"},PREVIEW={key:PREVIEW_ENVIRONMENT_KEY,name:"Preview"},ENV_OPTION="production, preview, or a custom Environment name or id (default: the Environment of the current branch)";function registerProjectSecretsCommands(program2){let vars=program2.command("vars").description("Manage site variables");vars.command("list").description("List site variables").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((opts,command)=>listCommand3("variable",opts,command)),vars.command("add <key> [value]").description("Add a site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Variable value").option("--private","Keep the value server-only: write-only, never pulled into local env files").action((key,value,opts,command)=>writeCommand("variable","add",key,opts.value??value,opts,command)),vars.command("update <key> [value]").description("Update an existing site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Variable value").action((key,value,opts,command)=>writeCommand("variable","update",key,opts.value??value,opts,command)),vars.command("unset <key>").alias("remove").description("Delete a site variable").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((key,opts,command)=>unsetCommand("variable",key,opts,command)),vars.command("pull [file]").description("Write public site variables to a local env file").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((file,opts,command)=>pullVarsCommand(file,opts,command));let secrets=program2.command("secrets").description("Manage site secrets");secrets.command("list").description("List site secrets without revealing values").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((opts,command)=>listCommand3("secret",opts,command)),secrets.command("add <key> [value]").description("Add a site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Secret value (prefer --stdin in shells that record history)").action((key,value,opts,command)=>writeCommand("secret","add",key,opts.value??value,opts,command)),secrets.command("update <key> [value]").description("Update an existing site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").option("--stdin","Read the value from stdin").option("--value <value>","Secret value (prefer --stdin in shells that record history)").action((key,value,opts,command)=>writeCommand("secret","update",key,opts.value??value,opts,command)),secrets.command("unset <key>").alias("remove").description("Delete a site secret").option("--project <id>","Site id (defaults to the locally linked site)").option("--env <environment>",ENV_OPTION).option("-C, --cwd <dir>","Site directory").action((key,opts,command)=>unsetCommand("secret",key,opts,command))}__name(registerProjectSecretsCommands,"registerProjectSecretsCommands");function commandName(kind,verb){return`${kind==="secret"?"secrets":"vars"} ${verb}`}__name(commandName,"commandName");async function listCommand3(kind,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command),rows=await fimo.execute("secrets.list",{projectId,kind,environment:environment.key});if(rows.length===0){ui.info({command:commandName(kind,"list"),message:`No site ${kind==="secret"?"secrets":"variables"} set in ${environment.name}.`,jsonData:{environment:environment.key}});return}ui.table({command:commandName(kind,"list"),headline:`${kind==="secret"?"Secrets":"Variables"} in ${environment.name}`,jsonData:{environment:environment.key},columns:[{key:"key",label:"KEY"},{key:"value",label:kind==="secret"?"VALUE (masked)":"VALUE"},...kind==="variable"?[{key:"exposure",label:"EXPOSURE"}]:[]],rows:rows.map(row2=>({key:row2.key,value:row2.value??row2.maskedValue??"",...kind==="variable"&&{exposure:row2.exposure}}))})}__name(listCommand3,"listCommand");async function writeCommand(kind,operation,key,valueArg,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command),value=opts.stdin||valueArg===void 0?await readStdinValue4(kind):valueArg,input={projectId,key,kind,value,environment:environment.key};operation==="add"?await fimo.execute("secrets.create",{...input,...opts.private&&{exposure:"private"}}):await fimo.execute("secrets.update",input);let envLocal=kind==="variable"&&environment.key!==PRODUCTION_ENVIRONMENT_KEY?await syncDefaultLocalVars(fimo,projectId,environment.key,opts):null,action=operation==="add"?"Added":"Updated";warnUntilPublished(kind,environment.key,commandName(kind,operation)),ui.ok({command:commandName(kind,operation),headline:`${action} site ${kind==="secret"?"secret":opts.private?"private variable":"variable"} ${key} in ${environment.name}`,details:{project_id:projectId,key,kind,...opts.private&&{exposure:"private"},environment:environment.key,...envLocal&&{env_local:envLocal}},...kind==="variable"&&{hint:redeployHint(environment.key)}})}__name(writeCommand,"writeCommand");async function unsetCommand(kind,key,opts,command){let{fimo,environment,projectId}=await resolveScope2(opts,command);await fimo.execute("secrets.delete",{projectId,key,kind,environment:environment.key});let envLocal=kind==="variable"&&environment.key!==PRODUCTION_ENVIRONMENT_KEY?await syncDefaultLocalVars(fimo,projectId,environment.key,opts):null;warnUntilPublished(kind,environment.key,commandName(kind,"unset")),ui.ok({command:commandName(kind,"unset"),headline:`Removed site ${kind==="secret"?"secret":"variable"} ${key} from ${environment.name}`,details:{project_id:projectId,key,kind,environment:environment.key,...envLocal&&{env_local:envLocal}},...kind==="variable"&&{hint:redeployHint(environment.key)}})}__name(unsetCommand,"unsetCommand");async function pullVarsCommand(file,opts,command){let projectRoot=resolveProjectCwd(opts.cwd),{fimo,environment,projectId}=await resolveScope2(opts,command),result=await writePulledVars(fimo,projectRoot,projectId,environment.key,file??".env.local");ui.ok({command:"vars pull",headline:`Wrote ${result.written} ${environment.name} variable${result.written===1?"":"s"} to ${result.path}`,details:{project_id:projectId,environment:environment.key,file:result.path,written:result.written}})}__name(pullVarsCommand,"pullVarsCommand");async function syncDefaultLocalVars(fimo,projectId,environment,opts){let projectRoot=resolveProjectCwd(opts.cwd);try{if(loadProjectSettings(projectRoot).projectId!==projectId)return null}catch{return null}return writePulledVars(fimo,projectRoot,projectId,environment,".env.local")}__name(syncDefaultLocalVars,"syncDefaultLocalVars");async function writePulledVars(fimo,projectRoot,projectId,environment,file){let rows=await fimo.execute("secrets.list",{projectId,kind:"variable",environment}),target=path42.resolve(projectRoot,file),existing=fs42.existsSync(target)?fs42.readFileSync(target,"utf8"):"",body=mergeEnvFile(existing,rows);return fs42.writeFileSync(target,body),{path:target,written:rows.filter(isWrittenLocally).length}}__name(writePulledVars,"writePulledVars");function redeployHint(environment){return environment===PRODUCTION_ENVIRONMENT_KEY?"Applies to the live site on the next `fimo publish`.":"Hosted previews rebuild on their own; the Studio preview applies it on the next `fimo deploy`."}__name(redeployHint,"redeployHint");function warnUntilPublished(kind,environment,command){kind==="variable"&&environment===PRODUCTION_ENVIRONMENT_KEY&&ui.warn({command,message:"The live site keeps its current variables until you publish again: run `fimo publish`."})}__name(warnUntilPublished,"warnUntilPublished");function resolveProjectId7(opts){if(opts.project)return opts.project;let cwd=resolveProjectCwd(opts.cwd);return loadProjectSettings(cwd).projectId}__name(resolveProjectId7,"resolveProjectId");async function resolveScope2(opts,command){let fimo=createCliFimoClient(loadConfig()),projectId=resolveProjectId7(opts);if(opts.env!==void 0)return{fimo,projectId,environment:await resolveEnvOption(fimo,projectId,opts.env)};let override=branchOverrideFromCommand(command);return override&&ui.warn({command:command?.name()??"vars",message:"--branch is deprecated for vars and secrets. Pass --env production, --env preview or --env <custom Environment name>."}),{fimo,projectId,environment:await environmentOfBranch(fimo,projectId,override??await currentBranch3(opts))}}__name(resolveScope2,"resolveScope");async function currentBranch3(opts){try{return(await getProjectContext({cwd:opts.cwd})).branch}catch(error){if(!opts.project)throw error;return DEFAULT_BRANCH}}__name(currentBranch3,"currentBranch");async function listEnvironments(fimo,projectId){let custom=(await fimo.execute("environments.list",{projectId})).filter(environment=>environment.kind==="custom").map(environment=>({key:environment.id,name:environment.name}));return[PRODUCTION,PREVIEW,...custom]}__name(listEnvironments,"listEnvironments");async function environmentOfBranch(fimo,projectId,branch){if(branch===PRODUCTION_BRANCH)return PRODUCTION;let{environment}=await fimo.execute("environments.resolve",{projectId,branch});return environment===PREVIEW_ENVIRONMENT_KEY?PREVIEW:environment===PRODUCTION_ENVIRONMENT_KEY?PRODUCTION:(await listEnvironments(fimo,projectId)).find(candidate=>candidate.key===environment)??{key:environment,name:environment}}__name(environmentOfBranch,"environmentOfBranch");async function resolveEnvOption(fimo,projectId,value){let trimmed=value.trim();if(!trimmed)throw new Error("--env needs an Environment: production, preview, or a custom Environment name or id.");let wanted=trimmed.toLowerCase();if(wanted===PRODUCTION_ENVIRONMENT_KEY)return PRODUCTION;if(wanted===PREVIEW_ENVIRONMENT_KEY)return PREVIEW;let environments=await listEnvironments(fimo,projectId),match=environments.find(environment=>environment.key.toLowerCase()===wanted)??environments.find(environment=>environment.name===trimmed);if(match)return match;let sameName=environments.filter(environment=>environment.name.toLowerCase()===wanted);if(sameName.length>1){let candidates=sameName.map(environment=>`${environment.name} (${environment.key})`).join(", ");throw new Error(`'${value}' matches several Environments: ${candidates}. Pass the exact name or the id.`)}if(sameName.length===0){let names=environments.map(environment=>environment.name).join(", ");throw new Error(`No Environment named '${value}'. This site has: ${names}.`)}return sameName[0]}__name(resolveEnvOption,"resolveEnvOption");async function readStdinValue4(kind){if(process.stdin.isTTY)throw new Error(`Pass a ${kind} value or pipe one with --stdin.`);let chunks=[];for await(let chunk of process.stdin)chunks.push(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk));return Buffer.concat(chunks).toString("utf8").replace(/\r?\n$/,"")}__name(readStdinValue4,"readStdinValue");var VARS_BLOCK={start:"# fimo:vars:start",end:"# fimo:vars:end",header:["# Generated by fimo vars pull. Do not put secrets in this block."]};function isWrittenLocally(row2){return row2.exposure==="public"&&!isProcessControlEnvKey(row2.key)}__name(isWrittenLocally,"isWrittenLocally");function mergeEnvFile(existing,rows){let entries2=Object.fromEntries(rows.filter(isWrittenLocally).map(row2=>[row2.key,row2.value??""])),setLocally=keysOutsideManagedBlock(existing,VARS_BLOCK),notes=rows.filter(row2=>!isWrittenLocally(row2)&&!setLocally.has(row2.key)).map(row2=>row2.exposure==="private"?`${row2.key} is a private variable: add a local value outside this block`:`${row2.key} controls the shell or toolchain, so Fimo does not apply it: rename the variable`);return mergeManagedEnvBlock(existing,entries2,VARS_BLOCK,notes).content}__name(mergeEnvFile,"mergeEnvFile");import fs43 from"node:fs";init_dist();init_auth();init_config();init_sdk_transport();init_project_services();init_project2();function resolveCwd2(options){return resolveProjectCwd(options.cwd)}__name(resolveCwd2,"resolveCwd");function readLocalConfig(options){let cwd=resolveCwd2(options);try{return loadProjectSettings(cwd)}catch{return null}}__name(readLocalConfig,"readLocalConfig");function resolveProjectId8(argv,options,command){if(argv)return argv;let local=readLocalConfig(options);return local?local.projectId:(ui.error({command,code:"NOT_IN_PROJECT",message:"No site ID and no Fimo site link found in the current directory.",hint:"Pass a site ID explicitly, or cd into a linked site."}),null)}__name(resolveProjectId8,"resolveProjectId");async function projectsListCommand(options){let cfg=loadConfig(),fimo=createCliFimoClient(cfg),creds=requireAccountCredentials(cfg),organizationId=options.org??creds?.activeOrganization?.id;if(!organizationId){ui.error({command:"projects list",code:"NO_ORGANIZATION_SPECIFIED",message:"No organization specified and no active organization set.",hint:"Run `fimo switch` or pass --org <id>."});return}let{data:projects2}=await fimo.execute("projects.list",{organizationId});if(projects2.length===0){ui.info({command:"projects list",message:"No sites in this organization yet."});return}ui.table({command:"projects list",columns:[{key:"published",label:"PUB"},{key:"id",label:"ID"},{key:"name",label:"NAME"},{key:"displayName",label:"DISPLAY NAME"}],rows:projects2.map(p2=>({published:p2.appUrl?"\u{1F7E2}":"\u26AA",id:p2.id,name:p2.name,displayName:p2.displayName??""}))})}__name(projectsListCommand,"projectsListCommand");async function projectsUnclaimedCommand(){let cfg=loadConfig(),entries2=readUnclaimedIndex(cfg);if(entries2.length===0){ui.info({command:"projects unclaimed",message:"No projects were created without an account on this machine.",jsonData:{projects:[]}});return}let claims=await createUnclaimedProjectsService(cfg).claimStates(entries2.map(entry=>claimSecretFromUrl(entry.claimUrl))),projects2=entries2.flatMap((entry,index)=>{let claim=claims[index];return claim?.state!=="claimable"?[]:[{project_id:entry.projectId,name:entry.name,dir:entry.dir,state:claim.state,expires_at:new Date(claim.expiresAt??entry.expiresAt).toISOString(),claim_url:entry.claimUrl}]});if(projects2.length===0){ui.info({command:"projects unclaimed",message:"No site created on this machine is waiting for a claim.",jsonData:{projects:[]}});return}ui.result({command:"projects unclaimed",data:{projects:projects2},render:__name(()=>projects2.map(project=>[`${project.name} claim by ${formatClaimDeadline(project.expires_at)}`,` ${project.dir}`,` ${project.claim_url}`].join(`
2774
2774
  `)).join(`
2775
2775
 
2776
2776
  `),"render")})}__name(projectsUnclaimedCommand,"projectsUnclaimedCommand");async function projectsDeleteCommand(projectIdArg,options){let cfg=loadConfig(),fimo=createCliFimoClient(cfg),projectId=resolveProjectId8(projectIdArg,options,"projects delete");if(projectId){if(!options.yes){assertInteractive("Pass --yes to skip confirmation.","projects delete");let confirmed=await ot2({message:`Delete site ${projectId}? This cannot be undone.`,initialValue:!1});if(q(confirmed)||!confirmed){ui.info({command:"projects delete",message:"Cancelled."});return}}await fimo.execute("projects.delete",{projectId}),ui.ok({command:"projects delete",headline:`Deleted site ${projectId}.`,details:{project_id:projectId}})}}__name(projectsDeleteCommand,"projectsDeleteCommand");async function projectsRenameCommand(nameArg,projectIdArg,options){let cwd=resolveCwd2(options),local=readLocalConfig(options);if(!local){ui.error({command:"projects rename",code:"NOT_IN_PROJECT",message:"No Fimo site link found in the current directory.",hint:"`fimo rename` only operates on a local site. cd into the site root."});return}if(projectIdArg&&projectIdArg!==local.projectId){ui.error({command:"projects rename",code:"PROJECT_ID_MISMATCH",message:`Site ID ${projectIdArg} does not match this directory's site (${local.projectId}).`,hint:"cd into the site you want to rename."});return}let name=nameArg.trim();if(!name){ui.error({command:"projects rename",code:"EMPTY_DISPLAY_NAME",message:"Display name cannot be empty."});return}let configPath=resolveProjectConfigPath(cwd),config={};if(fs43.existsSync(configPath))try{config=JSON.parse(fs43.readFileSync(configPath,"utf-8"))}catch(error){ui.error({command:"projects rename",code:"CONFIG_PARSE_FAILED",message:`Could not parse ${configPath}: ${error instanceof Error?error.message:String(error)}`});return}let seo=config.seo??{};config.seo={...seo,siteName:name},fs43.writeFileSync(configPath,JSON.stringify(config,null,2)+`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fimo",
3
- "version": "2.9.0-staging.7",
3
+ "version": "2.9.0-staging.8",
4
4
  "description": "Fimo CLI - create, deploy, and manage Fimo sites",
5
5
  "keywords": [
6
6
  "astro-component"
@@ -194,13 +194,13 @@
194
194
  "devDependencies": {
195
195
  "@clack/core": "^1.2.0",
196
196
  "@clack/prompts": "^1.2.0",
197
- "@fimo/agents-bundle": "2.9.0-staging.7",
198
- "@fimo/api-contracts": "2.9.0-staging.7",
199
- "@fimo/cli-kit": "2.9.0-staging.7",
200
- "@fimo/framework-detect": "2.9.0-staging.7",
201
- "@fimo/routes": "2.9.0-staging.7",
202
- "@fimo/sdk": "2.9.0-staging.7",
203
- "@fimo/tsconfig": "2.9.0-staging.7",
197
+ "@fimo/agents-bundle": "2.9.0-staging.8",
198
+ "@fimo/api-contracts": "2.9.0-staging.8",
199
+ "@fimo/cli-kit": "2.9.0-staging.8",
200
+ "@fimo/framework-detect": "2.9.0-staging.8",
201
+ "@fimo/routes": "2.9.0-staging.8",
202
+ "@fimo/sdk": "2.9.0-staging.8",
203
+ "@fimo/tsconfig": "2.9.0-staging.8",
204
204
  "@types/node": "22.18.6",
205
205
  "agent-install": "^0.0.5",
206
206
  "astro": "^7.1.6",
@@ -9,9 +9,9 @@
9
9
  "check": "astro sync && astro check"
10
10
  },
11
11
  "dependencies": {
12
- "fimo": "2.9.0-staging.7",
13
- "fimo-analytics": "2.9.0-staging.7",
14
- "fimo-astro": "2.9.0-staging.7",
12
+ "fimo": "2.9.0-staging.8",
13
+ "fimo-analytics": "2.9.0-staging.8",
14
+ "fimo-astro": "2.9.0-staging.8",
15
15
  "zod": "^4.4.3"
16
16
  },
17
17
  "devDependencies": {
@@ -12,10 +12,10 @@
12
12
  },
13
13
  "dependencies": {
14
14
  "@tanstack/react-query": "^5.80.6",
15
- "fimo": "2.9.0-staging.7",
16
- "fimo-analytics": "2.9.0-staging.7",
17
- "fimo-next": "2.9.0-staging.7",
18
- "fimo-react": "2.9.0-staging.7",
15
+ "fimo": "2.9.0-staging.8",
16
+ "fimo-analytics": "2.9.0-staging.8",
17
+ "fimo-next": "2.9.0-staging.8",
18
+ "fimo-react": "2.9.0-staging.8",
19
19
  "next": "16.4.2",
20
20
  "react": "^19.2.7",
21
21
  "react-dom": "^19.2.7",
@@ -21,11 +21,11 @@
21
21
  "cn": "0.2.4",
22
22
  "date-fns": "^4.1.0",
23
23
  "embla-carousel-react": "^8.6.0",
24
- "fimo": "2.9.0-staging.7",
25
- "fimo-analytics": "2.9.0-staging.7",
26
- "fimo-react": "2.9.0-staging.7",
27
- "fimo-react-router": "2.9.0-staging.7",
28
- "fimo-vite": "2.9.0-staging.7",
24
+ "fimo": "2.9.0-staging.8",
25
+ "fimo-analytics": "2.9.0-staging.8",
26
+ "fimo-react": "2.9.0-staging.8",
27
+ "fimo-react-router": "2.9.0-staging.8",
28
+ "fimo-vite": "2.9.0-staging.8",
29
29
  "input-otp": "^1.4.2",
30
30
  "isbot": "^5",
31
31
  "lucide-react": "^0.577.0",
@@ -11,9 +11,9 @@
11
11
  "prepare": "svelte-kit sync"
12
12
  },
13
13
  "dependencies": {
14
- "fimo": "2.9.0-staging.7",
15
- "fimo-analytics": "2.9.0-staging.7",
16
- "fimo-sveltekit": "2.9.0-staging.7",
14
+ "fimo": "2.9.0-staging.8",
15
+ "fimo-analytics": "2.9.0-staging.8",
16
+ "fimo-sveltekit": "2.9.0-staging.8",
17
17
  "zod": "^4.4.3"
18
18
  },
19
19
  "devDependencies": {
@@ -11,11 +11,11 @@
11
11
  },
12
12
  "dependencies": {
13
13
  "@tanstack/react-query": "^5.80.6",
14
- "fimo": "2.9.0-staging.7",
15
- "fimo-analytics": "2.9.0-staging.7",
16
- "fimo-react": "2.9.0-staging.7",
17
- "fimo-react-router": "2.9.0-staging.7",
18
- "fimo-vite": "2.9.0-staging.7",
14
+ "fimo": "2.9.0-staging.8",
15
+ "fimo-analytics": "2.9.0-staging.8",
16
+ "fimo-react": "2.9.0-staging.8",
17
+ "fimo-react-router": "2.9.0-staging.8",
18
+ "fimo-vite": "2.9.0-staging.8",
19
19
  "react": "^19.2.7",
20
20
  "react-dom": "^19.2.7",
21
21
  "react-router": "^8.3.0",