@initx-plugin/env 0.1.3 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -54,6 +54,14 @@ or the full namespace, including multiple subgroups. `apiBaseUrl` means the API
54
54
  `stores`; `"path": ""` explicitly selects repository root. For a GitHub vault, use `"type": "github"`
55
55
  and `"repo": "owner/vault"`. Examples are in [examples](examples/).
56
56
 
57
+ The vault project/repository must already exist, but it can be empty. The first `env push <store>`
58
+ or `env set <store> K=V` creates the configured branch (default `main`) and the store file in one
59
+ commit, on both GitHub and GitLab. No README or manual branch creation is required. `list` and
60
+ `env-config status` report zero stores for a confirmed empty vault without writing anything.
61
+ An initialized vault with a missing configured branch still fails. The token must have permission
62
+ to create the first commit; GitLab instance rules for the initial/default branch may require a
63
+ Maintainer even when a Developer can write to other branches.
64
+
57
65
  All storage commands and `env-config status` accept `--config <file>`. Relative paths resolve
58
66
  against the caller's cwd. Without the flag, only cwd's `.initx-env.json` is checked; parents are
59
67
  never searched. An explicitly missing file, invalid JSON, unknown schema or unknown field fails
@@ -98,6 +106,14 @@ Legacy flat config remains GitHub config; its token is accepted only on the defa
98
106
  | `initx env run <store> -- <command> [...args]` | Inject a store directly into one child process and return its exit status |
99
107
  | `initx env apply <store> --repo o/r` | Write a store into a repo's GitHub Actions secrets |
100
108
 
109
+ Command failures print only the error message to stderr and exit with code 1, without a stack
110
+ trace or minified source dump. A failed connectivity check in `env-config status` also exits
111
+ with code 1. `env run` continues to forward the child's own exit status, signals and output.
112
+ Terminal messages use the existing utils color builders: errors are red, successful changes
113
+ green, warnings/modified keys yellow, and configuration values/store names blue. Message-body
114
+ colors are disabled when redirected or when `NO_COLOR`/`FORCE_COLOR=0` is set; `FORCE_COLOR=1`
115
+ enables them explicitly. JSON, exported variable values and child output are not colorized.
116
+
101
117
  ```bash
102
118
  # write / update a store
103
119
  initx env set mail-peon-publish EXTENSION_ID=abc CHROME_REFRESH_TOKEN=1//0g...
@@ -273,7 +289,8 @@ hints; concurrent remote-only changes can be replaced. Pull/review before force
273
289
 
274
290
  GitLab uses Files GET/POST/PUT, a conditional Commits delete action, and Tree offset pagination
275
291
  (`per_page=100`). It supports full subgroups and numeric IDs, and does not require keyset pagination, newer Tree metadata or job-token
276
- features. Missing paths are empty only after validating repository/ref access. Tree accepts both
292
+ features. Missing paths are empty only after validating repository/ref access or confirming an
293
+ empty repository (GitLab project `empty_repo`, GitHub's explicit empty-repository response). Tree accepts both
277
294
  legacy 200 empty arrays and newer 404 responses. Directory listing is not recursive. Errors expose
278
295
  only a category, safe hint and HTTP status, never upstream response text or request URLs.
279
296
 
package/dist/index.d.mts CHANGED
@@ -27,6 +27,7 @@ declare class EnvPlugin extends InitxPlugin<EnvPluginStore> {
27
27
  defaultStore: EnvPluginStore;
28
28
  rules: InitxMatcherRules;
29
29
  handle(ctx: InitxContext<EnvPluginStore>, ...args: (string | undefined)[]): Promise<void>;
30
+ private dispatch;
30
31
  }
31
32
 
32
33
  export { EnvPlugin as default };
package/dist/index.d.ts CHANGED
@@ -27,6 +27,7 @@ declare class EnvPlugin extends InitxPlugin<EnvPluginStore> {
27
27
  defaultStore: EnvPluginStore;
28
28
  rules: InitxMatcherRules;
29
29
  handle(ctx: InitxContext<EnvPluginStore>, ...args: (string | undefined)[]): Promise<void>;
30
+ private dispatch;
30
31
  }
31
32
 
32
33
  export { EnvPlugin as default };
package/dist/index.mjs CHANGED
@@ -1,27 +1,28 @@
1
- import{InitxPlugin as Nu}from"@initx-plugin/core";import{readFile as su,copyFile as Iu,writeFile as au,stat as Su,readdir as Uu}from"node:fs/promises";import f from"node:process";import{logger as F,inquirer as b}from"@initx-plugin/utils";import{readFileSync as Ou,appendFileSync as ju}from"node:fs";import{resolve as Gu}from"node:path";import{z as A}from"zod";import{Buffer as I}from"node:buffer";import{randomBytes as cu}from"node:crypto";import Fu from"libsodium-wrappers";import{constants as Pu}from"node:os";import Ru from"cross-spawn";function M(u){return u.replace(/-([a-z])/g,(t,e)=>e.toUpperCase())}function z(u,t){return u[t]??u[M(t)]}function Vu(u){if(typeof u=="string")return u===""?void 0:u;if(typeof u=="number")return String(u);if(Array.isArray(u))return u.length?u.map(String).join(","):void 0}function Lu(u={},t=[]){const e=new Set(t);return{raw:u,string:n=>Vu(z(u,n)),boolean:n=>{const r=z(u,n);return typeof r=="boolean"?r:e.has(`--${n}`)||e.has(`--${M(n)}`)},has:n=>z(u,n)!==void 0?!0:e.has(`--${n}`)||e.has(`--${M(n)}`)}}function P(u){if(!u.has("config"))return;const t=u.raw.config;if(typeof t!="string"||!t.trim())throw new Error("--config \u9700\u8981\u5355\u4E2A\u6587\u4EF6\u8DEF\u5F84");return t}const Hu={authentication:"\u8BA4\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5F53\u524D\u540E\u7AEF\u7684 token",permission:"\u6CA1\u6709\u6743\u9650\uFF0C\u8BF7\u68C0\u67E5 token \u6388\u6743\u4E0E\u5206\u652F\u4FDD\u62A4","not-found":"\u4ED3\u5E93\u6216 ref \u4E0D\u5B58\u5728\uFF0C\u6216\u5F53\u524D token \u65E0\u6743\u8BBF\u95EE",conflict:"\u8FDC\u7AEF\u7248\u672C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\uFF1Bpush \u53EF\u7528 --force \u91CD\u8BFB\u540E\u91CD\u8BD5\u4E00\u6B21",validation:"\u8BF7\u6C42\u6216\u54CD\u5E94\u4E0D\u5408\u6CD5\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84\u3001ref \u4E0E\u914D\u7F6E","rate-limit":"API \u8BF7\u6C42\u88AB\u9650\u6D41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",network:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\u6216\u8D85\u65F6\uFF1B\u5199\u5165\u7ED3\u679C\u53EF\u80FD\u672A\u77E5\uFF0C\u8BF7\u5148\u91CD\u8BFB\u786E\u8BA4",unsupported:"\u5B58\u50A8\u540E\u7AEF\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C"};class d extends Error{constructor(t,e){super(`${Hu[t]}${e?`\uFF08HTTP ${e}\uFF09`:""}`),this.code=t,this.status=e,this.name="StorageError"}}function Ku(u){return u instanceof d&&u.code==="conflict"}function q(u){const t=u.status,e=t===429||t===403&&(u.headers.get("x-ratelimit-remaining")==="0"||u.headers.has("retry-after"));return new d(e?"rate-limit":t===401?"authentication":t===403?"permission":t===404?"not-found":t>=500?"network":"validation",t)}const $={github:"https://api.github.com",gitlab:"https://gitlab.com/api/v4"};function D(u,t=!1){if(!(u===""&&t)){if(u.split("/").some(e=>e==="."||e===".."))throw Object.assign(new d("validation"),{message:"\u8DEF\u5F84\u4E0D\u80FD\u5305\u542B . \u6216 .."});if(!u||/[\\\x00-\x1F\x7F]/.test(u)||u.startsWith("/")||/^[A-Z]:/i.test(u)||u.split("/").some(e=>!e||e==="."||e===".."))throw new d("validation")}}function k(u){try{const t=new URL(u);if(!["https:","http:"].includes(t.protocol)||t.username||t.password||t.search||t.hash)throw new Error("Invalid API base URL");return t.href.replace(/\/+$/,"")}catch{throw new d("validation")}}function x(u,t){if(D(t),/\s/.test(t)||(u==="github"?t.split("/").length!==2:!/^\d+$/.test(t)&&t.split("/").length<2))throw new Error(u==="github"?"\u4ED3\u5E93\u8981\u5199\u6210 owner/repo \u5F62\u5F0F":"GitLab \u4ED3\u5E93\u5FC5\u987B\u662F\u6570\u5B57\u9879\u76EE ID \u6216 group/subgroup/project")}const Xu=A.object({schema:A.literal(1),storage:A.object({type:A.enum(["github","gitlab"]),apiBaseUrl:A.string().min(1).optional(),repo:A.string().min(1),branch:A.string().min(1).optional(),path:A.string().optional()}).strict()}).strict();class R extends Error{constructor(t){super(t),this.name="ProjectConfigError"}}function Ju(u,t=f.cwd()){const e=Gu(t,u||".initx-env.json");let n;try{n=Ou(e,"utf8")}catch(o){if(!u&&o.code==="ENOENT")return;throw new R("\u65E0\u6CD5\u8BFB\u53D6\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\uFF0C\u8BF7\u68C0\u67E5 --config \u8DEF\u5F84\u4E0E\u6587\u4EF6\u6743\u9650")}let r;try{r=Xu.parse(JSON.parse(n))}catch{throw new R("\u9879\u76EE\u914D\u7F6E\u5FC5\u987B\u662F schema 1 \u7684\u5408\u6CD5 JSON\uFF0C\u4E14\u53EA\u80FD\u5305\u542B\u975E\u654F\u611F storage \u5B9A\u4F4D\u5B57\u6BB5\uFF08\u7981\u6B62 token / vars\uFF09")}try{const o={...r.storage,apiBaseUrl:k(r.storage.apiBaseUrl||$[r.storage.type])};return x(o.type,o.repo),o.path!==void 0&&D(o.path,!0),{file:e,storage:o}}catch{throw new R("\u9879\u76EE storage \u7684 API \u5730\u5740\u3001\u4ED3\u5E93\u6216\u8DEF\u5F84\u4E0D\u5408\u6CD5")}}const V="main",L="stores";function H(u,t){return`${u}:${k(t)}`}function S(u){const t=u.storage?.type||"github";if(t!=="github"&&t!=="gitlab")throw new Error("\u672C\u5730 storage.type \u5FC5\u987B\u662F github \u6216 gitlab");return{type:t,apiBaseUrl:k(u.storage?.apiBaseUrl||$[t])}}function Yu(u,t){const e=t.env??f.env,n=Ju(t.config,t.cwd),r=S(u),o=t.type||e.INITX_ENV_TYPE||n?.storage.type||r.type;if(o!=="github"&&o!=="gitlab")throw new Error("storage.type \u5FC5\u987B\u662F github \u6216 gitlab");const i=o,s=n?.storage.type===i,a=t.apiBaseUrl||e.INITX_ENV_API_BASE_URL||(s?n.storage.apiBaseUrl:void 0)||(r.type===i?r.apiBaseUrl:$[i]),E=k(a),c=r.type===i&&r.apiBaseUrl===E,l=s&&n.storage.apiBaseUrl===E,h=c?u.storage||u:{},p=l?n.storage:void 0,w={type:t.type?"override":e.INITX_ENV_TYPE?"INITX_ENV_TYPE":n?"project":"local/default",apiBaseUrl:t.apiBaseUrl?"override":e.INITX_ENV_API_BASE_URL?"INITX_ENV_API_BASE_URL":l?"project":c?"local/default":"default",repo:"",branch:"",path:""};function B(y,g){const _=`INITX_ENV_${y.toUpperCase()}`,m=[[t[y]||void 0,"override"],[e[_]||void 0,_],[p?.[y],"project"],[h[y]||void 0,"local"],[g,"default"]].find(([_u])=>_u!==void 0);return w[y]=m[1],m[0]}return{type:i,apiBaseUrl:E,repo:B("repo",""),branch:B("branch",V),path:B("path",L),sources:w,configSource:n?.file||"local/env/default"}}function Wu(u,t,e){const n=t.env??f.env;if(t.token)return{token:t.token,source:"flag"};if(n.INITX_ENV_TOKEN)return{token:n.INITX_ENV_TOKEN,source:"INITX_ENV_TOKEN"};const r=e.type==="github"&&e.apiBaseUrl===$.github;if(r){for(const i of["GH_TOKEN","GITHUB_TOKEN"])if(n[i])return{token:n[i],source:i}}const o=u.credentials?.[H(e.type,e.apiBaseUrl)];return o?{token:o,source:"config"}:r&&u.token?{token:u.token,source:"config"}:{token:"",source:"none"}}function K(u,t={}){const e=Yu(u,t);if(!e.repo)throw new Error("\u8FD8\u6CA1\u914D vault \u4ED3\u5E93\uFF0C\u8BF7\u914D\u7F6E .initx-env.json \u6216 env-config set repo <owner/repo>");x(e.type,e.repo),D(e.path,!0);const{token:n,source:r}=Wu(u,t,e);if(!n)throw new Error("\u6CA1\u6709\u53EF\u7528\u7684\u5F53\u524D\u540E\u7AEF token\uFF0C\u8BF7\u8BBE\u7F6E INITX_ENV_TOKEN\u3001--token \u6216\u7ED1\u5B9A\u5F53\u524D API \u5730\u5740\u7684\u672C\u5730\u51ED\u636E");return{...e,token:n,tokenSource:r}}function Mu(u){return u?"***":"(\u672A\u8BBE\u7F6E)"}function Z(u){return Mu(u)}async function C(u,t={}){try{return await fetch(u,{...t,redirect:"error",signal:AbortSignal.timeout(3e4)})}catch{throw new d("network")}}async function N(u){try{return await u.json()}catch(t){throw new d(t instanceof SyntaxError?"validation":"network")}}function v(u){if(!u.ok)throw q(u)}function lu(u){return{Authorization:`Bearer ${u}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"initx-plugin-env"}}class zu{constructor(t,e){this.location=t,x("github",t.repo),this.base=`${k(t.apiBaseUrl)}/repos/${t.repo.split("/").map(encodeURIComponent).join("/")}`,this.headers=lu(e)}capabilities={read:!0,list:!0,write:!0,delete:!0,conditionalWrite:!0};base;headers;url(t){D(t,!0);const e=t?`/${t.split("/").map(encodeURIComponent).join("/")}`:"";return`${this.base}/contents${e}?${new URLSearchParams({ref:this.location.branch})}`}async checkTarget(){const t=await C(`${this.base}/commits/${encodeURIComponent(this.location.branch)}`,{headers:this.headers});v(t)}async read(t){D(t);const e=await C(this.url(t),{headers:this.headers});if(e.status===404)return await this.checkTarget(),null;v(e);const n=await N(e);if(!n||n.type!=="file"||typeof n.sha!="string"||!n.sha||typeof n.content!="string"||n.encoding!=="base64")throw new d("validation");return{content:I.from(n.content,"base64").toString("utf8"),version:n.sha}}async list(t){const e=await C(this.url(t),{headers:this.headers});if(e.status===404)return await this.checkTarget(),[];v(e);const n=await N(e);if(!Array.isArray(n)||n.some(r=>!r||typeof r.name!="string"||typeof r.path!="string"||typeof r.type!="string"))throw new d("validation");return n.map(r=>({name:r.name,path:r.path,kind:r.type==="file"?"file":r.type==="dir"?"directory":"other"}))}async write(t,e,n){D(t);const r=n.condition;if(r.kind!=="create"&&(r.kind!=="update"||!r.expectedVersion))throw new d("validation");const o=await C(this.url(t),{method:"PUT",headers:{...this.headers,"Content-Type":"application/json"},body:JSON.stringify({branch:this.location.branch,message:n.message||"env: write store",content:I.from(e).toString("base64"),...r.kind==="update"?{sha:r.expectedVersion}:{}})});if([404,409,422].includes(o.status)){const i=await this.read(t);if(r.kind==="create"?i!==null:i?.version!==r.expectedVersion)throw new d("conflict",o.status)}if(!o.ok)throw q(o)}async remove(t,e){if(D(t),!e.expectedVersion)throw new d("validation");const n=await C(this.url(t),{method:"DELETE",headers:{...this.headers,"Content-Type":"application/json"},body:JSON.stringify({branch:this.location.branch,message:e.message||"env: remove store",sha:e.expectedVersion})});if([404,409,422].includes(n.status)&&(await this.read(t))?.version!==e.expectedVersion)throw new d("conflict",n.status);v(n)}}async function Eu(u){if(u.status!==400)return;let t;try{t=await N(u)}catch(e){if(e instanceof d&&e.code==="network")throw e}if(t?.message==="You are not allowed to push into this branch")throw new d("permission",400)}class qu{constructor(t,e){this.location=t,x("gitlab",t.repo),this.base=`${k(t.apiBaseUrl)}/projects/${encodeURIComponent(t.repo)}/repository`,this.headers={"PRIVATE-TOKEN":e,"Content-Type":"application/json"}}capabilities={read:!0,list:!0,write:!0,delete:!0,conditionalWrite:!0};base;headers;fileUrl(t){return D(t),`${this.base}/files/${encodeURIComponent(t)}`}async checkTarget(){const t=await C(`${this.base}/commits/${encodeURIComponent(this.location.branch)}`,{headers:this.headers});v(t)}async read(t){const e=await C(`${this.fileUrl(t)}?${new URLSearchParams({ref:this.location.branch})}`,{headers:this.headers});if(e.status===404)return await this.checkTarget(),null;v(e);const n=await N(e);if(!n||typeof n.content!="string"||n.encoding!=="base64"||typeof n.last_commit_id!="string"||!n.last_commit_id)throw new d("validation");return{content:I.from(n.content,"base64").toString("utf8"),version:n.last_commit_id}}async list(t){D(t,!0);const e=[];await this.checkTarget();for(let n=1;;n++){const r=new URLSearchParams({ref:this.location.branch,per_page:"100",page:String(n),...t?{path:t}:{}}),o=await C(`${this.base}/tree?${r}`,{headers:this.headers});if(o.status===404)return await this.checkTarget(),e;v(o);const i=await N(o);if(!Array.isArray(i)||i.some(a=>!a||typeof a.name!="string"||typeof a.path!="string"||typeof a.type!="string"))throw new d("validation");e.push(...i.map(a=>({name:a.name,path:a.path,kind:a.type==="blob"?"file":a.type==="tree"?"directory":"other"})));const s=o.headers.get("x-next-page");if(!i.length||s===""||s===null&&i.length<100)return e;if(s!==null&&s!==String(n+1))throw new d("validation")}}async write(t,e,n){const r=n.condition;if(r.kind!=="create"&&(r.kind!=="update"||!r.expectedVersion))throw new d("validation");const o=await C(this.fileUrl(t),{method:r.kind==="create"?"POST":"PUT",headers:this.headers,body:JSON.stringify({branch:this.location.branch,commit_message:n.message||"env: write store",content:I.from(e).toString("base64"),encoding:"base64",...r.kind==="update"?{last_commit_id:r.expectedVersion}:{}})});if(await Eu(o),[400,404,409,422].includes(o.status)){const i=await this.read(t);if(r.kind==="create"?i!==null:i?.version!==r.expectedVersion)throw new d("conflict",o.status);if(r.kind==="update"&&o.status===400&&i?.content===e)return}if(!o.ok)throw q(o)}async remove(t,e){if(D(t),!e.expectedVersion)throw new d("validation");const n=await C(`${this.base}/commits`,{method:"POST",headers:this.headers,body:JSON.stringify({branch:this.location.branch,commit_message:e.message||"env: remove store",actions:[{action:"delete",file_path:t,last_commit_id:e.expectedVersion}]})});if(await Eu(n),[400,404,409,422].includes(n.status)&&(await this.read(t))?.version!==e.expectedVersion)throw new d("conflict",n.status);v(n)}}const Zu={github:zu,gitlab:qu};function X(u){const t=Zu[u.type];if(!t)throw new d("unsupported");return new t(u,u.token)}function J(u,t){if(!u.capabilities[t])throw new d("unsupported")}const Q=1,Qu=A.object({repo:A.string().regex(/^[^/\s]+\/[^/\s]+$/,"\u5FC5\u987B\u662F owner/repo \u5F62\u5F0F"),env:A.string().nullish()}),ut=A.object({schema:A.number().int().positive().default(Q),vars:A.record(A.string(),A.string()).default({}),targets:A.object({envFiles:A.array(A.string().min(1)).optional(),secrets:A.array(Qu).optional()}).optional()});function pu(){return{schema:Q,vars:{}}}function T(u){const t=u.trim().replace(/\.json$/i,"");if(!t)throw new Error("store \u540D\u4E0D\u80FD\u4E3A\u7A7A");if(t.includes("/")||t.includes("\\"))throw new Error(`store \u540D\u4E0D\u80FD\u5305\u542B\u8DEF\u5F84\u5206\u9694\u7B26\uFF1A"${u}"`);if(t==="."||t==="..")throw new Error(`store \u540D\u4E0D\u80FD\u662F "${t}"`);if(/[\u0000-\u001F\u007F]/.test(t))throw new Error("store \u540D\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26");if(t.length>100)throw new Error("store \u540D\u592A\u957F\uFF08\u4E0A\u9650 100 \u5B57\u7B26\uFF09");return t}function tt(u){return/^[A-Z_]\w*$/i.test(u)?u.toUpperCase().startsWith("GITHUB_")?"GITHUB_ \u524D\u7F00\u662F GitHub \u4FDD\u7559\u7684":null:"\u53EA\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4E0D\u80FD\u4EE5\u6570\u5B57\u5F00\u5934"}function et(u){return/^[A-Z_][\w.-]*$/i.test(u)}function fu(u,t){const e=T(t),n=(u||"").trim().replace(/^\/+|\/+$/g,""),r=n?`${n}/${e}.json`:`${e}.json`;return D(r),r}function nt(u,t){let e;try{e=JSON.parse(u)}catch{throw new Error(`store "${t}" \u4E0D\u662F\u5408\u6CD5 JSON`)}const n=ut.safeParse(e);if(!n.success)throw new Error(`store "${t}" \u7ED3\u6784\u4E0D\u5408\u6CD5\uFF1A${n.error.issues.map(r=>`${r.path.join(".")||"(root)"} ${r.message}`).join("; ")}`);return n.data}function rt(u){return`${JSON.stringify({...u,schema:u.schema??Q},null,2)}
2
- `}async function uu(u,t){J(u,"list");const e=(t||"").trim().replace(/^\/+|\/+$/g,"");return(await u.list(e)).filter(n=>n.kind==="file"&&n.name.toLowerCase().endsWith(".json")).map(n=>n.name.replace(/\.json$/i,"")).sort((n,r)=>n.localeCompare(r))}async function U(u,t,e){const n=fu(t,e);J(u,"read");const r=await u.read(n);if(!r)return null;const o=T(e);return{name:o,path:n,version:r.version,store:nt(r.content,o)}}async function tu(u,t,e,n,r,o){J(u,"write"),J(u,"conditionalWrite"),await u.write(fu(t,e),rt(n),{message:r,condition:o===void 0?{kind:"create"}:{kind:"update",expectedVersion:o}})}function hu(u,t){const e={added:[],updated:[],unchanged:[]};for(const[n,r]of Object.entries(t)){const o=u.vars[n];o===void 0?(u.vars[n]=r,e.added.push(n)):o===r?e.unchanged.push(n):(u.vars[n]=r,e.updated.push(n))}return e}const du=/^export[ \t]+/,ot=/^([^=]*)=(.*)$/;function it(u){const t=u.replace(/[ \t]+$/,"");return t===""||/^[ \t]/.test(t)?null:t}const st=/^[ \t]*#/;function gu(u){return typeof u=="object"&&u!==null&&u.code==="ENOENT"}async function at(u){try{return await Su(u)}catch(t){if(gu(t))return null;throw t}}function ct(u){return u.replace(/\\([nrt"\\])/g,(t,e)=>e==="n"?`
3
- `:e==="r"?"\r":e==="t"?" ":e)}function Ft(u){const t=u.replace(/^[ \t]+/,"");for(const e of t.split(`
4
- `)){const n=/[ \t]#/.exec(e);if(n!==null)return e.slice(0,n.index).replace(/[ \t]+$/,"")}return t.replace(/[ \t]+$/,"")}function lt(u){if(u==="")return[];const t=u.split(/\r?\n/);return u.endsWith(`
5
- `)&&t.pop(),t}function wu(u){for(let t=0;t<u.length;t+=1){if(u[t]==="\\"){t+=1;continue}if(u[t]==='"')return t}return-1}function Et(u,t){const e=u[t];if(st.test(e))return null;const n=du.test(e),r=ot.exec(n?e.replace(du,""):e);if(r===null)return null;const o=it(r[1]);if(o===null)return null;const i=r[2];let s=t,a="none",E;if(i.startsWith('"')){let c=i.slice(1),l=wu(c);for(;l===-1&&s+1<u.length;)s+=1,c+=`
6
- ${u[s]}`,l=wu(c);a="double",E=ct(l===-1?c:c.slice(0,l))}else if(i.startsWith("'")){const c=i.indexOf("'",1);a="single",E=c===-1?i.slice(1):i.slice(1,c)}else E=Ft(i);return{key:o,value:E,exportPrefix:n,quote:a,raw:e,startLine:t,endLine:s}}function Y(u){const t=u.includes(`\r
1
+ import{InitxPlugin as Iu}from"@initx-plugin/core";import{readFile as au,copyFile as Su,writeFile as cu,stat as Ou,readdir as Uu}from"node:fs/promises";import f from"node:process";import{useColors as ju,logger as l,inquirer as x}from"@initx-plugin/utils";import{readFileSync as Ru,appendFileSync as Gu}from"node:fs";import{resolve as Pu}from"node:path";import{z as B}from"zod";import{Buffer as S}from"node:buffer";import{randomBytes as Fu}from"node:crypto";import lu from"libsodium-wrappers";import{constants as Lu}from"node:os";import Vu from"cross-spawn";function z(u){return u.replace(/-([a-z])/g,(t,e)=>e.toUpperCase())}function q(u,t){return u[t]??u[z(t)]}function Hu(u){if(typeof u=="string")return u===""?void 0:u;if(typeof u=="number")return String(u);if(Array.isArray(u))return u.length?u.map(String).join(","):void 0}function Ku(u={},t=[]){const e=new Set(t);return{raw:u,string:n=>Hu(q(u,n)),boolean:n=>{const r=q(u,n);return typeof r=="boolean"?r:e.has(`--${n}`)||e.has(`--${z(n)}`)},has:n=>q(u,n)!==void 0?!0:e.has(`--${n}`)||e.has(`--${z(n)}`)}}function P(u){if(!u.has("config"))return;const t=u.raw.config;if(typeof t!="string"||!t.trim())throw new Error("--config \u9700\u8981\u5355\u4E2A\u6587\u4EF6\u8DEF\u5F84");return t}const Xu={authentication:"\u8BA4\u8BC1\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5F53\u524D\u540E\u7AEF\u7684 token",permission:"\u6CA1\u6709\u6743\u9650\uFF0C\u8BF7\u68C0\u67E5 token \u6388\u6743\u4E0E\u5206\u652F\u4FDD\u62A4","not-found":"\u4ED3\u5E93\u6216 ref \u4E0D\u5B58\u5728\uFF0C\u6216\u5F53\u524D token \u65E0\u6743\u8BBF\u95EE",conflict:"\u8FDC\u7AEF\u7248\u672C\u5DF2\u53D8\u5316\uFF0C\u8BF7\u91CD\u65B0\u8BFB\u53D6\uFF1Bpush \u53EF\u7528 --force \u91CD\u8BFB\u540E\u91CD\u8BD5\u4E00\u6B21",validation:"\u8BF7\u6C42\u6216\u54CD\u5E94\u4E0D\u5408\u6CD5\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84\u3001ref \u4E0E\u914D\u7F6E","rate-limit":"API \u8BF7\u6C42\u88AB\u9650\u6D41\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",network:"\u7F51\u7EDC\u8BF7\u6C42\u5931\u8D25\u6216\u8D85\u65F6\uFF1B\u5199\u5165\u7ED3\u679C\u53EF\u80FD\u672A\u77E5\uFF0C\u8BF7\u5148\u91CD\u8BFB\u786E\u8BA4",unsupported:"\u5B58\u50A8\u540E\u7AEF\u4E0D\u652F\u6301\u6B64\u64CD\u4F5C"};class g extends Error{constructor(t,e){super(`${Xu[t]}${e?`\uFF08HTTP ${e}\uFF09`:""}`),this.code=t,this.status=e,this.name="StorageError"}}function Ju(u){return u instanceof g&&u.code==="conflict"}function Z(u){const t=u.status,e=t===429||t===403&&(u.headers.get("x-ratelimit-remaining")==="0"||u.headers.has("retry-after"));return new g(e?"rate-limit":t===401?"authentication":t===403?"permission":t===404?"not-found":t>=500?"network":"validation",t)}const b={github:"https://api.github.com",gitlab:"https://gitlab.com/api/v4"};function y(u,t=!1){if(!(u===""&&t)){if(u.split("/").some(e=>e==="."||e===".."))throw Object.assign(new g("validation"),{message:"\u8DEF\u5F84\u4E0D\u80FD\u5305\u542B . \u6216 .."});if(!u||/[\\\x00-\x1F\x7F]/.test(u)||u.startsWith("/")||/^[A-Z]:/i.test(u)||u.split("/").some(e=>!e||e==="."||e===".."))throw new g("validation")}}function _(u){try{const t=new URL(u);if(!["https:","http:"].includes(t.protocol)||t.username||t.password||t.search||t.hash)throw new Error("Invalid API base URL");return t.href.replace(/\/+$/,"")}catch{throw new g("validation")}}function T(u,t){if(y(t),/\s/.test(t)||(u==="github"?t.split("/").length!==2:!/^\d+$/.test(t)&&t.split("/").length<2))throw new Error(u==="github"?"\u4ED3\u5E93\u8981\u5199\u6210 owner/repo \u5F62\u5F0F":"GitLab \u4ED3\u5E93\u5FC5\u987B\u662F\u6570\u5B57\u9879\u76EE ID \u6216 group/subgroup/project")}const Yu=B.object({schema:B.literal(1),storage:B.object({type:B.enum(["github","gitlab"]),apiBaseUrl:B.string().min(1).optional(),repo:B.string().min(1),branch:B.string().min(1).optional(),path:B.string().optional()}).strict()}).strict();class L extends Error{constructor(t){super(t),this.name="ProjectConfigError"}}function Wu(u,t=f.cwd()){const e=Pu(t,u||".initx-env.json");let n;try{n=Ru(e,"utf8")}catch(o){if(!u&&o.code==="ENOENT")return;throw new L("\u65E0\u6CD5\u8BFB\u53D6\u9879\u76EE\u914D\u7F6E\u6587\u4EF6\uFF0C\u8BF7\u68C0\u67E5 --config \u8DEF\u5F84\u4E0E\u6587\u4EF6\u6743\u9650")}let r;try{r=Yu.parse(JSON.parse(n))}catch{throw new L("\u9879\u76EE\u914D\u7F6E\u5FC5\u987B\u662F schema 1 \u7684\u5408\u6CD5 JSON\uFF0C\u4E14\u53EA\u80FD\u5305\u542B\u975E\u654F\u611F storage \u5B9A\u4F4D\u5B57\u6BB5\uFF08\u7981\u6B62 token / vars\uFF09")}try{const o={...r.storage,apiBaseUrl:_(r.storage.apiBaseUrl||b[r.storage.type])};return T(o.type,o.repo),o.path!==void 0&&y(o.path,!0),{file:e,storage:o}}catch{throw new L("\u9879\u76EE storage \u7684 API \u5730\u5740\u3001\u4ED3\u5E93\u6216\u8DEF\u5F84\u4E0D\u5408\u6CD5")}}const V="main",H="stores";function K(u,t){return`${u}:${_(t)}`}function O(u){const t=u.storage?.type||"github";if(t!=="github"&&t!=="gitlab")throw new Error("\u672C\u5730 storage.type \u5FC5\u987B\u662F github \u6216 gitlab");return{type:t,apiBaseUrl:_(u.storage?.apiBaseUrl||b[t])}}function Mu(u,t){const e=t.env??f.env,n=Wu(t.config,t.cwd),r=O(u),o=t.type||e.INITX_ENV_TYPE||n?.storage.type||r.type;if(o!=="github"&&o!=="gitlab")throw new Error("storage.type \u5FC5\u987B\u662F github \u6216 gitlab");const i=o,s=n?.storage.type===i,a=t.apiBaseUrl||e.INITX_ENV_API_BASE_URL||(s?n.storage.apiBaseUrl:void 0)||(r.type===i?r.apiBaseUrl:b[i]),E=_(a),F=r.type===i&&r.apiBaseUrl===E,p=s&&n.storage.apiBaseUrl===E,d=F?u.storage||u:{},h=p?n.storage:void 0,C={type:t.type?"override":e.INITX_ENV_TYPE?"INITX_ENV_TYPE":n?"project":"local/default",apiBaseUrl:t.apiBaseUrl?"override":e.INITX_ENV_API_BASE_URL?"INITX_ENV_API_BASE_URL":p?"project":F?"local/default":"default",repo:"",branch:"",path:""};function A($,w){const I=`INITX_ENV_${$.toUpperCase()}`,v=[[t[$]||void 0,"override"],[e[I]||void 0,I],[h?.[$],"project"],[d[$]||void 0,"local"],[w,"default"]].find(([Nu])=>Nu!==void 0);return C[$]=v[1],v[0]}return{type:i,apiBaseUrl:E,repo:A("repo",""),branch:A("branch",V),path:A("path",H),sources:C,configSource:n?.file||"local/env/default"}}function zu(u,t,e){const n=t.env??f.env;if(t.token)return{token:t.token,source:"flag"};if(n.INITX_ENV_TOKEN)return{token:n.INITX_ENV_TOKEN,source:"INITX_ENV_TOKEN"};const r=e.type==="github"&&e.apiBaseUrl===b.github;if(r){for(const i of["GH_TOKEN","GITHUB_TOKEN"])if(n[i])return{token:n[i],source:i}}const o=u.credentials?.[K(e.type,e.apiBaseUrl)];return o?{token:o,source:"config"}:r&&u.token?{token:u.token,source:"config"}:{token:"",source:"none"}}function X(u,t={}){const e=Mu(u,t);if(!e.repo)throw new Error("\u8FD8\u6CA1\u914D vault \u4ED3\u5E93\uFF0C\u8BF7\u914D\u7F6E .initx-env.json \u6216 env-config set repo <owner/repo>");T(e.type,e.repo),y(e.path,!0);const{token:n,source:r}=zu(u,t,e);if(!n)throw new Error("\u6CA1\u6709\u53EF\u7528\u7684\u5F53\u524D\u540E\u7AEF token\uFF0C\u8BF7\u8BBE\u7F6E INITX_ENV_TOKEN\u3001--token \u6216\u7ED1\u5B9A\u5F53\u524D API \u5730\u5740\u7684\u672C\u5730\u51ED\u636E");return{...e,token:n,tokenSource:r}}function qu(u){return u?"***":"(\u672A\u8BBE\u7F6E)"}function Q(u){return qu(u)}async function D(u,t={}){try{return await fetch(u,{...t,redirect:"error",signal:AbortSignal.timeout(3e4)})}catch{throw new g("network")}}async function k(u){try{return await u.json()}catch(t){throw new g(t instanceof SyntaxError?"validation":"network")}}function m(u){if(!u.ok)throw Z(u)}function pu(u){return{Authorization:`Bearer ${u}`,Accept:"application/vnd.github+json","X-GitHub-Api-Version":"2022-11-28","User-Agent":"initx-plugin-env"}}class Zu{constructor(t,e){this.location=t,T("github",t.repo),this.base=`${_(t.apiBaseUrl)}/repos/${t.repo.split("/").map(encodeURIComponent).join("/")}`,this.headers=pu(e)}capabilities={read:!0,list:!0,write:!0,delete:!0,conditionalWrite:!0};base;headers;url(t){y(t,!0);const e=t?`/${t.split("/").map(encodeURIComponent).join("/")}`:"";return`${this.base}/contents${e}?${new URLSearchParams({ref:this.location.branch})}`}async checkTarget(){const t=await D(`${this.base}/commits/${encodeURIComponent(this.location.branch)}`,{headers:this.headers});if(!await this.isEmptyRepository(t)){if(t.status===404){const e=await D(`${this.base}/commits?per_page=1`,{headers:this.headers});if(await this.isEmptyRepository(e))return;m(e)}m(t)}}async isEmptyRepository(t){return t.status!==409?!1:(await k(t))?.message==="Git Repository is empty."}async read(t){y(t);const e=await D(this.url(t),{headers:this.headers});if(e.status===404||await this.isEmptyRepository(e))return await this.checkTarget(),null;m(e);const n=await k(e);if(!n||n.type!=="file"||typeof n.sha!="string"||!n.sha||typeof n.content!="string"||n.encoding!=="base64")throw new g("validation");return{content:S.from(n.content,"base64").toString("utf8"),version:n.sha}}async list(t){const e=await D(this.url(t),{headers:this.headers});if(e.status===404||await this.isEmptyRepository(e))return await this.checkTarget(),[];m(e);const n=await k(e);if(!Array.isArray(n)||n.some(r=>!r||typeof r.name!="string"||typeof r.path!="string"||typeof r.type!="string"))throw new g("validation");return n.map(r=>({name:r.name,path:r.path,kind:r.type==="file"?"file":r.type==="dir"?"directory":"other"}))}async write(t,e,n){y(t);const r=n.condition;if(r.kind!=="create"&&(r.kind!=="update"||!r.expectedVersion))throw new g("validation");const o=await D(this.url(t),{method:"PUT",headers:{...this.headers,"Content-Type":"application/json"},body:JSON.stringify({branch:this.location.branch,message:n.message||"env: write store",content:S.from(e).toString("base64"),...r.kind==="update"?{sha:r.expectedVersion}:{}})});if([404,409,422].includes(o.status)){const i=await this.read(t);if(r.kind==="create"?i!==null:i?.version!==r.expectedVersion)throw new g("conflict",o.status)}if(!o.ok)throw Z(o)}async remove(t,e){if(y(t),!e.expectedVersion)throw new g("validation");const n=await D(this.url(t),{method:"DELETE",headers:{...this.headers,"Content-Type":"application/json"},body:JSON.stringify({branch:this.location.branch,message:e.message||"env: remove store",sha:e.expectedVersion})});if([404,409,422].includes(n.status)&&(await this.read(t))?.version!==e.expectedVersion)throw new g("conflict",n.status);m(n)}}async function Eu(u){if(u.status!==400)return;let t;try{t=await k(u)}catch(e){if(e instanceof g&&e.code==="network")throw e}if(t?.message==="You are not allowed to push into this branch")throw new g("permission",400)}class Qu{constructor(t,e){this.location=t,T("gitlab",t.repo),this.projectUrl=`${_(t.apiBaseUrl)}/projects/${encodeURIComponent(t.repo)}`,this.base=`${this.projectUrl}/repository`,this.headers={"PRIVATE-TOKEN":e,"Content-Type":"application/json"}}capabilities={read:!0,list:!0,write:!0,delete:!0,conditionalWrite:!0};projectUrl;base;headers;fileUrl(t){return y(t),`${this.base}/files/${encodeURIComponent(t)}`}async checkTarget(){const t=await D(`${this.base}/commits/${encodeURIComponent(this.location.branch)}`,{headers:this.headers});if(t.status===404){const e=await D(this.projectUrl,{headers:this.headers});m(e);const n=await k(e);if(!n||typeof n.empty_repo!="boolean")throw new g("validation");if(n.empty_repo)return!1}return m(t),!0}async read(t){const e=await D(`${this.fileUrl(t)}?${new URLSearchParams({ref:this.location.branch})}`,{headers:this.headers});if(e.status===404)return await this.checkTarget(),null;m(e);const n=await k(e);if(!n||typeof n.content!="string"||n.encoding!=="base64"||typeof n.last_commit_id!="string"||!n.last_commit_id)throw new g("validation");return{content:S.from(n.content,"base64").toString("utf8"),version:n.last_commit_id}}async list(t){y(t,!0);const e=[];if(!await this.checkTarget())return e;for(let n=1;;n++){const r=new URLSearchParams({ref:this.location.branch,per_page:"100",page:String(n),...t?{path:t}:{}}),o=await D(`${this.base}/tree?${r}`,{headers:this.headers});if(o.status===404)return await this.checkTarget(),e;m(o);const i=await k(o);if(!Array.isArray(i)||i.some(a=>!a||typeof a.name!="string"||typeof a.path!="string"||typeof a.type!="string"))throw new g("validation");e.push(...i.map(a=>({name:a.name,path:a.path,kind:a.type==="blob"?"file":a.type==="tree"?"directory":"other"})));const s=o.headers.get("x-next-page");if(!i.length||s===""||s===null&&i.length<100)return e;if(s!==null&&s!==String(n+1))throw new g("validation")}}async write(t,e,n){const r=n.condition;if(r.kind!=="create"&&(r.kind!=="update"||!r.expectedVersion))throw new g("validation");const o=await D(this.fileUrl(t),{method:r.kind==="create"?"POST":"PUT",headers:this.headers,body:JSON.stringify({branch:this.location.branch,commit_message:n.message||"env: write store",content:S.from(e).toString("base64"),encoding:"base64",...r.kind==="update"?{last_commit_id:r.expectedVersion}:{}})});if(await Eu(o),[400,404,409,422].includes(o.status)){const i=await this.read(t);if(r.kind==="create"?i!==null:i?.version!==r.expectedVersion)throw new g("conflict",o.status);if(r.kind==="update"&&o.status===400&&i?.content===e)return}if(!o.ok)throw Z(o)}async remove(t,e){if(y(t),!e.expectedVersion)throw new g("validation");const n=await D(`${this.base}/commits`,{method:"POST",headers:this.headers,body:JSON.stringify({branch:this.location.branch,commit_message:e.message||"env: remove store",actions:[{action:"delete",file_path:t,last_commit_id:e.expectedVersion}]})});if(await Eu(n),[400,404,409,422].includes(n.status)&&(await this.read(t))?.version!==e.expectedVersion)throw new g("conflict",n.status);m(n)}}const ut={github:Zu,gitlab:Qu};function J(u){const t=ut[u.type];if(!t)throw new g("unsupported");return new t(u,u.token)}function Y(u,t){if(!u.capabilities[t])throw new g("unsupported")}const uu=1,tt=B.object({repo:B.string().regex(/^[^/\s]+\/[^/\s]+$/,"\u5FC5\u987B\u662F owner/repo \u5F62\u5F0F"),env:B.string().nullish()}),et=B.object({schema:B.number().int().positive().default(uu),vars:B.record(B.string(),B.string()).default({}),targets:B.object({envFiles:B.array(B.string().min(1)).optional(),secrets:B.array(tt).optional()}).optional()});function fu(){return{schema:uu,vars:{}}}function N(u){const t=u.trim().replace(/\.json$/i,"");if(!t)throw new Error("store \u540D\u4E0D\u80FD\u4E3A\u7A7A");if(t.includes("/")||t.includes("\\"))throw new Error(`store \u540D\u4E0D\u80FD\u5305\u542B\u8DEF\u5F84\u5206\u9694\u7B26\uFF1A"${u}"`);if(t==="."||t==="..")throw new Error(`store \u540D\u4E0D\u80FD\u662F "${t}"`);if(/[\u0000-\u001F\u007F]/.test(t))throw new Error("store \u540D\u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26");if(t.length>100)throw new Error("store \u540D\u592A\u957F\uFF08\u4E0A\u9650 100 \u5B57\u7B26\uFF09");return t}function nt(u){return/^[A-Z_]\w*$/i.test(u)?u.toUpperCase().startsWith("GITHUB_")?"GITHUB_ \u524D\u7F00\u662F GitHub \u4FDD\u7559\u7684":null:"\u53EA\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u4E14\u4E0D\u80FD\u4EE5\u6570\u5B57\u5F00\u5934"}function rt(u){return/^[A-Z_][\w.-]*$/i.test(u)}function hu(u,t){const e=N(t),n=(u||"").trim().replace(/^\/+|\/+$/g,""),r=n?`${n}/${e}.json`:`${e}.json`;return y(r),r}function ot(u,t){let e;try{e=JSON.parse(u)}catch{throw new Error(`store "${t}" \u4E0D\u662F\u5408\u6CD5 JSON`)}const n=et.safeParse(e);if(!n.success)throw new Error(`store "${t}" \u7ED3\u6784\u4E0D\u5408\u6CD5\uFF1A${n.error.issues.map(r=>`${r.path.join(".")||"(root)"} ${r.message}`).join("; ")}`);return n.data}function it(u){return`${JSON.stringify({...u,schema:u.schema??uu},null,2)}
2
+ `}async function tu(u,t){Y(u,"list");const e=(t||"").trim().replace(/^\/+|\/+$/g,"");return(await u.list(e)).filter(n=>n.kind==="file"&&n.name.toLowerCase().endsWith(".json")).map(n=>n.name.replace(/\.json$/i,"")).sort((n,r)=>n.localeCompare(r))}async function U(u,t,e){const n=hu(t,e);Y(u,"read");const r=await u.read(n);if(!r)return null;const o=N(e);return{name:o,path:n,version:r.version,store:ot(r.content,o)}}async function eu(u,t,e,n,r,o){Y(u,"write"),Y(u,"conditionalWrite"),await u.write(hu(t,e),it(n),{message:r,condition:o===void 0?{kind:"create"}:{kind:"update",expectedVersion:o}})}function du(u,t){const e={added:[],updated:[],unchanged:[]};for(const[n,r]of Object.entries(t)){const o=u.vars[n];o===void 0?(u.vars[n]=r,e.added.push(n)):o===r?e.unchanged.push(n):(u.vars[n]=r,e.updated.push(n))}return e}const gu=/^export[ \t]+/,st=/^([^=]*)=(.*)$/;function at(u){const t=u.replace(/[ \t]+$/,"");return t===""||/^[ \t]/.test(t)?null:t}const ct=/^[ \t]*#/;function wu(u){return typeof u=="object"&&u!==null&&u.code==="ENOENT"}async function Ft(u){try{return await Ou(u)}catch(t){if(wu(t))return null;throw t}}function lt(u){return u.replace(/\\([nrt"\\])/g,(t,e)=>e==="n"?`
3
+ `:e==="r"?"\r":e==="t"?" ":e)}function pt(u){const t=u.replace(/^[ \t]+/,"");for(const e of t.split(`
4
+ `)){const n=/[ \t]#/.exec(e);if(n!==null)return e.slice(0,n.index).replace(/[ \t]+$/,"")}return t.replace(/[ \t]+$/,"")}function Et(u){if(u==="")return[];const t=u.split(/\r?\n/);return u.endsWith(`
5
+ `)&&t.pop(),t}function Cu(u){for(let t=0;t<u.length;t+=1){if(u[t]==="\\"){t+=1;continue}if(u[t]==='"')return t}return-1}function ft(u,t){const e=u[t];if(ct.test(e))return null;const n=gu.test(e),r=st.exec(n?e.replace(gu,""):e);if(r===null)return null;const o=at(r[1]);if(o===null)return null;const i=r[2];let s=t,a="none",E;if(i.startsWith('"')){let F=i.slice(1),p=Cu(F);for(;p===-1&&s+1<u.length;)s+=1,F+=`
6
+ ${u[s]}`,p=Cu(F);a="double",E=lt(p===-1?F:F.slice(0,p))}else if(i.startsWith("'")){const F=i.indexOf("'",1);a="single",E=F===-1?i.slice(1):i.slice(1,F)}else E=pt(i);return{key:o,value:E,exportPrefix:n,quote:a,raw:e,startLine:t,endLine:s}}function W(u){const t=u.includes(`\r
7
7
  `)?`\r
8
8
  `:`
9
9
  `,e=u.endsWith(`
10
- `),n=lt(u),r=new Map,o=[],i=[];for(let s=0;s<n.length;){const a=Et(n,s);if(a===null){s+=1;continue}r.has(a.key)&&!o.includes(a.key)&&o.push(a.key),r.set(a.key,a.value),i.push(a),s=a.endLine+1}return{lines:n,pairs:r,duplicates:o,eol:t,trailingNewline:e,entries:i}}const pt=/[\s"'\\#$`]/;function ft(u){return u!==""&&!pt.test(u)}function ht(u){return ft(u)?u:`"${u.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`}function eu(u,t,e){return`${e?"export ":""}${u}=${ht(t)}`}function Au(u,t,e){return`${u.join(t)}${e?t:""}`}function Bu(u,t){const{pairs:e}=Y(u),n=[],r=[],o=[],i=new Map;for(const[s,a]of Object.entries(t))i.set(s,a),e.has(s)?e.get(s)===a?o.push(s):r.push(s):n.push(s);return{added:n,updated:r,unchanged:o,target:i}}function dt(u,t){if(u===""){const c=gt(t);return{content:c,added:Object.keys(t),updated:[],unchanged:[],duplicates:[],changed:c!==u}}const e=Y(u),{added:n,updated:r,unchanged:o,target:i}=Bu(u,t),s=e.lines,a=new Map;e.entries.forEach((c,l)=>a.set(c.key,l));for(let c=e.entries.length-1;c>=0;c-=1){const l=e.entries[c];if(a.get(l.key)!==c)continue;const h=i.get(l.key);if(h===void 0||h===l.value)continue;const p=eu(l.key,h,l.exportPrefix);s.splice(l.startLine,l.endLine-l.startLine+1,p)}if(n.length>0){s.length>0&&s[s.length-1].trim()!==""&&s.push("");for(const c of n)s.push(eu(c,t[c],!1))}const E=Au(s,e.eol,e.trailingNewline);return{content:E,added:n,updated:r,unchanged:o,duplicates:e.duplicates,changed:E!==u}}function gt(u,t=`
11
- `){const e=Object.entries(u).map(([n,r])=>eu(n,r,!1));return e.length===0?"":Au(e,t,!0)}function wt(u,t){const{added:e,updated:n,unchanged:r}=Bu(u,t),o=[...Y(u).pairs.keys()].filter(i=>!(i in t));return{added:e,updated:n,unchanged:r,localOnly:o}}async function nu(u){try{return await su(u,"utf8")}catch(t){if(gu(t))return null;throw t}}async function At(u,t){const e=await at(u);if(e!==null&&e.isFile()){if(await su(u,"utf8")!==t){const n=`${u}.bak`;return await Iu(u,n),await au(u,t,"utf8"),{backupPath:n}}return{backupPath:null}}return await au(u,t,"utf8"),{backupPath:null}}function Du(){return f.env.GITHUB_ACTIONS==="true"?!0:typeof f.env.GITHUB_ENV=="string"&&f.env.GITHUB_ENV.length>0}function Bt(u){let t=`EOF_${cu(4).toString("hex")}`;for(;u.includes(t);)t=`EOF_${cu(4).toString("hex")}`;return t}function Dt(u){return Object.entries(u).map(([t,e])=>{if(!e.includes(`
12
- `))return`${t}=${e}`;const n=Bt(e);return[`${t}<<${n}`,e,n].join(`
10
+ `),n=Et(u),r=new Map,o=[],i=[];for(let s=0;s<n.length;){const a=ft(n,s);if(a===null){s+=1;continue}r.has(a.key)&&!o.includes(a.key)&&o.push(a.key),r.set(a.key,a.value),i.push(a),s=a.endLine+1}return{lines:n,pairs:r,duplicates:o,eol:t,trailingNewline:e,entries:i}}const ht=/[\s"'\\#$`]/;function dt(u){return u!==""&&!ht.test(u)}function gt(u){return dt(u)?u:`"${u.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t")}"`}function nu(u,t,e){return`${e?"export ":""}${u}=${gt(t)}`}function Bu(u,t,e){return`${u.join(t)}${e?t:""}`}function Au(u,t){const{pairs:e}=W(u),n=[],r=[],o=[],i=new Map;for(const[s,a]of Object.entries(t))i.set(s,a),e.has(s)?e.get(s)===a?o.push(s):r.push(s):n.push(s);return{added:n,updated:r,unchanged:o,target:i}}function wt(u,t){if(u===""){const F=Ct(t);return{content:F,added:Object.keys(t),updated:[],unchanged:[],duplicates:[],changed:F!==u}}const e=W(u),{added:n,updated:r,unchanged:o,target:i}=Au(u,t),s=e.lines,a=new Map;e.entries.forEach((F,p)=>a.set(F.key,p));for(let F=e.entries.length-1;F>=0;F-=1){const p=e.entries[F];if(a.get(p.key)!==F)continue;const d=i.get(p.key);if(d===void 0||d===p.value)continue;const h=nu(p.key,d,p.exportPrefix);s.splice(p.startLine,p.endLine-p.startLine+1,h)}if(n.length>0){s.length>0&&s[s.length-1].trim()!==""&&s.push("");for(const F of n)s.push(nu(F,t[F],!1))}const E=Bu(s,e.eol,e.trailingNewline);return{content:E,added:n,updated:r,unchanged:o,duplicates:e.duplicates,changed:E!==u}}function Ct(u,t=`
11
+ `){const e=Object.entries(u).map(([n,r])=>nu(n,r,!1));return e.length===0?"":Bu(e,t,!0)}function Bt(u,t){const{added:e,updated:n,unchanged:r}=Au(u,t),o=[...W(u).pairs.keys()].filter(i=>!(i in t));return{added:e,updated:n,unchanged:r,localOnly:o}}async function ru(u){try{return await au(u,"utf8")}catch(t){if(wu(t))return null;throw t}}async function At(u,t){const e=await Ft(u);if(e!==null&&e.isFile()){if(await au(u,"utf8")!==t){const n=`${u}.bak`;return await Su(u,n),await cu(u,t,"utf8"),{backupPath:n}}return{backupPath:null}}return await cu(u,t,"utf8"),{backupPath:null}}function Du(){return f.env.GITHUB_ACTIONS==="true"?!0:typeof f.env.GITHUB_ENV=="string"&&f.env.GITHUB_ENV.length>0}function Dt(u){let t=`EOF_${Fu(4).toString("hex")}`;for(;u.includes(t);)t=`EOF_${Fu(4).toString("hex")}`;return t}function yt(u){return Object.entries(u).map(([t,e])=>{if(!e.includes(`
12
+ `))return`${t}=${e}`;const n=Dt(e);return[`${t}<<${n}`,e,n].join(`
13
13
  `)}).join(`
14
- `)}const Ct=/[\s'"$]/,yt=/[\\"$`]/g;function mt(u){return Object.entries(u).map(([t,e])=>{if(e.includes(`
15
- `)||e.includes("\r")){const n=e.replace(yt,r=>`\\${r}`).replace(/\r\n|\r|\n/g,"\\n");return`${t}="${n}"`}return Ct.test(e)?`${t}='${e.replace(/'/g,"'\\''")}'`:`${t}=${e}`}).join(`
16
- `)}function vt(u){if(u.includes(`
17
- `)||u.includes("\r"))for(const t of u.split(/\r?\n/))t!==""&&console.log(`::add-mask::${t}`);console.log(`::add-mask::${u}`)}function $t(u,t={}){const{forceStdout:e=!1,mask:n=!0}=t,r=Object.keys(u),o=[];if(n&&r.length>0&&Du())for(const a of r)vt(u[a]),o.push(a);const i=e?void 0:f.env.GITHUB_ENV;if(i){const a=Dt(u);return a!==""&&ju(i,`
18
- ${a}`,{encoding:"utf8"}),{target:"github_env",injected:r,masked:o}}const s=mt(u);return s!==""&&console.log(s),{target:"stdout",injected:r,masked:o}}const bt=/^\.env(?:\..+)?$/,kt=[".bak",".example",".sample",".template",".keys",".enc"];async function xt(u,t){const[e="list",...n]=t;switch(e){case"list":case"ls":return Tt(u);case"pull":return It(u,n);case"set":return Ut(u,n);case"push":return Ot(u,n);case"setup":return Gt(u,n);default:throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4 "${e}"\uFF0C\u53EF\u7528\uFF1Alist | pull | set | push | setup | apply\uFF08npx initx env help\uFF09`)}}function O(u,t={}){const e=K(u.store,{token:u.options.string("token"),config:P(u.options),repo:t.repo});return{config:e,client:X(e)}}async function Tt(u){const{config:t,client:e}=O(u),n=await uu(e,t.path);if(!n.length){F.warn(`${t.repo} \u7684 ${t.path}/ \u4E0B\u8FD8\u6CA1\u6709 store`),F.info("\u5EFA\u4E00\u4E2A\uFF1Anpx initx env set <\u540D\u5B57> KEY=value");return}F.info(`${t.repo} \xB7 ${t.path}/ \u5171 ${n.length} \u4E2A store\uFF1A`);for(const r of n)F.info(` - ${r}`)}async function Cu(u,t,e){if(e)return T(e);const n=await uu(u,t);if(!n.length)throw new Error("\u4ED3\u5E93\u91CC\u8FD8\u6CA1\u6709 store\u3002\u5148\u5EFA\u4E00\u4E2A\uFF1Anpx initx env set <\u540D\u5B57> KEY=value");if(n.length===1)return n[0];if(!f.stdin.isTTY)throw new Error(`\u6709\u591A\u4E2A store\uFF0C\u975E\u4EA4\u4E92\u73AF\u5883\u4E0B\u5FC5\u987B\u6307\u5B9A\u540D\u5B57\uFF1A
14
+ `)}const mt=/[\s'"$]/,$t=/[\\"$`]/g;function vt(u){return Object.entries(u).map(([t,e])=>{if(e.includes(`
15
+ `)||e.includes("\r")){const n=e.replace($t,r=>`\\${r}`).replace(/\r\n|\r|\n/g,"\\n");return`${t}="${n}"`}return mt.test(e)?`${t}='${e.replace(/'/g,"'\\''")}'`:`${t}=${e}`}).join(`
16
+ `)}function bt(u){if(u.includes(`
17
+ `)||u.includes("\r"))for(const t of u.split(/\r?\n/))t!==""&&console.log(`::add-mask::${t}`);console.log(`::add-mask::${u}`)}function kt(u,t={}){const{forceStdout:e=!1,mask:n=!0}=t,r=Object.keys(u),o=[];if(n&&r.length>0&&Du())for(const a of r)bt(u[a]),o.push(a);const i=e?void 0:f.env.GITHUB_ENV;if(i){const a=yt(u);return a!==""&&Gu(i,`
18
+ ${a}`,{encoding:"utf8"}),{target:"github_env",injected:r,masked:o}}const s=vt(u);return s!==""&&console.log(s),{target:"stdout",injected:r,masked:o}}function c(u,t,e="stdout"){return f.env.NO_COLOR!==void 0||f.env.FORCE_COLOR==="0"||!f[e].isTTY&&!f.env.FORCE_COLOR?u:ju(u)[t]().toString()}function xt(u){const t=u instanceof Error&&u.message?u.message:"\u547D\u4EE4\u6267\u884C\u5931\u8D25";f.stderr.write(`${c(t,"red","stderr")}
19
+ `),f.exitCode=1}const _t=/^\.env(?:\..+)?$/,Tt=[".bak",".example",".sample",".template",".keys",".enc"];async function Nt(u,t){const[e="list",...n]=t;switch(e){case"list":case"ls":return It(u);case"pull":return Ut(u,n);case"set":return Rt(u,n);case"push":return Gt(u,n);case"setup":return Lt(u,n);default:throw new Error(`\u672A\u77E5\u5B50\u547D\u4EE4 "${e}"\uFF0C\u53EF\u7528\uFF1Alist | pull | set | push | setup | apply\uFF08npx initx env help\uFF09`)}}function j(u,t={}){const e=X(u.store,{token:u.options.string("token"),config:P(u.options),repo:t.repo});return{config:e,client:J(e)}}async function It(u){const{config:t,client:e}=j(u),n=await tu(e,t.path);if(!n.length){l.warn(c(`${t.repo} \u7684 ${t.path}/ \u4E0B\u8FD8\u6CA1\u6709 store`,"yellow")),l.info("\u5EFA\u4E00\u4E2A\uFF1Anpx initx env set <\u540D\u5B57> KEY=value");return}l.info(`${c(t.repo,"blue")} \xB7 ${c(`${t.path}/`,"blue")} \u5171 ${n.length} \u4E2A store\uFF1A`);for(const r of n)l.info(` - ${c(r,"blue")}`)}async function yu(u,t,e){if(e)return N(e);const n=await tu(u,t);if(!n.length)throw new Error("\u4ED3\u5E93\u91CC\u8FD8\u6CA1\u6709 store\u3002\u5148\u5EFA\u4E00\u4E2A\uFF1Anpx initx env set <\u540D\u5B57> KEY=value");if(n.length===1)return n[0];if(!f.stdin.isTTY)throw new Error(`\u6709\u591A\u4E2A store\uFF0C\u975E\u4EA4\u4E92\u73AF\u5883\u4E0B\u5FC5\u987B\u6307\u5B9A\u540D\u5B57\uFF1A
19
20
  ${n.join(`
20
- `)}`);return b.search("\u9009\u4E00\u4E2A store",n)}async function ru(u,t,e){const n=await U(u,t,e);if(!n)throw new Error(`\u4ED3\u5E93\u91CC\u6CA1\u6709 store "${e}"\u3002\u7528 npx initx env list \u770B\u770B\u6709\u54EA\u4E9B`);return n}async function _t(u,t){const e=u.options.string("to");if(e)return e.split(",").map(i=>i.trim()).filter(Boolean);const n=t.store.targets?.envFiles;if(n?.length)return n;const r=await Nt();if(r.length===1)return r;if(r.length===0){if(!f.stdin.isTTY)return[".env.local"];if(!await b.confirm("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 .env \u6587\u4EF6\uFF0C\u65B0\u5EFA .env.local\uFF1F"))throw new Error("\u5DF2\u53D6\u6D88\uFF08\u4E5F\u53EF\u4EE5\u7528 --to <\u6587\u4EF6> \u6307\u5B9A\u76EE\u6807\uFF09");return[".env.local"]}if(!f.stdin.isTTY)throw new Error(`\u5F53\u524D\u76EE\u5F55\u6709\u591A\u4E2A .env \u6587\u4EF6\uFF0C\u975E\u4EA4\u4E92\u73AF\u5883\u4E0B\u8BF7\u7528 --to \u6307\u5B9A\uFF1A
21
+ `)}`);return x.search("\u9009\u4E00\u4E2A store",n)}async function ou(u,t,e){const n=await U(u,t,e);if(!n)throw new Error(`\u4ED3\u5E93\u91CC\u6CA1\u6709 store "${e}"\u3002\u7528 npx initx env list \u770B\u770B\u6709\u54EA\u4E9B`);return n}async function St(u,t){const e=u.options.string("to");if(e)return e.split(",").map(i=>i.trim()).filter(Boolean);const n=t.store.targets?.envFiles;if(n?.length)return n;const r=await Ot();if(r.length===1)return r;if(r.length===0){if(!f.stdin.isTTY)return[".env.local"];if(!await x.confirm("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 .env \u6587\u4EF6\uFF0C\u65B0\u5EFA .env.local\uFF1F"))throw new Error("\u5DF2\u53D6\u6D88\uFF08\u4E5F\u53EF\u4EE5\u7528 --to <\u6587\u4EF6> \u6307\u5B9A\u76EE\u6807\uFF09");return[".env.local"]}if(!f.stdin.isTTY)throw new Error(`\u5F53\u524D\u76EE\u5F55\u6709\u591A\u4E2A .env \u6587\u4EF6\uFF0C\u975E\u4EA4\u4E92\u73AF\u5883\u4E0B\u8BF7\u7528 --to \u6307\u5B9A\uFF1A
21
22
  ${r.join(`
22
- `)}`);const o=await b.select("\u5199\u5230\u54EA\u4E2A\u6587\u4EF6",r);return[r[o]]}async function Nt(){return(await Uu(f.cwd(),{withFileTypes:!0})).filter(u=>u.isFile()&&bt.test(u.name)).map(u=>u.name).filter(u=>!kt.some(t=>u.endsWith(t))).sort((u,t)=>{const e=n=>n===".env.local"?0:n===".env"?1:2;return e(u)-e(t)||u.localeCompare(t)})}async function It(u,t){const{config:e,client:n}=O(u),r=await Cu(n,e.path,t[0]),o=await ru(n,e.path,r),i=o.store.vars,s=Object.keys(i);if(!s.length){F.warn(`store "${r}" \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF`);return}const a=await _t(u,o),E=u.options.boolean("dry-run");for(const c of a){const l=await nu(c)??"",h=dt(l,i);if(!h.changed){F.info(`${c}: \u5DF2\u7ECF\u662F\u6700\u65B0\u7684\uFF08${s.length} \u4E2A\u53D8\u91CF\uFF0C\u65E0\u9700\u6539\u52A8\uFF09`);continue}if(E){const w=wt(l,i);F.info(`${c}\uFF08--dry-run\uFF0C\u672A\u5199\u5165\uFF09\uFF1A`);for(const B of w.added)F.info(` + ${B}`);for(const B of w.updated)F.info(` ~ ${B}`);continue}const{backupPath:p}=await At(c,h.content);F.success(`${c}: \u65B0\u589E ${h.added.length} \xB7 \u66F4\u65B0 ${h.updated.length} \xB7 \u672A\u53D8 ${h.unchanged.length}`),p&&F.info(` \u65E7\u6587\u4EF6\u5907\u4EFD\u5728 ${p}`),h.duplicates.length&&F.warn(` \u6CE8\u610F\uFF1A${h.duplicates.join(", ")} \u5728\u6587\u4EF6\u91CC\u51FA\u73B0\u591A\u6B21\uFF0C\u53EA\u66F4\u65B0\u4E86\u6700\u540E\u4E00\u884C`)}}function St(u){const t={};for(const e of u){const n=e.indexOf("=");if(n<=0)throw new Error("\u53C2\u6570\u8981\u5199\u6210 KEY=value \u5F62\u5F0F");const r=e.slice(0,n).trim(),o=e.slice(n+1);if(!et(r))throw new Error(`\u53D8\u91CF\u540D\u4E0D\u5408\u6CD5\uFF1A"${r}"`);t[r]=o}if(!Object.keys(t).length)throw new Error("\u81F3\u5C11\u7ED9\u4E00\u4E2A KEY=value");return t}async function Ut(u,t){const[e,...n]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env set <store \u540D> KEY=value [KEY2=value2 ...]");const r=T(e),o=St(n),{config:i,client:s}=O(u),a=await U(s,i.path,r),E=a?.store??pu(),c=hu(E,o);if(!c.added.length&&!c.updated.length){F.info(`store "${r}" \u65E0\u9700\u6539\u52A8\uFF08${c.unchanged.length} \u4E2A\u53D8\u91CF\u503C\u76F8\u540C\uFF09`);return}await tu(s,i.path,r,E,`env: set ${Object.keys(o).join(", ")} in ${r}`,a?.version),F.success(`store "${r}" \u5DF2\u66F4\u65B0\uFF1A\u65B0\u589E ${c.added.length} \xB7 \u4FEE\u6539 ${c.updated.length}`);for(const l of c.added)F.info(` + ${l}`);for(const l of c.updated)F.info(` ~ ${l}`)}async function Ot(u,t){const[e]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env push <store \u540D> [--from .env.local] [--prune] [--force]");const n=T(e),r=u.options.string("from")??await jt(),o=await nu(r);if(o===null)throw new Error(`\u627E\u4E0D\u5230\u6587\u4EF6 "${r}"\uFF08\u7528 --from \u6307\u5B9A\uFF09`);const i=Object.fromEntries(Y(o).pairs);if(!Object.keys(i).length)throw new Error(`"${r}" \u91CC\u6CA1\u89E3\u6790\u51FA\u4EFB\u4F55 KEY=value`);const{config:s,client:a}=O(u),E=await U(a,s.path,n),c=E?.store??pu(),l=hu(c,i),h=[];if(u.options.boolean("prune"))for(const w of Object.keys(c.vars))w in i||(delete c.vars[w],h.push(w));if(!l.added.length&&!l.updated.length&&!h.length){F.info(`store "${n}" \u65E0\u9700\u6539\u52A8\uFF08${r} \u91CC\u7684\u503C\u90FD\u4E00\u6837\uFF09`);return}const p=`env: push ${n} from ${r}`;try{await tu(a,s.path,n,c,p,E?.version)}catch(w){if(!Ku(w)||!u.options.boolean("force"))throw w;const B=await ru(a,s.path,n);F.warn("\u8FDC\u7AEF\u5DF2\u66F4\u65B0\uFF0C--force\uFF1A\u4EE5\u672C\u5730\u6587\u4EF6\u4E3A\u51C6\u91CD\u65B0\u5199\u5165"),await tu(a,s.path,n,c,p,B.version)}F.success(`store "${n}" \u5DF2\u66F4\u65B0\uFF1A\u65B0\u589E ${l.added.length} \xB7 \u4FEE\u6539 ${l.updated.length}${h.length?` \xB7 \u5220\u9664 ${h.length}`:""}`)}async function jt(){for(const u of[".env.local",".env"])if(await nu(u)!==null)return u;throw new Error("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 .env.local / .env\uFF08\u7528 --from \u6307\u5B9A\u6587\u4EF6\uFF09")}async function Gt(u,t){const{config:e,client:n}=O(u),r=await Cu(n,e.path,t[0]),o=(await ru(n,e.path,r)).store.vars;if(!Object.keys(o).length)throw new Error(`store "${r}" \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF`);if(u.options.boolean("json")){console.log(JSON.stringify(o)),F.info(`\u5DF2\u8F93\u51FA ${Object.keys(o).length} \u4E2A\u53D8\u91CF\uFF08JSON\uFF09`);return}const i=$t(o,{forceStdout:u.options.boolean("stdout"),mask:!u.options.boolean("no-mask")});if(i.target==="github_env"){F.success(`\u5DF2\u6CE8\u5165\u672C\u6B21 job \u7684\u540E\u7EED\u6B65\u9AA4\uFF08${i.injected.length} \u4E2A\u53D8\u91CF\uFF0C${i.masked.length} \u4E2A\u5DF2\u8131\u654F\uFF09`);return}Du()||F.warn("\u5F53\u524D\u4E0D\u5728 GitHub Actions \u91CC\uFF0C\u53D8\u91CF\u6253\u5230 stdout\uFF08\u53EF\u4EE5 eval \u6216\u91CD\u5B9A\u5411\uFF09")}const yu=32;let ou;function Pt(){return ou||(ou=Fu.ready.then(()=>Fu)),ou}function Rt(u,t){let e;try{e=u.from_base64(t.trim(),u.base64_variants.ORIGINAL)}catch{throw new Error("GitHub \u516C\u94A5\u89E3\u7801\u5931\u8D25\uFF1A\u5B83\u4E0D\u662F\u5408\u6CD5\u7684 base64\uFF08ORIGINAL \u53D8\u4F53\uFF09\u5B57\u7B26\u4E32\uFF1B\u8BF7\u786E\u8BA4\u4F20\u5165\u7684\u662F public-key \u63A5\u53E3\u8FD4\u56DE\u7684 key \u5B57\u6BB5\uFF0C\u800C\u4E0D\u662F key_id")}if(e.length!==yu)throw new Error(`GitHub \u516C\u94A5\u957F\u5EA6\u4E0D\u6B63\u786E\uFF1AX25519 \u516C\u94A5\u5FC5\u987B\u662F ${yu} \u5B57\u8282\uFF0C\u5B9E\u9645 ${e.length} \u5B57\u8282\u3002 \u8FD9\u79CD\u60C5\u51B5\u901A\u5E38\u662F key_id \u4E0E key \u4E24\u4E2A\u5B57\u6BB5\u5F04\u53CD\u4E86\uFF08\u6216\u628A key_id \u5F53\u6210\u4E86\u516C\u94A5\uFF09\uFF1B\u8BF7\u6539\u7528 public-key \u63A5\u53E3\u8FD4\u56DE\u7684 key \u5B57\u6BB5`);return e}async function Vt(u,t){const e=await Pt(),n=Rt(e,u),r=e.crypto_box_seal(e.from_string(t),n);return e.to_base64(r,e.base64_variants.ORIGINAL)}async function mu(u,t,e={}){const n=await C(u,{...e,headers:{...lu(t),...e.headers??{}}});return v(n),n}function vu(u,t){const[e,n]=u.split("/",2),r=`https://api.github.com/repos/${encodeURIComponent(e)}/${encodeURIComponent(n)}`;return t?`${r}/environments/${encodeURIComponent(t)}/secrets`:`${r}/actions/secrets`}async function Lt(u,t,e){const n=await mu(`${vu(u,e)}/public-key`,t),r=await N(n);if(!r.key_id||!r.key)throw new Error(`\u62FF\u4E0D\u5230 ${u} \u7684\u516C\u94A5\uFF08\u8FD4\u56DE\u4F53\u91CC\u6CA1\u6709 key_id/key\uFF09`);return{keyId:r.key_id,key:r.key}}async function Ht(u,t,e,n,r={}){const{keyId:o,key:i}=await Lt(u,t,r.env),s=await Vt(i,n);return(await mu(`${vu(u,r.env)}/${encodeURIComponent(e)}`,t,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({encrypted_value:s,key_id:o})})).status===201?"created":"updated"}function Kt(u,t,e=f.env){const n=t||e.INITX_ENV_TARGET_TOKEN||(u.type==="github"&&u.apiBaseUrl===$.github?u.token:"");if(!n)throw new Error("GitHub Actions \u76EE\u6807\u9700\u8981\u72EC\u7ACB\u51ED\u636E\uFF1A--target-token \u6216 INITX_ENV_TARGET_TOKEN");return{write(r,o,i,s){return x("github",r),Ht(r,n,o,i,{env:s})}}}const Xt=48*1024;async function Jt(u,t){const[e]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env apply <store \u540D> --repo <owner/repo> [--env <\u73AF\u5883\u540D>] [--only A,B] [--dry-run]");const n=T(e),r=K(u.store,{token:u.options.string("token"),config:P(u.options)}),o=X(r),i=Kt(r,u.options.string("target-token")),s=await U(o,r.path,n);if(!s)throw new Error(`\u4ED3\u5E93\u91CC\u6CA1\u6709 store "${n}"\u3002\u7528 npx initx env list \u770B\u770B\u6709\u54EA\u4E9B`);const a=s.store.targets?.secrets?.[0],E=u.options.string("repo")??a?.repo;if(!E)throw new Error("\u8981\u6307\u5B9A\u5199\u5165\u76EE\u6807\uFF1A--repo <owner/repo>\uFF0C\u6216\u5728 store \u91CC\u5199 targets.secrets");x("github",E);const c=u.options.string("env")??a?.env??null,l=u.options.string("only")?.split(",").map(g=>g.trim()).filter(Boolean),h=Object.entries(s.store.vars).filter(([g])=>!l||l.includes(g));if(!h.length)throw new Error(l?.length?`--only \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF\u547D\u4E2D store "${n}"`:`store "${n}" \u91CC\u6CA1\u6709\u53D8\u91CF`);const p=[];for(const[g,_]of h){const m=tt(g);if(m){p.push(`${g} \u2014 \u540D\u5B57\u4E0D\u5408\u6CD5\uFF1A${m}`);continue}I.byteLength(_,"utf8")>Xt&&p.push(`${g} \u2014 \u503C\u8D85\u8FC7 48 KB \u4E0A\u9650`)}if(p.length){F.error("\u8FD9\u4E9B\u53D8\u91CF\u4E0D\u80FD\u5199\u8FDB Actions secrets\uFF1A");for(const g of p)F.error(` ${g}`);if(!u.options.boolean("skip-invalid"))throw new Error(`\u6709 ${p.length} \u4E2A\u53D8\u91CF\u4E0D\u5408\u6CD5\uFF0C\u5DF2\u4E2D\u6B62\uFF08\u6539\u540D\u540E\u7528 --only \u6392\u9664\uFF0C\u6216\u52A0 --skip-invalid \u8DF3\u8FC7\uFF09`);F.warn("--skip-invalid\uFF1A\u8DF3\u8FC7\u8FD9\u4E9B\u53D8\u91CF")}const w=new Set(p.map(g=>g.split(" \u2014 ")[0])),B=h.filter(([g])=>!w.has(g));if(u.options.boolean("dry-run")){F.info(`--dry-run\uFF1A\u5C06\u5199\u5165 ${B.length} \u4E2A secret \u2192 ${E}${c?`\uFF08\u73AF\u5883 ${c}\uFF09`:"\uFF08\u4ED3\u5E93\u7EA7\uFF09"}`);for(const[g]of B)F.info(` ${g}`);return}F.info(`\u5199\u5165 ${E}${c?`\uFF08\u73AF\u5883 ${c}\uFF09`:"\uFF08\u4ED3\u5E93\u7EA7\uFF09"} \u2026`);const y=[];for(const[g,_]of B)try{const m=await i.write(E,g,_,c);F.success(`${g}: ${m==="created"?"\u65B0\u5EFA":"\u66F4\u65B0"}`)}catch(m){y.push(g),F.error(`${g}: \u5931\u8D25 \u2014 ${m.message}`)}if(y.length)throw new Error(`${y.length} \u4E2A secret \u5199\u5165\u5931\u8D25\uFF1A${y.join(", ")}`);F.success(`\u5B8C\u6210\uFF1A${B.length} \u4E2A secret \u2192 ${E}`),c&&F.info("\u73AF\u5883\u7EA7 secret \u9700\u8981\u8BE5 environment \u5DF2\u5B58\u5728\uFF0C\u4E14 job \u5F15\u7528\u5B83\u65F6\u624D\u53EF\u7528")}const j=["type","apiBaseUrl","repo","token","branch","path"],$u="token \u4F1A\u4EE5**\u660E\u6587**\u5B58\u5728 ~/.initx/stores/@initx-plugin/env/store.json\uFF1B\u4ECB\u610F\u7684\u8BDD\u6539\u7528\u73AF\u5883\u53D8\u91CF INITX_ENV_TOKEN\uFF0C\u6216\u6BCF\u6B21\u7528 --token \u4F20\u3002";function iu(u){return j.includes(u)}async function Yt(u,t,e){const[n="status",...r]=t;switch(n){case"setup":return Wt(u);case"set":return G(u,r);case"get":return Mt(u,r);case"list":case"ls":return zt(u);case"rm":case"remove":return qt(u,r);case"status":return Zt(u,e);default:ku()}}async function Wt(u){if(!f.stdin.isTTY)throw new Error(`setup \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\u3002\u975E\u4EA4\u4E92\u73AF\u5883\u8BF7\u7528\uFF1A
23
+ `)}`);const o=await x.select("\u5199\u5230\u54EA\u4E2A\u6587\u4EF6",r);return[r[o]]}async function Ot(){return(await Uu(f.cwd(),{withFileTypes:!0})).filter(u=>u.isFile()&&_t.test(u.name)).map(u=>u.name).filter(u=>!Tt.some(t=>u.endsWith(t))).sort((u,t)=>{const e=n=>n===".env.local"?0:n===".env"?1:2;return e(u)-e(t)||u.localeCompare(t)})}async function Ut(u,t){const{config:e,client:n}=j(u),r=await yu(n,e.path,t[0]),o=await ou(n,e.path,r),i=o.store.vars,s=Object.keys(i);if(!s.length){l.warn(c(`store "${r}" \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF`,"yellow"));return}const a=await St(u,o),E=u.options.boolean("dry-run");for(const F of a){const p=await ru(F)??"",d=wt(p,i);if(!d.changed){l.info(`${c(F,"blue")}: \u5DF2\u7ECF\u662F\u6700\u65B0\u7684\uFF08${s.length} \u4E2A\u53D8\u91CF\uFF0C\u65E0\u9700\u6539\u52A8\uFF09`);continue}if(E){const C=Bt(p,i);l.info(`${c(F,"blue")}\uFF08${c("--dry-run\uFF0C\u672A\u5199\u5165","yellow")}\uFF09\uFF1A`);for(const A of C.added)l.info(c(` + ${A}`,"green"));for(const A of C.updated)l.info(c(` ~ ${A}`,"yellow"));continue}const{backupPath:h}=await At(F,d.content);l.success(c(`${F}: \u65B0\u589E ${d.added.length} \xB7 \u66F4\u65B0 ${d.updated.length} \xB7 \u672A\u53D8 ${d.unchanged.length}`,"green")),h&&l.info(` \u65E7\u6587\u4EF6\u5907\u4EFD\u5728 ${c(h,"blue")}`),d.duplicates.length&&l.warn(c(` \u6CE8\u610F\uFF1A${d.duplicates.join(", ")} \u5728\u6587\u4EF6\u91CC\u51FA\u73B0\u591A\u6B21\uFF0C\u53EA\u66F4\u65B0\u4E86\u6700\u540E\u4E00\u884C`,"yellow"))}}function jt(u){const t={};for(const e of u){const n=e.indexOf("=");if(n<=0)throw new Error("\u53C2\u6570\u8981\u5199\u6210 KEY=value \u5F62\u5F0F");const r=e.slice(0,n).trim(),o=e.slice(n+1);if(!rt(r))throw new Error(`\u53D8\u91CF\u540D\u4E0D\u5408\u6CD5\uFF1A"${r}"`);t[r]=o}if(!Object.keys(t).length)throw new Error("\u81F3\u5C11\u7ED9\u4E00\u4E2A KEY=value");return t}async function Rt(u,t){const[e,...n]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env set <store \u540D> KEY=value [KEY2=value2 ...]");const r=N(e),o=jt(n),{config:i,client:s}=j(u),a=await U(s,i.path,r),E=a?.store??fu(),F=du(E,o);if(!F.added.length&&!F.updated.length){l.info(`store "${c(r,"blue")}" \u65E0\u9700\u6539\u52A8\uFF08${F.unchanged.length} \u4E2A\u53D8\u91CF\u503C\u76F8\u540C\uFF09`);return}await eu(s,i.path,r,E,`env: set ${Object.keys(o).join(", ")} in ${r}`,a?.version),l.success(c(`store "${r}" \u5DF2\u66F4\u65B0\uFF1A\u65B0\u589E ${F.added.length} \xB7 \u4FEE\u6539 ${F.updated.length}`,"green"));for(const p of F.added)l.info(c(` + ${p}`,"green"));for(const p of F.updated)l.info(c(` ~ ${p}`,"yellow"))}async function Gt(u,t){const[e]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env push <store \u540D> [--from .env.local] [--prune] [--force]");const n=N(e),r=u.options.string("from")??await Pt(),o=await ru(r);if(o===null)throw new Error(`\u627E\u4E0D\u5230\u6587\u4EF6 "${r}"\uFF08\u7528 --from \u6307\u5B9A\uFF09`);const i=Object.fromEntries(W(o).pairs);if(!Object.keys(i).length)throw new Error(`"${r}" \u91CC\u6CA1\u89E3\u6790\u51FA\u4EFB\u4F55 KEY=value`);const{config:s,client:a}=j(u),E=await U(a,s.path,n),F=E?.store??fu(),p=du(F,i),d=[];if(u.options.boolean("prune"))for(const C of Object.keys(F.vars))C in i||(delete F.vars[C],d.push(C));if(!p.added.length&&!p.updated.length&&!d.length){l.info(`store "${c(n,"blue")}" \u65E0\u9700\u6539\u52A8\uFF08${c(r,"blue")} \u91CC\u7684\u503C\u90FD\u4E00\u6837\uFF09`);return}const h=`env: push ${n} from ${r}`;try{await eu(a,s.path,n,F,h,E?.version)}catch(C){if(!Ju(C)||!u.options.boolean("force"))throw C;const A=await ou(a,s.path,n);l.warn(c("\u8FDC\u7AEF\u5DF2\u66F4\u65B0\uFF0C--force\uFF1A\u4EE5\u672C\u5730\u6587\u4EF6\u4E3A\u51C6\u91CD\u65B0\u5199\u5165","yellow")),await eu(a,s.path,n,F,h,A.version)}l.success(c(`store "${n}" \u5DF2\u66F4\u65B0\uFF1A\u65B0\u589E ${p.added.length} \xB7 \u4FEE\u6539 ${p.updated.length}${d.length?` \xB7 \u5220\u9664 ${d.length}`:""}`,"green"))}async function Pt(){for(const u of[".env.local",".env"])if(await ru(u)!==null)return u;throw new Error("\u5F53\u524D\u76EE\u5F55\u6CA1\u6709 .env.local / .env\uFF08\u7528 --from \u6307\u5B9A\u6587\u4EF6\uFF09")}async function Lt(u,t){const{config:e,client:n}=j(u),r=await yu(n,e.path,t[0]),o=(await ou(n,e.path,r)).store.vars;if(!Object.keys(o).length)throw new Error(`store "${r}" \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF`);if(u.options.boolean("json")){console.log(JSON.stringify(o)),l.info(`\u5DF2\u8F93\u51FA ${Object.keys(o).length} \u4E2A\u53D8\u91CF\uFF08JSON\uFF09`);return}const i=kt(o,{forceStdout:u.options.boolean("stdout"),mask:!u.options.boolean("no-mask")});if(i.target==="github_env"){l.success(c(`\u5DF2\u6CE8\u5165\u672C\u6B21 job \u7684\u540E\u7EED\u6B65\u9AA4\uFF08${i.injected.length} \u4E2A\u53D8\u91CF\uFF0C${i.masked.length} \u4E2A\u5DF2\u8131\u654F\uFF09`,"green"));return}Du()||l.warn(c("\u5F53\u524D\u4E0D\u5728 GitHub Actions \u91CC\uFF0C\u53D8\u91CF\u6253\u5230 stdout\uFF08\u53EF\u4EE5 eval \u6216\u91CD\u5B9A\u5411\uFF09","yellow"))}const mu=32;let iu;function Vt(){return iu||(iu=lu.ready.then(()=>lu)),iu}function Ht(u,t){let e;try{e=u.from_base64(t.trim(),u.base64_variants.ORIGINAL)}catch{throw new Error("GitHub \u516C\u94A5\u89E3\u7801\u5931\u8D25\uFF1A\u5B83\u4E0D\u662F\u5408\u6CD5\u7684 base64\uFF08ORIGINAL \u53D8\u4F53\uFF09\u5B57\u7B26\u4E32\uFF1B\u8BF7\u786E\u8BA4\u4F20\u5165\u7684\u662F public-key \u63A5\u53E3\u8FD4\u56DE\u7684 key \u5B57\u6BB5\uFF0C\u800C\u4E0D\u662F key_id")}if(e.length!==mu)throw new Error(`GitHub \u516C\u94A5\u957F\u5EA6\u4E0D\u6B63\u786E\uFF1AX25519 \u516C\u94A5\u5FC5\u987B\u662F ${mu} \u5B57\u8282\uFF0C\u5B9E\u9645 ${e.length} \u5B57\u8282\u3002 \u8FD9\u79CD\u60C5\u51B5\u901A\u5E38\u662F key_id \u4E0E key \u4E24\u4E2A\u5B57\u6BB5\u5F04\u53CD\u4E86\uFF08\u6216\u628A key_id \u5F53\u6210\u4E86\u516C\u94A5\uFF09\uFF1B\u8BF7\u6539\u7528 public-key \u63A5\u53E3\u8FD4\u56DE\u7684 key \u5B57\u6BB5`);return e}async function Kt(u,t){const e=await Vt(),n=Ht(e,u),r=e.crypto_box_seal(e.from_string(t),n);return e.to_base64(r,e.base64_variants.ORIGINAL)}async function $u(u,t,e={}){const n=await D(u,{...e,headers:{...pu(t),...e.headers??{}}});return m(n),n}function vu(u,t){const[e,n]=u.split("/",2),r=`https://api.github.com/repos/${encodeURIComponent(e)}/${encodeURIComponent(n)}`;return t?`${r}/environments/${encodeURIComponent(t)}/secrets`:`${r}/actions/secrets`}async function Xt(u,t,e){const n=await $u(`${vu(u,e)}/public-key`,t),r=await k(n);if(!r.key_id||!r.key)throw new Error(`\u62FF\u4E0D\u5230 ${u} \u7684\u516C\u94A5\uFF08\u8FD4\u56DE\u4F53\u91CC\u6CA1\u6709 key_id/key\uFF09`);return{keyId:r.key_id,key:r.key}}async function Jt(u,t,e,n,r={}){const{keyId:o,key:i}=await Xt(u,t,r.env),s=await Kt(i,n);return(await $u(`${vu(u,r.env)}/${encodeURIComponent(e)}`,t,{method:"PUT",headers:{"Content-Type":"application/json"},body:JSON.stringify({encrypted_value:s,key_id:o})})).status===201?"created":"updated"}function Yt(u,t,e=f.env){const n=t||e.INITX_ENV_TARGET_TOKEN||(u.type==="github"&&u.apiBaseUrl===b.github?u.token:"");if(!n)throw new Error("GitHub Actions \u76EE\u6807\u9700\u8981\u72EC\u7ACB\u51ED\u636E\uFF1A--target-token \u6216 INITX_ENV_TARGET_TOKEN");return{write(r,o,i,s){return T("github",r),Jt(r,n,o,i,{env:s})}}}const Wt=48*1024;async function Mt(u,t){const[e]=t;if(!e)throw new Error("\u7528\u6CD5\uFF1Anpx initx env apply <store \u540D> --repo <owner/repo> [--env <\u73AF\u5883\u540D>] [--only A,B] [--dry-run]");const n=N(e),r=X(u.store,{token:u.options.string("token"),config:P(u.options)}),o=J(r),i=Yt(r,u.options.string("target-token")),s=await U(o,r.path,n);if(!s)throw new Error(`\u4ED3\u5E93\u91CC\u6CA1\u6709 store "${n}"\u3002\u7528 npx initx env list \u770B\u770B\u6709\u54EA\u4E9B`);const a=s.store.targets?.secrets?.[0],E=u.options.string("repo")??a?.repo;if(!E)throw new Error("\u8981\u6307\u5B9A\u5199\u5165\u76EE\u6807\uFF1A--repo <owner/repo>\uFF0C\u6216\u5728 store \u91CC\u5199 targets.secrets");T("github",E);const F=u.options.string("env")??a?.env??null,p=u.options.string("only")?.split(",").map(w=>w.trim()).filter(Boolean),d=Object.entries(s.store.vars).filter(([w])=>!p||p.includes(w));if(!d.length)throw new Error(p?.length?`--only \u91CC\u6CA1\u6709\u4EFB\u4F55\u53D8\u91CF\u547D\u4E2D store "${n}"`:`store "${n}" \u91CC\u6CA1\u6709\u53D8\u91CF`);const h=[];for(const[w,I]of d){const v=nt(w);if(v){h.push(`${w} \u2014 \u540D\u5B57\u4E0D\u5408\u6CD5\uFF1A${v}`);continue}S.byteLength(I,"utf8")>Wt&&h.push(`${w} \u2014 \u503C\u8D85\u8FC7 48 KB \u4E0A\u9650`)}if(h.length){l.error(c("\u8FD9\u4E9B\u53D8\u91CF\u4E0D\u80FD\u5199\u8FDB Actions secrets\uFF1A","red"));for(const w of h)l.error(c(` ${w}`,"red"));if(!u.options.boolean("skip-invalid"))throw new Error(`\u6709 ${h.length} \u4E2A\u53D8\u91CF\u4E0D\u5408\u6CD5\uFF0C\u5DF2\u4E2D\u6B62\uFF08\u6539\u540D\u540E\u7528 --only \u6392\u9664\uFF0C\u6216\u52A0 --skip-invalid \u8DF3\u8FC7\uFF09`);l.warn(c("--skip-invalid\uFF1A\u8DF3\u8FC7\u8FD9\u4E9B\u53D8\u91CF","yellow"))}const C=new Set(h.map(w=>w.split(" \u2014 ")[0])),A=d.filter(([w])=>!C.has(w));if(u.options.boolean("dry-run")){l.info(`${c("--dry-run","yellow")}\uFF1A\u5C06\u5199\u5165 ${A.length} \u4E2A secret \u2192 ${c(E,"blue")}${F?`\uFF08\u73AF\u5883 ${c(F,"blue")}\uFF09`:"\uFF08\u4ED3\u5E93\u7EA7\uFF09"}`);for(const[w]of A)l.info(` ${c(w,"blue")}`);return}l.info(`\u5199\u5165 ${c(E,"blue")}${F?`\uFF08\u73AF\u5883 ${c(F,"blue")}\uFF09`:"\uFF08\u4ED3\u5E93\u7EA7\uFF09"} \u2026`);const $=[];for(const[w,I]of A)try{const v=await i.write(E,w,I,F);l.success(c(`${w}: ${v==="created"?"\u65B0\u5EFA":"\u66F4\u65B0"}`,"green"))}catch(v){$.push(w),l.error(c(`${w}: \u5931\u8D25 \u2014 ${v.message}`,"red"))}if($.length)throw new Error(`${$.length} \u4E2A secret \u5199\u5165\u5931\u8D25\uFF1A${$.join(", ")}`);l.success(c(`\u5B8C\u6210\uFF1A${A.length} \u4E2A secret \u2192 ${E}`,"green")),F&&l.info("\u73AF\u5883\u7EA7 secret \u9700\u8981\u8BE5 environment \u5DF2\u5B58\u5728\uFF0C\u4E14 job \u5F15\u7528\u5B83\u65F6\u624D\u53EF\u7528")}const R=["type","apiBaseUrl","repo","token","branch","path"],bu="token \u4F1A\u4EE5**\u660E\u6587**\u5B58\u5728 ~/.initx/stores/@initx-plugin/env/store.json\uFF1B\u4ECB\u610F\u7684\u8BDD\u6539\u7528\u73AF\u5883\u53D8\u91CF INITX_ENV_TOKEN\uFF0C\u6216\u6BCF\u6B21\u7528 --token \u4F20\u3002";function su(u){return R.includes(u)}async function zt(u,t,e){const[n="status",...r]=t;switch(n){case"setup":return qt(u);case"set":return G(u,r);case"get":return Zt(u,r);case"list":case"ls":return Qt(u);case"rm":case"remove":return ue(u,r);case"status":return te(u,e);default:xu()}}async function qt(u){if(!f.stdin.isTTY)throw new Error(`setup \u9700\u8981\u4EA4\u4E92\u5F0F\u7EC8\u7AEF\u3002\u975E\u4EA4\u4E92\u73AF\u5883\u8BF7\u7528\uFF1A
23
24
  npx initx env-config set repo <owner/repo>
24
- npx initx env-config set token <pat>`);const t=S(u),e=await b.input(`vault \u4ED3\u5E93\uFF08${t.type}\uFF09`,{default:W(u,"repo"),required:!0});G(u,["repo",e]);const n=await b.password(`${t.type} token\uFF08\u56DE\u8F66\u4FDD\u7559\u5F53\u524D\u503C\uFF09`,{mask:"*"});n&&G(u,["token",n]);const r=await b.input("\u5206\u652F",{default:W(u,"branch")||V});G(u,["branch",r||V]);const o=await b.input("store \u76EE\u5F55",{default:W(u,"path")||L});G(u,["path",o||L]),F.success("\u672C\u5730 vault \u914D\u7F6E\u5DF2\u4FDD\u5B58"),F.warn($u)}function G(u,t){const[e,...n]=t;if(!e||!iu(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config set <${j.join("|")}> <\u503C>`);const r=n.join(" ").trim();if(!r)throw new Error(`${e} \u7684\u503C\u4E0D\u80FD\u4E3A\u7A7A`);const o=S(u);if(e==="type"||e==="apiBaseUrl"){if(e==="type"&&r!=="github"&&r!=="gitlab")throw new Error("type \u5FC5\u987B\u662F github \u6216 gitlab");const i=e==="type"?r:o.type,s=e==="apiBaseUrl"?k(r):i===o.type?o.apiBaseUrl:$[i],a=o.type===i&&o.apiBaseUrl===s;u.storage={...a?u.storage||{repo:u.repo,branch:u.branch,path:u.path}:{},type:i,apiBaseUrl:s}}else e==="token"?u.storage?(u.credentials??={})[H(o.type,o.apiBaseUrl)]=r:u.token=r:(e==="repo"&&x(o.type,r),e==="path"&&D(r),u.storage?u.storage[e]=r:u[e]=r);if(e==="token"){F.success(`token \u5DF2\u4FDD\u5B58\uFF1A${Z(r)}`),F.warn($u);return}F.success(`${e} = ${r}`)}function Mt(u,t){const[e]=t;if(!e||!iu(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config get <${j.join("|")}>`);F.info(`${e} = ${bu(u,e)}`)}function zt(u){for(const t of j)F.info(`${t}: ${bu(u,t)}`)}function qt(u,t){const[e]=t;if(!e||!iu(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config rm <${j.join("|")}>`);if(e==="token"){const n=S(u);delete u.credentials?.[H(n.type,n.apiBaseUrl)],n.type==="github"&&n.apiBaseUrl===$.github&&delete u.token}else e==="type"||e==="apiBaseUrl"?delete u.storage:u.storage?delete u.storage[e]:delete u[e];F.success(`\u5DF2\u6E05\u9664 ${e}`)}async function Zt(u,t){const e=P(t);let n;try{n=K(u,{token:t.string("token"),config:e})}catch(r){if(r instanceof R)throw r;F.warn(r.message);return}if(F.info(`\u5B58\u50A8\u540E\u7AEF: ${n.type}`),F.info(`API \u5730\u5740: ${n.apiBaseUrl}`),F.info(`\u914D\u7F6E\u6765\u6E90: ${n.configSource}`),F.info(`\u5B57\u6BB5\u6765\u6E90: ${JSON.stringify(n.sources)}`),F.info(`vault \u4ED3\u5E93: ${n.repo}`),F.info(`\u5206\u652F: ${n.branch}`),F.info(`store \u76EE\u5F55: ${n.path}`),F.info(`token: ${Z(n.token)}\uFF08\u6765\u81EA ${n.tokenSource}\uFF09`),t.boolean("offline")){F.info("\uFF08--offline\uFF1A\u8DF3\u8FC7\u8FDE\u901A\u6027\u68C0\u67E5\uFF09");return}try{const r=X(n),o=await uu(r,n.path);F.success(`\u8FDE\u901A\u6B63\u5E38\uFF0C${n.path}/ \u4E0B\u6709 ${o.length} \u4E2A store`)}catch(r){F.error(`\u8FDE\u4E0D\u4E0A\u6216\u6CA1\u6743\u9650\uFF1A${r.message}`),F.warn("\u68C0\u67E5\uFF1A\u4ED3\u5E93\u3001ref\u3001\u5F53\u524D\u540E\u7AEF token \u7684\u8BFB\u53D6\u6743\u9650\u4E0E API \u5730\u5740")}}function W(u,t){const e=S(u);return t==="type"||t==="apiBaseUrl"?e[t]:t==="token"?u.credentials?.[H(e.type,e.apiBaseUrl)]||(e.type==="github"&&e.apiBaseUrl===$.github?u.token:void 0):u.storage?u.storage[t]:u[t]}function bu(u,t){const e=W(u,t);return t==="token"?Z(e||""):e??"(\u672A\u8BBE\u7F6E)"}function Qt(){ku()}function ku(){console.log(`
25
+ npx initx env-config set token <pat>`);const t=O(u),e=await x.input(`vault \u4ED3\u5E93\uFF08${t.type}\uFF09`,{default:M(u,"repo"),required:!0});G(u,["repo",e]);const n=await x.password(`${t.type} token\uFF08\u56DE\u8F66\u4FDD\u7559\u5F53\u524D\u503C\uFF09`,{mask:"*"});n&&G(u,["token",n]);const r=await x.input("\u5206\u652F",{default:M(u,"branch")||V});G(u,["branch",r||V]);const o=await x.input("store \u76EE\u5F55",{default:M(u,"path")||H});G(u,["path",o||H]),l.success(c("\u672C\u5730 vault \u914D\u7F6E\u5DF2\u4FDD\u5B58","green")),l.warn(c(bu,"yellow"))}function G(u,t){const[e,...n]=t;if(!e||!su(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config set <${R.join("|")}> <\u503C>`);const r=n.join(" ").trim();if(!r)throw new Error(`${e} \u7684\u503C\u4E0D\u80FD\u4E3A\u7A7A`);const o=O(u);if(e==="type"||e==="apiBaseUrl"){if(e==="type"&&r!=="github"&&r!=="gitlab")throw new Error("type \u5FC5\u987B\u662F github \u6216 gitlab");const i=e==="type"?r:o.type,s=e==="apiBaseUrl"?_(r):i===o.type?o.apiBaseUrl:b[i],a=o.type===i&&o.apiBaseUrl===s;u.storage={...a?u.storage||{repo:u.repo,branch:u.branch,path:u.path}:{},type:i,apiBaseUrl:s}}else e==="token"?u.storage?(u.credentials??={})[K(o.type,o.apiBaseUrl)]=r:u.token=r:(e==="repo"&&T(o.type,r),e==="path"&&y(r),u.storage?u.storage[e]=r:u[e]=r);if(e==="token"){l.success(c(`token \u5DF2\u4FDD\u5B58\uFF1A${Q(r)}`,"green")),l.warn(c(bu,"yellow"));return}l.success(`${e} = ${c(r,"green")}`)}function Zt(u,t){const[e]=t;if(!e||!su(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config get <${R.join("|")}>`);l.info(`${e} = ${c(ku(u,e),"blue")}`)}function Qt(u){for(const t of R)l.info(`${t}: ${c(ku(u,t),"blue")}`)}function ue(u,t){const[e]=t;if(!e||!su(e))throw new Error(`\u7528\u6CD5\uFF1Anpx initx env-config rm <${R.join("|")}>`);if(e==="token"){const n=O(u);delete u.credentials?.[K(n.type,n.apiBaseUrl)],n.type==="github"&&n.apiBaseUrl===b.github&&delete u.token}else e==="type"||e==="apiBaseUrl"?delete u.storage:u.storage?delete u.storage[e]:delete u[e];l.success(c(`\u5DF2\u6E05\u9664 ${e}`,"green"))}async function te(u,t){const e=P(t);let n;try{n=X(u,{token:t.string("token"),config:e})}catch(i){if(i instanceof L)throw i;l.warn(c(i.message,"yellow"));return}if(l.info(`\u5B58\u50A8\u540E\u7AEF: ${c(n.type,"blue")}`),l.info(`API \u5730\u5740: ${c(n.apiBaseUrl,"blue")}`),l.info(`\u914D\u7F6E\u6765\u6E90: ${c(n.configSource,"blue")}`),l.info(`\u5B57\u6BB5\u6765\u6E90: ${c(JSON.stringify(n.sources),"gray")}`),l.info(`vault \u4ED3\u5E93: ${c(n.repo,"blue")}`),l.info(`\u5206\u652F: ${c(n.branch,"blue")}`),l.info(`store \u76EE\u5F55: ${c(n.path,"blue")}`),l.info(`token: ${c(Q(n.token),"yellow")}\uFF08\u6765\u81EA ${n.tokenSource}\uFF09`),t.boolean("offline")){l.info(c("\uFF08--offline\uFF1A\u8DF3\u8FC7\u8FDE\u901A\u6027\u68C0\u67E5\uFF09","gray"));return}const r=J(n),o=await tu(r,n.path);l.success(c(`\u8FDE\u901A\u6B63\u5E38\uFF0C${n.path}/ \u4E0B\u6709 ${o.length} \u4E2A store`,"green"))}function M(u,t){const e=O(u);return t==="type"||t==="apiBaseUrl"?e[t]:t==="token"?u.credentials?.[K(e.type,e.apiBaseUrl)]||(e.type==="github"&&e.apiBaseUrl===b.github?u.token:void 0):u.storage?u.storage[t]:u[t]}function ku(u,t){const e=M(u,t);return t==="token"?Q(e||""):e??"(\u672A\u8BBE\u7F6E)"}function ee(){xu()}function xu(){console.log(`
25
26
  \u7528\u6CD5\uFF1Anpx initx env-config <\u547D\u4EE4>
26
27
 
27
28
  setup \u4EA4\u4E92\u5F0F\u914D\u7F6E\u5F53\u524D\u672C\u5730\u540E\u7AEF\uFF08repo / token / branch / path\uFF09
@@ -44,9 +45,9 @@ get/list/set/rm \u4EC5\u64CD\u4F5C\u672C\u5730\u914D\u7F6E\uFF1B\u5207\u6362 typ
44
45
  npx initx env-config set type gitlab
45
46
  npx initx env-config set apiBaseUrl https://gitlab.example.com/api/v4
46
47
  npx initx env-config set repo group/subgroup/vault
47
- `)}function xu(u){return 128+(Pu.signals[u]??1)}function ue(u,t,e){return new Promise(n=>{let r,o,i,s=!1;const a=p=>{const w=p.code;return{code:w==="ENOENT"?127:w==="EACCES"?126:1,errorCode:w??"UNKNOWN"}},E=p=>{s||(s=!0,clearTimeout(o),f.removeListener("SIGINT",l),f.removeListener("SIGTERM",h),n(p))},c=p=>{if(!(s||i||r.exitCode!==null||r.signalCode!==null)){i=p;try{r.kill(p)}catch{}o=setTimeout(()=>{try{r.kill("SIGKILL")}catch{}finally{r.unref(),E({code:xu(p),signal:p})}},5e3)}};function l(){c("SIGINT")}function h(){c("SIGTERM")}try{r=Ru(u,t,{env:e,stdio:"inherit",shell:!1})}catch(p){E(a(p));return}f.on("SIGINT",l),f.on("SIGTERM",h),r.once("error",p=>E(a(p))),r.once("close",(p,w)=>{const B=i??w??void 0;E(B?{code:xu(B),signal:B}:{code:p??1})})})}function te(u){if(f.exitCode=u.code,u.signal&&f.platform!=="win32"){const t=u.signal;f.once("beforeExit",()=>{try{f.kill(f.pid,t)}catch{f.exitCode=u.code}})}}const Tu="\u7528\u6CD5\uFF1Ainitx env run <store> [--config <file>] [--token <token>] -- <command> [...args]";function ee(u,t){if(u.length!==1||!u[0])throw new Error(Tu);const e=T(u[0]);if(!Array.isArray(t)||!t.every(n=>typeof n=="string")||!t[0]?.trim())throw new Error(Tu);if(t.some(n=>n.includes("\0")))throw new Error("\u547D\u4EE4\u6216\u53C2\u6570\u4E0D\u80FD\u5305\u542B NUL");return{name:e,command:t[0],args:t.slice(1)}}function ne(u,t=f.env,e=f.platform){const n={...t},r=new Set;for(const[o,i]of Object.entries(u)){if(!/^[A-Z_]\w*$/i.test(o))throw new Error(`\u53D8\u91CF\u540D ${JSON.stringify(o)} \u4E0D\u5408\u6CD5\uFF1A\u53EA\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u4E0D\u80FD\u4EE5\u6570\u5B57\u5F00\u5934`);if(typeof i!="string"||i.includes("\0"))throw new Error(`\u53D8\u91CF ${JSON.stringify(o)} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u4E14\u4E0D\u80FD\u5305\u542B NUL`);const s=e==="win32"?o.toUpperCase():o;if(r.has(s))throw new Error(`\u53D8\u91CF ${JSON.stringify(o)} \u5728 Windows \u4E0A\u5B58\u5728\u5927\u5C0F\u5199\u51B2\u7A81`);r.add(s)}if(e==="win32"){const o=new Set;for(const i of Object.keys(n)){const s=i.toUpperCase();r.has(s)||o.has(s)?delete n[i]:o.add(s)}}return{...n,...u}}async function re(u,t){let e="\u53C2\u6570";try{const n=ee(t,u.options.raw["--"]),r=new Set(["--","token","config"]);if(Object.keys(u.options.raw).some(h=>!r.has(h)))throw new Error("run \u53EA\u652F\u6301 --token / --config\uFF1B\u5B50\u8FDB\u7A0B\u53C2\u6570\u5FC5\u987B\u653E\u5728 -- \u540E");const o=u.options.raw.token;if(o!==void 0&&typeof o!="string"&&typeof o!="number")throw new Error("--token \u9700\u8981\u5355\u4E2A\u503C");const i=u.options.raw.config;if(i!==void 0&&(typeof i!="string"||!i))throw new Error("--config \u9700\u8981\u5355\u4E2A\u6587\u4EF6\u8DEF\u5F84");e="\u914D\u7F6E";const s=K(u.store,{token:u.options.string("token"),config:P(u.options)});e="\u8BFB\u53D6 store";const a=X(s),E=await U(a,s.path,n.name);if(!E)throw new Error("store \u4E0D\u5B58\u5728");e="\u53D8\u91CF\u6821\u9A8C";const c=ne(E.store.vars);e="\u542F\u52A8\u5B50\u8FDB\u7A0B";const l=await ue(n.command,n.args,c);l.errorCode&&f.stderr.write(`env run: \u542F\u52A8\u5931\u8D25\uFF08${l.errorCode}\uFF09
48
- `),te(l)}catch(n){const r=e==="\u53D8\u91CF\u6821\u9A8C"||e==="\u53C2\u6570"?`\uFF1A${n.message}`:"";f.stderr.write(`env run: ${e}\u5931\u8D25${r}
49
- `),f.exitCode=1}}const oe=["list","ls","pull","set","push","setup","apply","run","help"],ie=["setup","set","get","list","ls","rm","remove","status","help"];class se extends Nu{defaultStore={branch:V,path:L};rules=[{matching:"env",description:"Env vars from a private repo: env list | pull | set | push | setup | apply | run",optional:[void 0,...oe]},{matching:"env-config",description:"Configure GitHub/GitLab vault storage and check connectivity",optional:[void 0,...ie]}];async handle(t,...e){const n=e.filter(a=>typeof a=="string"),r=Lu(t.cliOptions,t.optionsList),o=t.store??{};if(t.key==="env-config"){if(n[0]==="help"||r.boolean("help")){Qt();return}await Yt(o,n,r);return}if(n[0]==="run"&&!r.boolean("help")&&!r.boolean("h")){await re({store:o,options:r},n.slice(1));return}if(!n.length||n[0]==="help"||r.boolean("help")||r.boolean("h")){ae();return}const[i,...s]=n;if(i==="apply"){await Jt({store:o,options:r},s);return}await xt({store:o,options:r},[i,...s])}}function ae(){console.log(`
48
+ `)}function _u(u){return 128+(Lu.signals[u]??1)}function ne(u,t,e){return new Promise(n=>{let r,o,i,s=!1;const a=h=>{const C=h.code;return{code:C==="ENOENT"?127:C==="EACCES"?126:1,errorCode:C??"UNKNOWN"}},E=h=>{s||(s=!0,clearTimeout(o),f.removeListener("SIGINT",p),f.removeListener("SIGTERM",d),n(h))},F=h=>{if(!(s||i||r.exitCode!==null||r.signalCode!==null)){i=h;try{r.kill(h)}catch{}o=setTimeout(()=>{try{r.kill("SIGKILL")}catch{}finally{r.unref(),E({code:_u(h),signal:h})}},5e3)}};function p(){F("SIGINT")}function d(){F("SIGTERM")}try{r=Vu(u,t,{env:e,stdio:"inherit",shell:!1})}catch(h){E(a(h));return}f.on("SIGINT",p),f.on("SIGTERM",d),r.once("error",h=>E(a(h))),r.once("close",(h,C)=>{const A=i??C??void 0;E(A?{code:_u(A),signal:A}:{code:h??1})})})}function re(u){if(f.exitCode=u.code,u.signal&&f.platform!=="win32"){const t=u.signal;f.once("beforeExit",()=>{try{f.kill(f.pid,t)}catch{f.exitCode=u.code}})}}const Tu="\u7528\u6CD5\uFF1Ainitx env run <store> [--config <file>] [--token <token>] -- <command> [...args]";function oe(u,t){if(u.length!==1||!u[0])throw new Error(Tu);const e=N(u[0]);if(!Array.isArray(t)||!t.every(n=>typeof n=="string")||!t[0]?.trim())throw new Error(Tu);if(t.some(n=>n.includes("\0")))throw new Error("\u547D\u4EE4\u6216\u53C2\u6570\u4E0D\u80FD\u5305\u542B NUL");return{name:e,command:t[0],args:t.slice(1)}}function ie(u,t=f.env,e=f.platform){const n={...t},r=new Set;for(const[o,i]of Object.entries(u)){if(!/^[A-Z_]\w*$/i.test(o))throw new Error(`\u53D8\u91CF\u540D ${JSON.stringify(o)} \u4E0D\u5408\u6CD5\uFF1A\u53EA\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\uFF0C\u4E0D\u80FD\u4EE5\u6570\u5B57\u5F00\u5934`);if(typeof i!="string"||i.includes("\0"))throw new Error(`\u53D8\u91CF ${JSON.stringify(o)} \u5FC5\u987B\u662F\u5B57\u7B26\u4E32\u4E14\u4E0D\u80FD\u5305\u542B NUL`);const s=e==="win32"?o.toUpperCase():o;if(r.has(s))throw new Error(`\u53D8\u91CF ${JSON.stringify(o)} \u5728 Windows \u4E0A\u5B58\u5728\u5927\u5C0F\u5199\u51B2\u7A81`);r.add(s)}if(e==="win32"){const o=new Set;for(const i of Object.keys(n)){const s=i.toUpperCase();r.has(s)||o.has(s)?delete n[i]:o.add(s)}}return{...n,...u}}async function se(u,t){let e="\u53C2\u6570";try{const n=oe(t,u.options.raw["--"]),r=new Set(["--","token","config"]);if(Object.keys(u.options.raw).some(d=>!r.has(d)))throw new Error("run \u53EA\u652F\u6301 --token / --config\uFF1B\u5B50\u8FDB\u7A0B\u53C2\u6570\u5FC5\u987B\u653E\u5728 -- \u540E");const o=u.options.raw.token;if(o!==void 0&&typeof o!="string"&&typeof o!="number")throw new Error("--token \u9700\u8981\u5355\u4E2A\u503C");const i=u.options.raw.config;if(i!==void 0&&(typeof i!="string"||!i))throw new Error("--config \u9700\u8981\u5355\u4E2A\u6587\u4EF6\u8DEF\u5F84");e="\u914D\u7F6E";const s=X(u.store,{token:u.options.string("token"),config:P(u.options)});e="\u8BFB\u53D6 store";const a=J(s),E=await U(a,s.path,n.name);if(!E)throw new Error("store \u4E0D\u5B58\u5728");e="\u53D8\u91CF\u6821\u9A8C";const F=ie(E.store.vars);e="\u542F\u52A8\u5B50\u8FDB\u7A0B";const p=await ne(n.command,n.args,F);p.errorCode&&f.stderr.write(`${c(`env run: \u542F\u52A8\u5931\u8D25\uFF08${p.errorCode}\uFF09`,"red","stderr")}
49
+ `),re(p)}catch(n){const r=e==="\u53D8\u91CF\u6821\u9A8C"||e==="\u53C2\u6570"?`\uFF1A${n.message}`:"";f.stderr.write(`${c(`env run: ${e}\u5931\u8D25${r}`,"red","stderr")}
50
+ `),f.exitCode=1}}const ae=["list","ls","pull","set","push","setup","apply","run","help"],ce=["setup","set","get","list","ls","rm","remove","status","help"];class Fe extends Iu{defaultStore={branch:V,path:H};rules=[{matching:"env",description:"Env vars from a private repo: env list | pull | set | push | setup | apply | run",optional:[void 0,...ae]},{matching:"env-config",description:"Configure GitHub/GitLab vault storage and check connectivity",optional:[void 0,...ce]}];async handle(t,...e){try{await this.dispatch(t,...e)}catch(n){xt(n)}}async dispatch(t,...e){const n=e.filter(a=>typeof a=="string"),r=Ku(t.cliOptions,t.optionsList),o=t.store??{};if(t.key==="env-config"){if(n[0]==="help"||r.boolean("help")){ee();return}await zt(o,n,r);return}if(n[0]==="run"&&!r.boolean("help")&&!r.boolean("h")){await se({store:o,options:r},n.slice(1));return}if(!n.length||n[0]==="help"||r.boolean("help")||r.boolean("h")){le();return}const[i,...s]=n;if(i==="apply"){await Mt({store:o,options:r},s);return}await Nt({store:o,options:r},[i,...s])}}function le(){console.log(`
50
51
  \u7528\u6CD5\uFF1Anpx initx env <\u547D\u4EE4>
51
52
 
52
53
  list \u5217\u51FA vault \u4ED3\u5E93\u91CC\u6240\u6709 store
@@ -83,4 +84,4 @@ get/list/set/rm \u4EC5\u64CD\u4F5C\u672C\u5730\u914D\u7F6E\uFF1B\u5207\u6362 typ
83
84
  npx initx env pull mail-peon-publish
84
85
  npx initx env setup mail-peon-publish --token "$GITHUB_TOKEN"
85
86
  npx initx env apply mail-peon-publish --repo mail-peon/mail-peon
86
- `)}export{se as default};
87
+ `)}export{Fe as default};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@initx-plugin/env",
3
3
  "type": "module",
4
- "version": "0.1.3",
4
+ "version": "0.1.4",
5
5
  "description": "initx plugin to manage env vars and secrets from private GitHub or GitLab repositories",
6
6
  "author": "imba97",
7
7
  "license": "MIT",