@pplethai/cli 0.4.0 → 0.4.2

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
@@ -109,7 +109,7 @@ echo '{ "updateCheck": false }' > ~/.config/pple/config.json # this machine
109
109
  npm install
110
110
  npm test # drives whole commands against a fake Provisioner and real git
111
111
  npm run typecheck
112
- npm run build # bundles the template and Skills, compiles to dist/
112
+ npm run build # bundles the template and Skills, then esbuild → dist/bin.js
113
113
  ```
114
114
 
115
115
  Tests run the real command path — real `git` in a temp directory, a fake
package/dist/bin.js CHANGED
@@ -1,16 +1,54 @@
1
1
  #!/usr/bin/env node
2
- import os from "node:os";
3
- import { run } from "./cli.js";
4
- import { nodeDeps } from "./node-deps.js";
5
- import { consoleOutput } from "./ui.js";
6
- const out = consoleOutput((text) => process.stdout.write(text), (text) => process.stderr.write(text));
7
- try {
8
- process.exitCode = await run(process.argv.slice(2), nodeDeps(out, os.homedir()));
9
- }
10
- catch (e) {
11
- // Not a failure the CLI knows how to explain — say so plainly instead of
12
- // dumping a stack trace on a Builder who can't act on it.
13
- process.stderr.write("เกิดข้อผิดพลาดภายใน pple CLI กรุณาส่งข้อความนี้ให้ทีมแพลตฟอร์ม:\n");
14
- process.stderr.write(`${e instanceof Error ? (e.stack ?? e.message) : String(e)}\n`);
15
- process.exitCode = 1;
16
- }
2
+ import Rr from"node:os";var s=class extends Error{constructor(r,n){super(r);this.hint=n;this.name="CliError"}hint},et=new s("\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A","\u0E23\u0E31\u0E19 `pple auth login` \u0E01\u0E48\u0E2D\u0E19"),x=new s("\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E2B\u0E21\u0E14\u0E2D\u0E32\u0E22\u0E38\u0E41\u0E25\u0E49\u0E27","\u0E23\u0E31\u0E19 `pple auth login` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07");var $=class{constructor(e,r){this.deps=e;this.token=r}deps;token;me(){return this.request("GET","/me")}app(e){return this.request("GET",`/apps/${encodeURIComponent(e)}`,{slug:e})}createApp(e){return this.request("POST","/apps",{body:{name:e}})}repoToken(e){return this.request("POST",`/apps/${encodeURIComponent(e)}/repo-token`,{slug:e})}deploys(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/deploys`,{slug:e}).then(r=>r.deploys)}env(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/env`,{slug:e}).then(r=>r.env)}metrics(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/metrics`,{slug:e})}collaborators(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/collaborators`,{slug:e}).then(r=>r.collaborators)}requests(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/requests`,{slug:e}).then(r=>r.requests)}invites(e){return this.request("GET",`/apps/${encodeURIComponent(e)}/invites`,{slug:e}).then(r=>r.invites)}setEnv(e,r,n,i){return this.request("PUT",`/apps/${encodeURIComponent(e)}/env/${encodeURIComponent(r)}`,{slug:e,body:{value:n,secret:i}})}deleteEnv(e,r){return this.request("DELETE",`/apps/${encodeURIComponent(e)}/env/${encodeURIComponent(r)}`,{slug:e,envKey:r})}async request(e,r,n={}){let i=`${this.deps.config.apiBase}${r}`,o={authorization:`Bearer ${this.token}`},u;n.body!==void 0&&(o["content-type"]="application/json",u=JSON.stringify(n.body));let a=await this.deps.fetch(i,{method:e,headers:o,body:u}).catch(()=>null);if(!a)throw new s("\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D PPLE Platform \u0E44\u0E21\u0E48\u0E44\u0E14\u0E49","\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D\u0E2D\u0E34\u0E19\u0E40\u0E17\u0E2D\u0E23\u0E4C\u0E40\u0E19\u0E47\u0E15\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07");if(a.ok)return a.status===204?void 0:await a.json();let c=await a.json().catch(()=>({}));throw me(a.status,c.error,n)}};function me(t,e,r={}){let{slug:n,envKey:i}=r;return t===401?x:e==="not_org_member"?new s("PPLE ID \u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E2D\u0E22\u0E39\u0E48\u0E43\u0E19\u0E2D\u0E07\u0E04\u0E4C\u0E01\u0E23\u0E02\u0E2D\u0E07\u0E1E\u0E23\u0E23\u0E04 \u0E08\u0E36\u0E07\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49","\u0E01\u0E23\u0E38\u0E13\u0E32\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E2B\u0E31\u0E27\u0E2B\u0E19\u0E49\u0E32\u0E17\u0E35\u0E21\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E2A\u0E34\u0E17\u0E18\u0E34\u0E4C \u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07"):e==="agreement_required"?new s("\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E02\u0E49\u0E2D\u0E15\u0E01\u0E25\u0E07\u0E1C\u0E39\u0E49\u0E1E\u0E31\u0E12\u0E19\u0E32","\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai \u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07\u0E19\u0E35\u0E49\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07"):e==="app_has_no_repo"?new s(`${n?`"${n}"`:"\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49"} \u0E22\u0E31\u0E07\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E44\u0E21\u0E48\u0E40\u0E2A\u0E23\u0E47\u0E08`,"\u0E23\u0E2D\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07 \u0E2B\u0E32\u0E01\u0E22\u0E31\u0E07\u0E40\u0E1B\u0E47\u0E19\u0E41\u0E1A\u0E1A\u0E19\u0E35\u0E49 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21"):e==="invalid_key"?new s("\u0E04\u0E35\u0E22\u0E4C\u0E19\u0E35\u0E49\u0E43\u0E0A\u0E49\u0E40\u0E1B\u0E47\u0E19\u0E0A\u0E37\u0E48\u0E2D\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49","\u0E04\u0E35\u0E22\u0E4C\u0E15\u0E49\u0E2D\u0E07\u0E02\u0E36\u0E49\u0E19\u0E15\u0E49\u0E19\u0E14\u0E49\u0E27\u0E22\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23\u0E2B\u0E23\u0E37\u0E2D\u0E02\u0E35\u0E14\u0E25\u0E48\u0E32\u0E07 \u0E15\u0E32\u0E21\u0E14\u0E49\u0E27\u0E22\u0E15\u0E31\u0E27\u0E2D\u0E31\u0E01\u0E29\u0E23 \u0E15\u0E31\u0E27\u0E40\u0E25\u0E02 \u0E2B\u0E23\u0E37\u0E2D\u0E02\u0E35\u0E14\u0E25\u0E48\u0E32\u0E07"):e==="reserved_key"?new s("\u0E04\u0E35\u0E22\u0E4C\u0E19\u0E35\u0E49\u0E16\u0E39\u0E01\u0E2A\u0E07\u0E27\u0E19\u0E44\u0E27\u0E49\u0E42\u0E14\u0E22\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21","\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E0A\u0E37\u0E48\u0E2D\u0E2D\u0E37\u0E48\u0E19 \u2014 APP_SLUG, DB, FILES, NOTIFY_* \u0E41\u0E25\u0E30 PPLE_DEPLOY_ID \u0E16\u0E39\u0E01\u0E43\u0E0A\u0E49\u0E44\u0E1B\u0E41\u0E25\u0E49\u0E27"):e==="invalid_value"?new s("\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E04\u0E48\u0E32\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08","\u0E2A\u0E48\u0E07\u0E04\u0E48\u0E32\u0E21\u0E32\u0E40\u0E1B\u0E47\u0E19 argument \u0E1C\u0E48\u0E32\u0E19 `--file` \u0E2B\u0E23\u0E37\u0E2D\u0E17\u0E32\u0E07 stdin"):t===404?i?new s(`\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32 "${i}" \u0E44\u0E27\u0E49`,"\u0E23\u0E31\u0E19 `pple env list` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E14\u0E39\u0E04\u0E48\u0E32\u0E17\u0E35\u0E48\u0E15\u0E31\u0E49\u0E07\u0E44\u0E27\u0E49"):new s(n?`\u0E44\u0E21\u0E48\u0E21\u0E35\u0E41\u0E2D\u0E1B\u0E0A\u0E37\u0E48\u0E2D "${n}" \u0E17\u0E35\u0E48\u0E40\u0E1B\u0E47\u0E19\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13`:"\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E2A\u0E34\u0E48\u0E07\u0E19\u0E35\u0E49\u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21","\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E41\u0E2D\u0E1B\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai"):t>=500||e==="sso_unavailable"?new s("PPLE Platform \u0E01\u0E33\u0E25\u0E31\u0E07\u0E21\u0E35\u0E1B\u0E31\u0E0D\u0E2B\u0E32\u0E43\u0E19\u0E02\u0E13\u0E30\u0E19\u0E35\u0E49","\u0E23\u0E2D\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07 \u0E2B\u0E32\u0E01\u0E22\u0E31\u0E07\u0E40\u0E01\u0E34\u0E14\u0E02\u0E36\u0E49\u0E19\u0E2D\u0E35\u0E01 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E41\u0E08\u0E49\u0E07\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21"):new s("PPLE Platform \u0E1B\u0E0F\u0E34\u0E40\u0E2A\u0E18\u0E04\u0E33\u0E02\u0E2D\u0E19\u0E35\u0E49",e?`\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A: ${e}`:void 0)}import D from"node:fs/promises";import ge from"node:path";var de="credentials.json",rt=384,ye=448;function T(t){return ge.join(t.configDir,de)}async function nt(t){let e=await D.readFile(T(t),"utf8").catch(()=>null);if(e===null)return null;let r;try{r=JSON.parse(e)}catch{return null}return typeof r.accessToken!="string"||r.ssoBase!==t.config.ssoBase?null:{accessToken:r.accessToken,refreshToken:typeof r.refreshToken=="string"?r.refreshToken:null,expiresAt:typeof r.expiresAt=="number"?r.expiresAt:null,ssoBase:r.ssoBase}}async function S(t,e){await D.mkdir(t.configDir,{recursive:!0,mode:ye}),await D.writeFile(T(t),`${JSON.stringify(e,null,2)}
3
+ `,{mode:rt}),await D.chmod(T(t),rt)}async function it(t){try{return await D.unlink(T(t)),!0}catch{return!1}}var we="/oauth/v2/device_authorization",st="/oauth/v2/token",he="urn:ietf:params:oauth:grant-type:device_code",at="openid profile offline_access";function F(t){return{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams(t).toString()}}function q(t){return new s(`\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D PPLE ID (${t}) \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49`,"\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D\u0E2D\u0E34\u0E19\u0E40\u0E17\u0E2D\u0E23\u0E4C\u0E40\u0E19\u0E47\u0E15\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07 `pple auth login` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07")}async function ut(t){let{ssoBase:e,clientId:r}=t.config,n=await t.fetch(`${e}${we}`,F({client_id:r,scope:at})).catch(()=>null);if(!n||!n.ok)throw q(e);let i=await n.json().catch(()=>({}));if(!i.device_code||!i.user_code||!i.verification_uri)throw q(e);return{deviceCode:i.device_code,userCode:i.user_code,verificationUri:i.verification_uri,verificationUriComplete:i.verification_uri_complete??null,expiresInMs:(i.expires_in??600)*1e3,intervalMs:(i.interval??5)*1e3}}async function lt(t,e){let{ssoBase:r,clientId:n}=t.config,i=t.now()+e.expiresInMs,o=e.intervalMs;for(;t.now()<i;){await t.sleep(o);let u=await t.fetch(`${r}${st}`,F({client_id:n,grant_type:he,device_code:e.deviceCode})).catch(()=>null);if(!u)throw q(r);let a=await u.json().catch(()=>({}));if(u.ok&&a.access_token)return pt(t,a);switch(a.error){case"authorization_pending":break;case"slow_down":o+=5e3;break;case"access_denied":throw new s("\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E16\u0E39\u0E01\u0E1B\u0E0F\u0E34\u0E40\u0E2A\u0E18\u0E43\u0E19\u0E40\u0E1A\u0E23\u0E32\u0E27\u0E4C\u0E40\u0E0B\u0E2D\u0E23\u0E4C","\u0E2B\u0E32\u0E01\u0E44\u0E21\u0E48\u0E43\u0E0A\u0E48\u0E04\u0E38\u0E13\u0E17\u0E35\u0E48\u0E1B\u0E0F\u0E34\u0E40\u0E2A\u0E18 \u0E43\u0E2B\u0E49\u0E23\u0E31\u0E19 `pple auth login` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07");case"expired_token":throw ot();default:throw new s("PPLE ID \u0E1B\u0E0F\u0E34\u0E40\u0E2A\u0E18\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A",a.error_description??"\u0E25\u0E2D\u0E07 `pple auth login` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07")}}throw ot()}function ot(){return new s("\u0E23\u0E2B\u0E31\u0E2A\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E2B\u0E21\u0E14\u0E2D\u0E32\u0E22\u0E38\u0E01\u0E48\u0E2D\u0E19\u0E44\u0E14\u0E49\u0E23\u0E31\u0E1A\u0E01\u0E32\u0E23\u0E2D\u0E19\u0E38\u0E21\u0E31\u0E15\u0E34","\u0E23\u0E31\u0E19 `pple auth login` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07 \u2014 \u0E02\u0E31\u0E49\u0E19\u0E15\u0E2D\u0E19\u0E43\u0E19\u0E40\u0E1A\u0E23\u0E32\u0E27\u0E4C\u0E40\u0E0B\u0E2D\u0E23\u0E4C\u0E15\u0E49\u0E2D\u0E07\u0E17\u0E33\u0E43\u0E2B\u0E49\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E20\u0E32\u0E22\u0E43\u0E19\u0E44\u0E21\u0E48\u0E01\u0E35\u0E48\u0E19\u0E32\u0E17\u0E35")}async function ct(t,e){let{ssoBase:r,clientId:n}=t.config,i=await t.fetch(`${r}${st}`,F({client_id:n,grant_type:"refresh_token",refresh_token:e,scope:at})).catch(()=>null);if(!i||!i.ok)return null;let o=await i.json().catch(()=>({}));return o.access_token?{...pt(t,o),refreshToken:o.refresh_token??e}:null}function pt(t,e){return{accessToken:e.access_token,refreshToken:e.refresh_token??null,expiresAt:typeof e.expires_in=="number"?t.now()+e.expires_in*1e3:null}}var ve=6e4;async function Pe(t){let e=await nt(t);if(!e)throw et;if(!(e.expiresAt!==null&&e.expiresAt-t.now()<ve))return e.accessToken;if(e.refreshToken){let n=await ct(t,e.refreshToken);if(n)return await S(t,{...n,ssoBase:t.config.ssoBase}),n.accessToken}throw x}async function p(t){return new $(t,await Pe(t))}async function ft(t){let e=await ut(t);t.out.say("\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E42\u0E14\u0E22\u0E40\u0E1B\u0E34\u0E14\u0E2B\u0E19\u0E49\u0E32\u0E19\u0E35\u0E49\u0E41\u0E25\u0E49\u0E27\u0E01\u0E23\u0E2D\u0E01\u0E23\u0E2B\u0E31\u0E2A:"),t.out.say(),t.out.say(` ${e.verificationUri}`),t.out.say(` \u0E23\u0E2B\u0E31\u0E2A: ${e.userCode}`),t.out.say(),t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E23\u0E2D\u0E43\u0E2B\u0E49\u0E04\u0E38\u0E13\u0E2D\u0E19\u0E38\u0E21\u0E31\u0E15\u0E34\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u2026"),await t.openBrowser(e.verificationUriComplete??e.verificationUri);let r=await lt(t,e);await S(t,{...r,ssoBase:t.config.ssoBase});let n=await new $(t,r.accessToken).me();t.out.say(`\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E43\u0E19\u0E0A\u0E37\u0E48\u0E2D ${n.name??n.sub} \u0E41\u0E25\u0E49\u0E27`),n.isBuilder||t.out.say("\u0E2D\u0E35\u0E01\u0E2B\u0E19\u0E36\u0E48\u0E07\u0E02\u0E31\u0E49\u0E19\u0E15\u0E2D\u0E19\u0E01\u0E48\u0E2D\u0E19\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E44\u0E14\u0E49: \u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E02\u0E49\u0E2D\u0E15\u0E01\u0E25\u0E07\u0E1C\u0E39\u0E49\u0E1E\u0E31\u0E12\u0E19\u0E32\u0E17\u0E35\u0E48 https://console.ppleth.ai")}async function mt(t){let e=await it(t);t.out.say(e?"\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E23\u0E30\u0E1A\u0E1A\u0E41\u0E25\u0E49\u0E27":"\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A")}async function G(t){let e=await(await p(t)).me();t.out.say(`\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E43\u0E19\u0E0A\u0E37\u0E48\u0E2D ${e.name??e.sub} \u0E41\u0E25\u0E49\u0E27`),e.isBuilder||t.out.say("\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E02\u0E49\u0E2D\u0E15\u0E01\u0E25\u0E07\u0E1C\u0E39\u0E49\u0E1E\u0E31\u0E12\u0E19\u0E32 \u2014 \u0E22\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai")}var R="main",Ee="x-access-token";async function d(t,e,r,n){return t.run("git",n?["-c","credential.helper=",...r]:r,{cwd:e,env:{GIT_TERMINAL_PROMPT:"0",...n?{GIT_ASKPASS:t.gitAskpass,PPLE_GIT_USER:Ee,PPLE_GIT_TOKEN:n.token}:{}}})}function gt(t){return["-c",`user.name=${t.author.name}`,"-c",`user.email=${t.author.email}`]}function dt(t){return/authentication|could not read|403|denied|not found/i.test(`${t.stdout}
4
+ ${t.stderr}`)}function yt(t,e){return new s(`\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E44\u0E21\u0E48\u0E2D\u0E19\u0E38\u0E0D\u0E32\u0E15\u0E43\u0E2B\u0E49\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E19\u0E35\u0E49${t}`,`\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E27\u0E48\u0E32\u0E41\u0E2D\u0E1B\u0E22\u0E31\u0E07\u0E40\u0E1B\u0E47\u0E19\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E2D\u0E22\u0E39\u0E48\u0E17\u0E35\u0E48 https://console.ppleth.ai \u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19 \`${e}\` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07`)}function wt(t){return new s("\u0E2D\u0E48\u0E32\u0E19\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49",t.stderr.trim())}async function k(t,e,r,n,i){let o=await d(t,e,r,i).catch(()=>{throw new s("\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E19\u0E35\u0E49\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E21\u0E37\u0E2D\u0E17\u0E35\u0E48 PPLE CLI \u0E15\u0E49\u0E2D\u0E07\u0E43\u0E0A\u0E49","\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 git (https://git-scm.com/downloads) \u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07")});if(o.code!==0)throw n(o);return o}async function ht(t,e,r,n){await k(t,t.cwd,["clone",e,r],i=>dt(i)?yt("\u0E40\u0E02\u0E49\u0E32\u0E16\u0E36\u0E07\u0E42\u0E04\u0E49\u0E14\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E04\u0E38\u0E13","pple init"):new s("\u0E14\u0E36\u0E07\u0E42\u0E04\u0E49\u0E14\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",i.stderr.trim()),n)}async function I(t,e){return(await k(t,e,["status","--porcelain"],wt)).stdout.trim()!==""}async function L(t,e,r,n){await k(t,e,["add","-A"],wt),await k(t,e,[...gt(n),"commit","-m",r],i=>new s("\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",i.stderr.trim()))}async function vt(t,e){return(await k(t,e,["rev-parse","HEAD"],n=>new s("\u0E2D\u0E48\u0E32\u0E19\u0E1B\u0E23\u0E30\u0E27\u0E31\u0E15\u0E34\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",n.stderr.trim()))).stdout.trim()}async function Pt(t,e,r){await d(t,e,["fetch","origin",R],r);let n=await d(t,e,["rev-parse","HEAD"]),i=await d(t,e,["rev-parse",`origin/${R}`]);return n.code!==0||i.code!==0?!1:n.stdout.trim()===i.stdout.trim()}async function $t(t,e,r){let n=["push","origin",`HEAD:${R}`],i=await d(t,e,n,r);if(i.code===0)return;let o=`${i.stdout}
5
+ ${i.stderr}`;if(!/rejected|non-fast-forward|fetch first/i.test(o))throw dt(i)?yt("\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E44\u0E1B\u0E22\u0E31\u0E07\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13","pple deploy"):new s("\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",i.stderr.trim());if(t.out.say("\u0E21\u0E35\u0E04\u0E19\u0E2D\u0E37\u0E48\u0E19\u0E41\u0E01\u0E49\u0E44\u0E02\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49 \u2014 \u0E01\u0E33\u0E25\u0E31\u0E07\u0E19\u0E33\u0E07\u0E32\u0E19\u0E02\u0E2D\u0E07\u0E40\u0E02\u0E32\u0E40\u0E02\u0E49\u0E32\u0E21\u0E32\u0E01\u0E48\u0E2D\u0E19\u2026"),(await d(t,e,[...gt(r),"pull","--rebase","origin",R],r)).code!==0)throw await d(t,e,["rebase","--abort"]),new s("\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E02\u0E31\u0E14\u0E41\u0E22\u0E49\u0E07\u0E01\u0E31\u0E1A\u0E17\u0E35\u0E48\u0E04\u0E19\u0E2D\u0E37\u0E48\u0E19\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E44\u0E1B\u0E41\u0E25\u0E49\u0E27","\u0E43\u0E2B\u0E49 AI coding agent \u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E23\u0E27\u0E21\u0E2A\u0E2D\u0E07\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E40\u0E02\u0E49\u0E32\u0E14\u0E49\u0E27\u0E22\u0E01\u0E31\u0E19 \u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19 `pple deploy` \u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07");let a=await d(t,e,n,r);if(a.code!==0)throw new s("\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08",a.stderr.trim())}import K from"node:fs/promises";import A from"node:path";var H=".pple",Et="app.json";async function Dt(t,e){await K.mkdir(A.join(t,H),{recursive:!0}),await K.writeFile(A.join(t,H,Et),`${JSON.stringify(e,null,2)}
6
+ `)}async function y(t){let e=await V(t);if(e)return e;throw new s("\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E43\u0E0A\u0E48\u0E41\u0E2D\u0E1B PPLE","\u0E40\u0E02\u0E49\u0E32\u0E44\u0E1B\u0E43\u0E19\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B \u0E2B\u0E23\u0E37\u0E2D\u0E23\u0E31\u0E19 `pple init <app>` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E41\u0E2D\u0E1B\u0E43\u0E2B\u0E21\u0E48")}async function V(t){let e=A.resolve(t.cwd);for(;;){let r=A.join(e,H,Et),n=await K.readFile(r,"utf8").catch(()=>null);if(n!==null){let o=De(n);if(o)return{...o,dir:e};throw new s("\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E42\u0E22\u0E07\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49\u0E01\u0E31\u0E1A\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E40\u0E2A\u0E35\u0E22\u0E2B\u0E32\u0E22","\u0E23\u0E31\u0E19 `pple init <app>` \u0E43\u0E19\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E43\u0E2B\u0E21\u0E48\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07")}let i=A.dirname(e);if(i===e)break;e=i}return null}function De(t){try{let e=JSON.parse(t);return typeof e.slug!="string"||e.slug===""?null:{slug:e.slug,apiBase:typeof e.apiBase=="string"?e.apiBase:"",url:typeof e.url=="string"?e.url:""}}catch{return null}}import{createHash as be}from"node:crypto";import g from"node:fs/promises";import w from"node:path";import{realpath as ke}from"node:fs/promises";import J from"node:path";var Y="@pplethai/cli",m=`npm install -g ${Y}`;async function N(t){let e=await t.fetch(`${t.config.registryBase}/${Y}/latest`,{headers:{accept:"application/json"}}).catch(()=>null);if(!e?.ok)return null;let r=await e.json().catch(()=>null);return typeof r?.version=="string"&&r.version!==""?r.version:null}async function O(t){let e=await t.run("npm",["root","-g"],{cwd:t.cwd}).catch(()=>null);if(!e||e.code!==0)return!1;let r=e.stdout.trim();return r===""?!1:Ae(r,t.packageDir)}function j(t,e){return t.run("npm",["install","-g",`${Y}@${e}`],{cwd:t.cwd}).catch(r=>({code:1,stdout:"",stderr:r instanceof Error?r.message:String(r)}))}async function Ae(t,e){let[r,n]=await Promise.all([kt(t),kt(e)]),i=J.relative(r,n);return i!==""&&!i.startsWith("..")&&!J.isAbsolute(i)}async function kt(t){return ke(t).catch(()=>J.resolve(t))}function B(t,e){let r=At(t),n=At(e);if(!r)return!1;if(!n)return!0;for(let i=0;i<3;i+=1)if(r.parts[i]!==n.parts[i])return r.parts[i]>n.parts[i];return _e(r.prerelease,n.prerelease)>0}function At(t){let e=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?/.exec(t.trim());return e?{parts:[Number(e[1]),Number(e[2]),Number(e[3])],prerelease:e[4]?e[4].split("."):[]}:null}function _e(t,e){if(t.length===0&&e.length===0)return 0;if(t.length===0)return 1;if(e.length===0)return-1;for(let r=0;r<Math.max(t.length,e.length);r+=1){let n=t[r],i=e[r];if(n===void 0)return-1;if(i===void 0)return 1;let o=/^\d+$/.test(n)&&/^\d+$/.test(i);if(n!==i)return o?Number(n)>Number(i)?1:-1:n>i?1:-1}return 0}function _t(t){return`${t.stderr}
7
+ ${t.stdout}`.split(`
8
+ `).map(r=>r.replace(/^npm (ERR!|error|warn)\s*/i,"").trim()).filter(r=>r!=="").slice(0,3).join(`
9
+ `)||"\u0E2B\u0E22\u0E38\u0E14\u0E17\u0E33\u0E07\u0E32\u0E19\u0E42\u0E14\u0E22\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E23\u0E30\u0E1A\u0E38\u0E2A\u0E32\u0E40\u0E2B\u0E15\u0E38"}var xt=w.join(".claude","skills","pple-platform"),bt=`${xt.split(w.sep).join("/")}/`;async function U(t,e){let r=t.skillsDir;if(await g.readdir(r).catch(()=>null)===null)throw new s("\u0E44\u0E21\u0E48\u0E1E\u0E1A Skill \u0E02\u0E2D\u0E07 PPLE Platform \u0E43\u0E19\u0E01\u0E32\u0E23\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 CLI \u0E0A\u0E38\u0E14\u0E19\u0E35\u0E49",`\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 CLI \u0E43\u0E2B\u0E21\u0E48 (\`${m}\`) \u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07`);let i=w.join(e,xt),o=await Ct(i);await Ce(r,i),await xe(e);let u=await Ct(i);o!==u&&t.out.say(o===null?"\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 Skill \u0E02\u0E2D\u0E07\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E41\u0E25\u0E49\u0E27":"\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 Skill \u0E02\u0E2D\u0E07\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E41\u0E25\u0E49\u0E27")}async function Ce(t,e){await g.rm(e,{recursive:!0,force:!0}),await Tt(t,e)}async function Tt(t,e){await g.mkdir(e,{recursive:!0});for(let r of await g.readdir(t,{withFileTypes:!0})){if(r.name===".DS_Store")continue;let n=w.join(t,r.name),i=w.join(e,r.name);r.isDirectory()?await Tt(n,i):await g.copyFile(n,i)}}async function Ct(t){let e=await St(t).catch(()=>null);if(e===null)return null;let r=be("sha256");for(let n of e.sort())r.update(n),r.update("\0"),r.update(await g.readFile(w.join(t,n))),r.update("\0");return r.digest("hex")}async function St(t,e=""){let r=await g.readdir(t,{withFileTypes:!0}),n=[];for(let i of r){if(i.name===".DS_Store")continue;let o=e===""?i.name:`${e}/${i.name}`;i.isDirectory()?n.push(...await St(w.join(t,i.name),o)):n.push(o)}return n}async function xe(t){let e=w.join(t,".gitignore"),r=await g.readFile(e,"utf8").catch(()=>"");if(r.split(`
10
+ `).some(o=>o.trim()===bt))return;let i=r.endsWith(`
11
+ `)||r===""?r:`${r}
12
+ `;await g.writeFile(e,`${i}${bt}
13
+ `)}var Te=3e3,Se=3*6e4,Re=10*6e4,Ie=20;async function Rt(t,e){let r=await y(t);if(r.apiBase!==""&&r.apiBase!==t.config.apiBase)throw new s("\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49\u0E2D\u0E22\u0E39\u0E48\u0E1A\u0E19 PPLE Platform \u0E04\u0E19\u0E25\u0E30\u0E15\u0E31\u0E27\u0E01\u0E31\u0E1A\u0E17\u0E35\u0E48\u0E04\u0E38\u0E13\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E2D\u0E22\u0E39\u0E48",`\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49\u0E16\u0E39\u0E01\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E44\u0E27\u0E49\u0E01\u0E31\u0E1A ${r.apiBase}`);let n=await p(t),i=await n.app(r.slug);if(i.status==="retired")throw new s(`"${i.name}" \u0E16\u0E39\u0E01\u0E1B\u0E25\u0E14\u0E23\u0E30\u0E27\u0E32\u0E07\u0E41\u0E25\u0E49\u0E27`,"\u0E41\u0E2D\u0E1B\u0E17\u0E35\u0E48\u0E1B\u0E25\u0E14\u0E23\u0E30\u0E27\u0E32\u0E07\u0E41\u0E25\u0E49\u0E27\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49 \u0E2B\u0E32\u0E01\u0E15\u0E49\u0E2D\u0E07\u0E01\u0E32\u0E23\u0E2A\u0E32\u0E19\u0E07\u0E32\u0E19\u0E19\u0E35\u0E49\u0E15\u0E48\u0E2D \u0E43\u0E2B\u0E49\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E43\u0E2B\u0E21\u0E48\u0E43\u0E19\u0E04\u0E2D\u0E19\u0E42\u0E0B\u0E25");if(i.status!=="ready")throw new s(`"${i.name}" \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E23\u0E31\u0E1A\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07`,i.error?`\u0E01\u0E32\u0E23\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E1E\u0E1A\u0E1B\u0E31\u0E0D\u0E2B\u0E32: ${i.error}`:"\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai \u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E43\u0E19\u0E2D\u0E35\u0E01\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48");let o=await n.repoToken(r.slug);if(await U(t,r.dir),await I(t,r.dir))t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u2026"),await L(t,r.dir,e.message??`\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 ${i.name}`,o);else if(await Pt(t,r.dir,o)){t.out.say(`\u0E44\u0E21\u0E48\u0E21\u0E35\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E43\u0E2B\u0E21\u0E48 \u2014 ${i.name} \u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27\u0E17\u0E35\u0E48 ${i.url}`);return}t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u2026"),await $t(t,r.dir,o);let u=await vt(t,r.dir);t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E1A\u0E34\u0E25\u0E14\u0E4C\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u2026 (\u0E1B\u0E01\u0E15\u0E34\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E25\u0E32\u0E23\u0E32\u0E27\u0E2B\u0E19\u0E36\u0E48\u0E07\u0E19\u0E32\u0E17\u0E35)");let a=await Le(t,n,r.slug,u);Oe(t,i,a)}async function Le(t,e,r,n){let i=t.now(),o;for(;;){let a=(await e.deploys(r)).find(fe=>fe.commit===n);if(a&&(o=a,a.status!=="building"))return a;if(t.now()-i>=(o?Re:Se))throw new s(o?"\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E41\u0E25\u0E49\u0E27 \u0E41\u0E15\u0E48\u0E01\u0E32\u0E23\u0E1A\u0E34\u0E25\u0E14\u0E4C\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E25\u0E32\u0E19\u0E32\u0E19\u0E01\u0E27\u0E48\u0E32\u0E17\u0E35\u0E48\u0E04\u0E32\u0E14\u0E44\u0E27\u0E49":"\u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E41\u0E25\u0E49\u0E27 \u0E41\u0E15\u0E48\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E40\u0E23\u0E34\u0E48\u0E21\u0E1A\u0E34\u0E25\u0E14\u0E4C",`\u0E15\u0E34\u0E14\u0E15\u0E32\u0E21\u0E08\u0E19\u0E40\u0E2A\u0E23\u0E47\u0E08\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai/apps/${r}`);await t.sleep(Te)}}var Ne="superseded by a newer deploy";function Oe(t,e,r){if(r.status==="failed"){if(r.error===Ne)throw new s("\u0E21\u0E35\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E21\u0E32\u0E41\u0E17\u0E19\u0E17\u0E35\u0E48\u0E04\u0E23\u0E31\u0E49\u0E07\u0E17\u0E35\u0E48\u0E04\u0E38\u0E13\u0E01\u0E33\u0E25\u0E31\u0E07\u0E23\u0E2D\u0E2D\u0E22\u0E39\u0E48",`\u0E15\u0E34\u0E14\u0E15\u0E32\u0E21\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E19\u0E31\u0E49\u0E19\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai/apps/${e.slug}`);let i=r.log?je(r.log,Ie):r.error;throw i&&(t.out.say(),t.out.say(i),t.out.say()),new s(`\u0E1A\u0E34\u0E25\u0E14\u0E4C ${e.name} \u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08 \u0E2A\u0E34\u0E48\u0E07\u0E17\u0E35\u0E48\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E2D\u0E22\u0E39\u0E48\u0E08\u0E36\u0E07\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07`,i?"\u0E2A\u0E48\u0E07\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E14\u0E49\u0E32\u0E19\u0E1A\u0E19\u0E43\u0E2B\u0E49 AI coding agent \u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13 \u2014 \u0E43\u0E19\u0E19\u0E31\u0E49\u0E19\u0E1A\u0E2D\u0E01\u0E27\u0E48\u0E32\u0E15\u0E49\u0E2D\u0E07\u0E41\u0E01\u0E49\u0E2D\u0E30\u0E44\u0E23":`\u0E14\u0E39\u0E23\u0E32\u0E22\u0E25\u0E30\u0E40\u0E2D\u0E35\u0E22\u0E14\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 https://console.ppleth.ai/apps/${e.slug}`)}let n=r.migrations.applied??[];if(n.length>0&&t.out.say(`\u0E43\u0E0A\u0E49 migration ${n.length} \u0E23\u0E32\u0E22\u0E01\u0E32\u0E23\u0E01\u0E31\u0E1A\u0E10\u0E32\u0E19\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E41\u0E25\u0E49\u0E27`),r.status==="unverified"){t.out.say(`\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 ${e.name} \u0E41\u0E25\u0E49\u0E27 \u0E41\u0E15\u0E48\u0E41\u0E2D\u0E1B\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E15\u0E2D\u0E1A\u0E2A\u0E19\u0E2D\u0E07`),t.out.say(`\u0E23\u0E2D\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48 \u0E41\u0E25\u0E49\u0E27\u0E40\u0E1B\u0E34\u0E14 ${e.url}`);return}t.out.say(`${e.name} \u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E44\u0E14\u0E49\u0E41\u0E25\u0E49\u0E27\u0E17\u0E35\u0E48 ${e.url}`)}function je(t,e){return t.split(`
14
+ `).slice(-e).join(`
15
+ `).trim()}import Be from"node:fs/promises";import Ue from"node:path";async function It(t){let e=await y(t),n=await(await p(t)).env(e.slug);if(n.length===0){t.out.say("\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E43\u0E14 \u0E46"),t.out.say("\u0E15\u0E31\u0E27\u0E41\u0E1B\u0E23\u0E17\u0E35\u0E48\u0E04\u0E38\u0E13\u0E15\u0E31\u0E49\u0E07\u0E08\u0E30\u0E21\u0E35\u0E1C\u0E25\u0E43\u0E19\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E16\u0E31\u0E14\u0E44\u0E1B");return}for(let i of n)i.secret?t.out.say(`${i.key}=(secret)`):t.out.say(`${i.key}=${i.value??""}`);t.out.say(""),t.out.say("\u0E08\u0E30\u0E21\u0E35\u0E1C\u0E25\u0E43\u0E19\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E16\u0E31\u0E14\u0E44\u0E1B")}async function Lt(t,e){let r=await y(t),n=await Me(t,e),o=await(await p(t)).setEnv(r.slug,e.key,n,e.secret);t.out.say(`\u0E1A\u0E31\u0E19\u0E17\u0E36\u0E01 ${o.key}${o.secret?" (secret)":""} \u0E41\u0E25\u0E49\u0E27`),t.out.say("\u0E08\u0E30\u0E21\u0E35\u0E1C\u0E25\u0E43\u0E19\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E16\u0E31\u0E14\u0E44\u0E1B")}async function Nt(t,e){let r=await y(t);await(await p(t)).deleteEnv(r.slug,e),t.out.say(`\u0E25\u0E1A ${e} \u0E41\u0E25\u0E49\u0E27`),t.out.say("\u0E08\u0E30\u0E21\u0E35\u0E1C\u0E25\u0E43\u0E19\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E04\u0E23\u0E31\u0E49\u0E07\u0E16\u0E31\u0E14\u0E44\u0E1B")}async function Me(t,e){if(e.file!==void 0&&e.value!==void 0)throw new s("\u0E2A\u0E48\u0E07\u0E04\u0E48\u0E32\u0E21\u0E32\u0E40\u0E1B\u0E47\u0E19 argument \u0E2B\u0E23\u0E37\u0E2D\u0E1C\u0E48\u0E32\u0E19 `--file` \u0E2D\u0E22\u0E48\u0E32\u0E07\u0E43\u0E14\u0E2D\u0E22\u0E48\u0E32\u0E07\u0E2B\u0E19\u0E36\u0E48\u0E07 \u0E44\u0E21\u0E48\u0E43\u0E0A\u0E48\u0E17\u0E31\u0E49\u0E07\u0E2A\u0E2D\u0E07\u0E2D\u0E22\u0E48\u0E32\u0E07");if(e.file!==void 0){let r=Ue.resolve(t.cwd,e.file),n=await Be.readFile(r,"utf8").catch(()=>null);if(n===null)throw new s(`\u0E2D\u0E48\u0E32\u0E19\u0E44\u0E1F\u0E25\u0E4C ${e.file} \u0E44\u0E21\u0E48\u0E44\u0E14\u0E49`,"\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E1E\u0E32\u0E18\u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07");return n}if(e.value!==void 0)return e.value;if(t.interactive)throw new s("`pple env set` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38\u0E04\u0E48\u0E32","\u0E2A\u0E48\u0E07\u0E04\u0E48\u0E32\u0E21\u0E32\u0E40\u0E1B\u0E47\u0E19 argument \u0E1C\u0E48\u0E32\u0E19 `--file` \u0E2B\u0E23\u0E37\u0E2D pipe \u0E17\u0E32\u0E07 stdin");return t.readStdin()}var Fe=20,Ge=/[\u0E31\u0E34-\u0E3A\u0E47-\u0E4E]/g;function l(t,e){let r=t.replace(Ge,"").length;return t+" ".repeat(Math.max(0,e-r))}var Ke={ready:"\u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19",provisioning:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E08\u0E31\u0E14\u0E40\u0E15\u0E23\u0E35\u0E22\u0E21",failed:"\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27",retired:"\u0E1B\u0E25\u0E14\u0E23\u0E30\u0E27\u0E32\u0E07\u0E41\u0E25\u0E49\u0E27"},Ot={draft:"\u0E09\u0E1A\u0E31\u0E1A\u0E23\u0E48\u0E32\u0E07",beta:"\u0E17\u0E14\u0E25\u0E2D\u0E07\u0E43\u0E0A\u0E49",live:"\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48\u0E08\u0E23\u0E34\u0E07"},He={owner:"\u0E40\u0E08\u0E49\u0E32\u0E02\u0E2D\u0E07",collaborator:"\u0E1C\u0E39\u0E49\u0E23\u0E48\u0E27\u0E21\u0E1E\u0E31\u0E12\u0E19\u0E32"},jt={live:"\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E2D\u0E22\u0E39\u0E48",building:"\u0E01\u0E33\u0E25\u0E31\u0E07\u0E1A\u0E34\u0E25\u0E14\u0E4C",unverified:"\u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E22\u0E37\u0E19\u0E22\u0E31\u0E19",failed:"\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27"},Ve={pending:"\u0E23\u0E2D\u0E14\u0E33\u0E40\u0E19\u0E34\u0E19\u0E01\u0E32\u0E23",approved:"\u0E2D\u0E19\u0E38\u0E21\u0E31\u0E15\u0E34\u0E41\u0E25\u0E49\u0E27",denied:"\u0E1B\u0E0F\u0E34\u0E40\u0E2A\u0E18\u0E41\u0E25\u0E49\u0E27"};function v(t,e){return t[e]??e}async function Bt(t,e){let r=await Je(t,e),n=await p(t),i=await n.app(r),o=i.role!=="collaborator",[u,a,c,P]=await Promise.all([n.metrics(r),n.deploys(r),n.env(r),o?Ye(n,r):Promise.resolve(null)]);We(t,i),Xe(t,u),ze(t,a),Ze(t,c),P&&(Qe(t,i,P.requests,P.invites),tr(t,P.collaborators),er(t,P.requests)),t.out.say(""),t.out.say("\u0E2B\u0E32\u0E01\u0E15\u0E49\u0E2D\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E42\u0E04\u0E27\u0E15\u0E32 \u0E04\u0E48\u0E32 env \u0E1C\u0E39\u0E49\u0E23\u0E48\u0E27\u0E21\u0E1E\u0E31\u0E12\u0E19\u0E32 \u0E2B\u0E23\u0E37\u0E2D\u0E01\u0E32\u0E23\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48 \u0E43\u0E0A\u0E49 https://console.ppleth.ai")}async function Je(t,e){if(e)return e;try{return(await y(t)).slug}catch(r){throw r instanceof s&&r.message==="\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E43\u0E0A\u0E48\u0E41\u0E2D\u0E1B PPLE"?new s("\u0E41\u0E2D\u0E1B\u0E44\u0E2B\u0E19? `pple info` \u0E15\u0E49\u0E2D\u0E07\u0E21\u0E35 App Link \u0E2B\u0E23\u0E37\u0E2D slug","\u0E40\u0E02\u0E49\u0E32\u0E44\u0E1B\u0E43\u0E19\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B \u0E43\u0E2A\u0E48 slug (`pple info <slug>`) \u0E2B\u0E23\u0E37\u0E2D\u0E40\u0E1B\u0E34\u0E14 https://console.ppleth.ai"):r}}async function Ye(t,e){let[r,n,i]=await Promise.all([t.collaborators(e),t.requests(e),t.invites(e)]);return{collaborators:r,requests:n,invites:i}}function We(t,e){t.out.say(e.name),t.out.say(` ${l("slug",18)}${e.slug}`),t.out.say(` ${l("URL",18)}${e.url}`),e.customAddress&&t.out.say(` ${l("\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48\u0E17\u0E35\u0E48\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E40\u0E2D\u0E07",18)}${e.customAddress}`),t.out.say(` ${l("\u0E2A\u0E16\u0E32\u0E19\u0E30",18)}${v(Ke,e.status)}`),t.out.say(` ${l("\u0E01\u0E32\u0E23\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48",18)}${v(Ot,e.tier??"draft")}`),e.role&&t.out.say(` ${l("\u0E1A\u0E17\u0E1A\u0E32\u0E17\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13",18)}${v(He,e.role)}`),e.deploy&&t.out.say(` ${l("\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E1B\u0E31\u0E08\u0E08\u0E38\u0E1A\u0E31\u0E19",18)}${v(jt,e.deploy.status)}`+(e.deploy.message?` \u2014 ${e.deploy.message}`:"")),e.error&&t.out.say(` ${l("\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14",18)}${e.error}`)}function Xe(t,e){t.out.say(""),t.out.say("\u0E01\u0E32\u0E23\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E41\u0E25\u0E30\u0E42\u0E04\u0E27\u0E15\u0E32\u0E17\u0E23\u0E31\u0E1E\u0E22\u0E32\u0E01\u0E23"),t.out.say(` ${l("CPU \u0E15\u0E48\u0E2D request",20)}${e.limits.cpuMs} ms`),t.out.say(` ${l("\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19",20)}${_(e.usage.notificationsSent)}`+(e.usage.notificationsSent===null?" (\u0E14\u0E39\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E43\u0E19\u0E02\u0E13\u0E30\u0E19\u0E35\u0E49)":` \u0E08\u0E32\u0E01\u0E42\u0E04\u0E27\u0E15\u0E32 ${_(e.limits.notificationsPerDay)} \u0E04\u0E23\u0E31\u0E49\u0E07\u0E27\u0E31\u0E19\u0E19\u0E35\u0E49`)),t.out.say(` ${l("\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14 (24 \u0E0A\u0E21.)",20)}${_(e.usage.errors)}`+(e.usage.errors===null?" (\u0E14\u0E39\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E43\u0E19\u0E02\u0E13\u0E30\u0E19\u0E35\u0E49)":e.usage.errors===0?" (\u0E44\u0E21\u0E48\u0E21\u0E35\u0E43\u0E19 24 \u0E0A\u0E31\u0E48\u0E27\u0E42\u0E21\u0E07\u0E17\u0E35\u0E48\u0E1C\u0E48\u0E32\u0E19\u0E21\u0E32)":e.usage.requests===null?" (\u0E04\u0E33\u0E02\u0E2D\u0E17\u0E35\u0E48\u0E25\u0E49\u0E21\u0E40\u0E2B\u0E25\u0E27\u0E43\u0E19 24 \u0E0A\u0E31\u0E48\u0E27\u0E42\u0E21\u0E07\u0E17\u0E35\u0E48\u0E1C\u0E48\u0E32\u0E19\u0E21\u0E32)":` \u0E08\u0E32\u0E01\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14 ${_(e.usage.requests)} \u0E04\u0E33\u0E02\u0E2D`)),t.out.say(` ${l("\u0E1C\u0E39\u0E49\u0E43\u0E0A\u0E49\u0E41\u0E2D\u0E1B",20)}${_(e.usage.appUsers)}`+(e.usage.appUsers===null?" (\u0E14\u0E39\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E43\u0E19\u0E02\u0E13\u0E30\u0E19\u0E35\u0E49)":""))}function _(t){return t===null?"\u2014":String(t)}function ze(t,e){if(t.out.say(""),t.out.say("\u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22\u0E25\u0E48\u0E32\u0E2A\u0E38\u0E14"),e.length===0){t.out.say(" \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35");return}for(let r of e.slice(0,10)){let n=r.commit.slice(0,7),i=r.message?` \u2014 ${r.message}`:"",o=v(jt,r.status);t.out.say(` ${l(o,13)} ${n}${i}`)}}function Ze(t,e){if(t.out.say(""),t.out.say("\u0E04\u0E48\u0E32 env"),e.length===0){t.out.say(" \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E43\u0E14 \u0E46");return}for(let r of e)r.secret?t.out.say(` ${r.key}=(secret)`):t.out.say(` ${r.key}=${r.value??""}`)}function Qe(t,e,r,n){t.out.say(""),t.out.say("\u0E01\u0E32\u0E23\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48"),t.out.say(` ${l("\u0E23\u0E30\u0E14\u0E31\u0E1A",18)}${v(Ot,e.tier??"draft")}`),e.customAddress&&t.out.say(` ${l("\u0E17\u0E35\u0E48\u0E2D\u0E22\u0E39\u0E48\u0E17\u0E35\u0E48\u0E01\u0E33\u0E2B\u0E19\u0E14\u0E40\u0E2D\u0E07",18)}${e.customAddress}`);let i=r.find(o=>o.type==="publish"&&o.status==="pending");if(i&&t.out.say(` ${l("\u0E04\u0E33\u0E02\u0E2D\u0E17\u0E35\u0E48\u0E23\u0E2D\u0E2D\u0E22\u0E39\u0E48",18)}${Ut(i)}`),e.tier==="beta"){let o=n.filter(u=>u.status!=="DECLINED").length;t.out.say(` ${l("\u0E04\u0E33\u0E40\u0E0A\u0E34\u0E0D\u0E17\u0E14\u0E25\u0E2D\u0E07\u0E43\u0E0A\u0E49",18)}\u0E43\u0E0A\u0E49\u0E44\u0E1B ${o} \u0E08\u0E32\u0E01 ${Fe} \u0E17\u0E35\u0E48\u0E19\u0E31\u0E48\u0E07`)}}function tr(t,e){if(t.out.say(""),t.out.say("\u0E1C\u0E39\u0E49\u0E23\u0E48\u0E27\u0E21\u0E1E\u0E31\u0E12\u0E19\u0E32"),e.length===0){t.out.say(" \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35");return}for(let r of e){let n=r.maskedName??"\u0E1C\u0E39\u0E49\u0E23\u0E48\u0E27\u0E21\u0E1E\u0E31\u0E12\u0E19\u0E32",i=r.phoneNumber?` (${r.phoneNumber})`:"";t.out.say(` ${n}${i}`)}}function er(t,e){if(t.out.say(""),t.out.say("\u0E1B\u0E23\u0E30\u0E27\u0E31\u0E15\u0E34\u0E04\u0E33\u0E02\u0E2D"),e.length===0){t.out.say(" \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35");return}for(let r of e.slice(0,10)){let n=r.reason?` \u2014 ${r.reason}`:"",i=v(Ve,r.status);t.out.say(` ${l(i,13)} ${Ut(r)}${n}`)}}function Ut(t){if(t.type==="publish"){let r=Array.isArray(t.payload.roles)?t.payload.roles:[],n=typeof t.payload.customAddress=="string"?` \xB7 \u0E17\u0E35\u0E48 ${t.payload.customAddress}`:"";return`\u0E04\u0E33\u0E02\u0E2D\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48 \xB7 \u0E02\u0E36\u0E49\u0E19\u0E40\u0E1C\u0E22\u0E41\u0E1E\u0E23\u0E48\u0E08\u0E23\u0E34\u0E07 \xB7 ${r.length===0?"\u0E17\u0E38\u0E01\u0E04\u0E19":r.join(", ")}${n}`}if(t.type==="retire")return"\u0E04\u0E33\u0E02\u0E2D\u0E1B\u0E25\u0E14\u0E23\u0E30\u0E27\u0E32\u0E07 \xB7 \u0E1B\u0E25\u0E14\u0E23\u0E30\u0E27\u0E32\u0E07\u0E41\u0E2D\u0E1B";let e=[];return typeof t.payload.cpuMs=="number"&&e.push(`CPU ${t.payload.cpuMs} ms/request`),typeof t.payload.notificationsPerDay=="number"&&e.push(`\u0E01\u0E32\u0E23\u0E41\u0E08\u0E49\u0E07\u0E40\u0E15\u0E37\u0E2D\u0E19 ${t.payload.notificationsPerDay} \u0E04\u0E23\u0E31\u0E49\u0E07/\u0E27\u0E31\u0E19`),`\u0E04\u0E33\u0E02\u0E2D\u0E40\u0E1E\u0E34\u0E48\u0E21\u0E42\u0E04\u0E27\u0E15\u0E32 \xB7 \u0E02\u0E2D\u0E40\u0E1E\u0E34\u0E48\u0E21 ${e.length>0?e.join(" \u0E41\u0E25\u0E30 "):"\u0E42\u0E04\u0E27\u0E15\u0E32"}`}import Kt from"node:fs/promises";import b from"node:path";import E from"node:fs/promises";import Mt from"node:path";var rr=new Set([".git","node_modules","dist",".wrangler",".dev.vars",".env"]),nr=new Map([["gitignore",".gitignore"]]),ir="pple-app",or=new Set(["package.json","package-lock.json","wrangler.jsonc"]);async function qt(t,e,r){if(await E.readdir(t).catch(()=>null)===null)throw new s("\u0E44\u0E21\u0E48\u0E1E\u0E1A\u0E40\u0E17\u0E21\u0E40\u0E1E\u0E25\u0E15\u0E41\u0E2D\u0E1B PPLE \u0E43\u0E19\u0E01\u0E32\u0E23\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 CLI \u0E0A\u0E38\u0E14\u0E19\u0E35\u0E49",`\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07 CLI \u0E43\u0E2B\u0E21\u0E48 (\`${m}\`) \u0E41\u0E25\u0E49\u0E27\u0E25\u0E2D\u0E07\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07`);let i=[];return await Ft({from:t,to:e,prefix:"",slug:r,written:i}),i.sort()}async function Ft(t){for(let e of await E.readdir(t.from,{withFileTypes:!0})){if(rr.has(e.name))continue;let r=nr.get(e.name)??e.name,n=Mt.join(t.from,e.name),i=Mt.join(t.to,r),o=t.prefix===""?r:`${t.prefix}/${r}`;if(e.isDirectory()){await E.mkdir(i,{recursive:!0}),await Ft({...t,from:n,to:i,prefix:o});continue}if(or.has(r)){let u=await E.readFile(n,"utf8");await E.writeFile(i,sr(u,ir,t.slug))}else await E.copyFile(n,i);t.written.push(o)}}function sr(t,e,r){return t.split(e).join(r)}var ar=3e3,ur=5*6e4;async function Ht(t,e){let r=await p(t),n=e.slug?await r.app(e.slug):await pr(t,r,await cr(t,e.name));if(!n.repo)throw new s(`"${n.name}" \u0E22\u0E31\u0E07\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E44\u0E21\u0E48\u0E40\u0E2A\u0E23\u0E47\u0E08`,`\u0E23\u0E2D\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19 \`pple init ${n.slug}\` \u0E2B\u0E32\u0E01\u0E22\u0E31\u0E07\u0E40\u0E1B\u0E47\u0E19\u0E41\u0E1A\u0E1A\u0E19\u0E35\u0E49 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21`);n.status==="provisioning"&&t.out.say("\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E22\u0E31\u0E07\u0E2D\u0E22\u0E39\u0E48\u0E23\u0E30\u0E2B\u0E27\u0E48\u0E32\u0E07\u0E01\u0E32\u0E23\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u2026");let i=b.resolve(t.cwd,e.dir??n.slug);await mr(i);let o=await r.repoToken(n.slug);if(t.out.say(`\u0E01\u0E33\u0E25\u0E31\u0E07\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32 "${n.name}" \u0E43\u0E19 ${b.basename(i)}/\u2026`),await ht(t,fr(t,n.repo),i,o),await gr(i))throw new s(`"${n.name}" \u0E21\u0E35\u0E42\u0E04\u0E49\u0E14\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27 \u0E08\u0E36\u0E07\u0E44\u0E21\u0E48\u0E21\u0E35\u0E2D\u0E30\u0E44\u0E23\u0E15\u0E49\u0E2D\u0E07\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32`,"\u0E17\u0E33\u0E07\u0E32\u0E19\u0E43\u0E19\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E19\u0E31\u0E49\u0E19\u0E41\u0E25\u0E49\u0E27\u0E23\u0E31\u0E19 `pple deploy` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E19\u0E33\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E36\u0E49\u0E19\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E08\u0E23\u0E34\u0E07");await qt(t.templateDir,i,n.slug),await Dt(i,{slug:n.slug,apiBase:t.config.apiBase,url:n.url}),await U(t,i),await I(t,i)&&await L(t,i,"\u0E40\u0E23\u0E34\u0E48\u0E21\u0E08\u0E32\u0E01\u0E40\u0E17\u0E21\u0E40\u0E1E\u0E25\u0E15\u0E21\u0E32\u0E15\u0E23\u0E10\u0E32\u0E19\u0E02\u0E2D\u0E07 PPLE",o);let u=await lr(t,i);dr(t,n,i,u)}async function lr(t,e){t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07\u0E41\u0E1E\u0E47\u0E01\u0E40\u0E01\u0E08\u0E41\u0E25\u0E30\u0E40\u0E15\u0E23\u0E35\u0E22\u0E21\u0E10\u0E32\u0E19\u0E02\u0E49\u0E2D\u0E21\u0E39\u0E25\u0E1A\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u2026");let r=[["npm",["install"]],["npm",["run","db:migrate:local"]]];for(let[n,i]of r){let o=await t.run(n,i,{cwd:e}).catch(()=>null);if(!o||o.code!==0)return!1}return!0}async function cr(t,e){if(await V(t))throw new s("\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E19\u0E35\u0E49\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E01\u0E31\u0E1A\u0E41\u0E2D\u0E1B PPLE \u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27","\u0E23\u0E31\u0E19 `pple info` \u0E2B\u0E23\u0E37\u0E2D `pple deploy` \u0E17\u0E35\u0E48\u0E19\u0E35\u0E48 \u0E2B\u0E23\u0E37\u0E2D\u0E22\u0E49\u0E32\u0E22\u0E44\u0E1B\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E2D\u0E37\u0E48\u0E19\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E43\u0E2B\u0E21\u0E48");if(e!==void 0){let n=e.trim();if(!n)throw new s("`--name` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B",'\u0E15\u0E31\u0E27\u0E2D\u0E22\u0E48\u0E32\u0E07: `pple init --name "\u0E25\u0E07\u0E17\u0E30\u0E40\u0E1A\u0E35\u0E22\u0E19\u0E2D\u0E32\u0E2A\u0E32\u0E2A\u0E21\u0E31\u0E04\u0E23"`');return n}if(!t.interactive)throw new s("`pple init` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B",'\u0E43\u0E2A\u0E48 `--name "\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"` \u0E2B\u0E23\u0E37\u0E2D\u0E23\u0E31\u0E19\u0E43\u0E19\u0E40\u0E17\u0E2D\u0E23\u0E4C\u0E21\u0E34\u0E19\u0E31\u0E25\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E43\u0E2B\u0E49\u0E23\u0E30\u0E1A\u0E1A\u0E16\u0E32\u0E21');let r=(await t.ask("\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B:")).trim();if(!r)throw new s("\u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B\u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B",'\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E2D\u0E35\u0E01\u0E04\u0E23\u0E31\u0E49\u0E07 \u0E2B\u0E23\u0E37\u0E2D\u0E43\u0E2A\u0E48 `--name "\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"`');return r}async function pr(t,e,r){t.out.say(`\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2A\u0E23\u0E49\u0E32\u0E07 "${r}" \u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u2026`);let n=await e.createApp(r);if(Gt(n))return n;t.out.say("\u0E01\u0E33\u0E25\u0E31\u0E07\u0E23\u0E2D\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E43\u0E2B\u0E49\u0E40\u0E2A\u0E23\u0E47\u0E08\u2026");let i=t.now();for(;;){if(n.status==="failed")throw new s(`\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32 "${n.name}" \u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21\u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08`,n.error?`${n.error} slug \u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E04\u0E37\u0E2D ${n.slug} \u2014 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21 \u0E2B\u0E23\u0E37\u0E2D\u0E25\u0E2D\u0E07 \`pple init ${n.slug}\` \u0E20\u0E32\u0E22\u0E2B\u0E25\u0E31\u0E07`:`slug \u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E04\u0E37\u0E2D ${n.slug} \u2014 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E15\u0E34\u0E14\u0E15\u0E48\u0E2D\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21 \u0E2B\u0E23\u0E37\u0E2D\u0E25\u0E2D\u0E07 \`pple init ${n.slug}\` \u0E20\u0E32\u0E22\u0E2B\u0E25\u0E31\u0E07`);if(t.now()-i>=ur)throw new s(`"${n.name}" \u0E22\u0E31\u0E07\u0E2D\u0E22\u0E39\u0E48\u0E23\u0E30\u0E2B\u0E27\u0E48\u0E32\u0E07\u0E01\u0E32\u0E23\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21`,`\u0E25\u0E2D\u0E07\u0E43\u0E2B\u0E21\u0E48\u0E14\u0E49\u0E27\u0E22 \`pple init ${n.slug}\` \u0E43\u0E19\u0E2D\u0E35\u0E01\u0E2A\u0E31\u0E01\u0E04\u0E23\u0E39\u0E48`);if(await t.sleep(ar),n=await e.app(n.slug),Gt(n))return n}}function Gt(t){return t.status==="ready"&&t.repo!==null}function fr(t,e){return`${t.config.repoBase}/${e}.git`}async function mr(t){let e=await Kt.readdir(t).catch(()=>null);if(e!==null&&e.length>0)throw new s(`\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C ${b.basename(t)}/ \u0E21\u0E35\u0E44\u0E1F\u0E25\u0E4C\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27`,"\u0E23\u0E31\u0E19 `pple init` \u0E17\u0E35\u0E48\u0E2D\u0E37\u0E48\u0E19 \u0E2B\u0E23\u0E37\u0E2D\u0E43\u0E2A\u0E48 `--dir <folder>` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E40\u0E25\u0E37\u0E2D\u0E01\u0E42\u0E1F\u0E25\u0E40\u0E14\u0E2D\u0E23\u0E4C\u0E2D\u0E37\u0E48\u0E19")}async function gr(t){return Kt.access(b.join(t,"package.json")).then(()=>!0).catch(()=>!1)}function dr(t,e,r,n){let i=b.basename(r);t.out.say(),t.out.say(`"${e.name}" \u0E1E\u0E23\u0E49\u0E2D\u0E21\u0E43\u0E2B\u0E49\u0E17\u0E33\u0E07\u0E32\u0E19\u0E41\u0E25\u0E49\u0E27\u0E43\u0E19 ${i}/`),t.out.say(`\u0E41\u0E2D\u0E1B\u0E08\u0E30\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E44\u0E14\u0E49\u0E17\u0E35\u0E48 ${e.url}`),t.out.say(),t.out.say("\u0E02\u0E31\u0E49\u0E19\u0E15\u0E48\u0E2D\u0E44\u0E1B:"),t.out.say(` cd ${i}`),n||(t.out.say(" npm install"),t.out.say(" npm run db:migrate:local")),t.out.say(" npm run dev # \u0E14\u0E39\u0E1C\u0E25\u0E1A\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E19\u0E35\u0E49"),t.out.say(" pple deploy # \u0E19\u0E33\u0E02\u0E36\u0E49\u0E19\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E08\u0E23\u0E34\u0E07")}import W from"node:fs/promises";import X from"node:path";var yr=1440*60*1e3,Vt="update-check.json",wr="config.json",hr=new Set(["upgrade","help","--help","-h"]);function Jt(t){return t.length>0&&!hr.has(t[0])}function z(t,e){t.out.say(`\u0E21\u0E35 pple \u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E43\u0E2B\u0E21\u0E48 (${e}) \u0E04\u0E38\u0E13\u0E43\u0E0A\u0E49\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19 ${t.version}`)}function Z(t){t.out.say("pple \u0E0A\u0E38\u0E14\u0E19\u0E35\u0E49\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07\u0E1C\u0E48\u0E32\u0E19 npm \u0E01\u0E32\u0E23\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15\u0E17\u0E35\u0E48\u0E19\u0E35\u0E48\u0E2D\u0E32\u0E08\u0E17\u0E33\u0E43\u0E2B\u0E49\u0E04\u0E38\u0E13"),t.out.say("\u0E21\u0E35 pple \u0E2A\u0E2D\u0E07\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19 \u0E01\u0E23\u0E38\u0E13\u0E32\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15\u0E14\u0E49\u0E27\u0E22\u0E27\u0E34\u0E18\u0E35\u0E40\u0E14\u0E34\u0E21\u0E17\u0E35\u0E48\u0E04\u0E38\u0E13\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07\u0E44\u0E27\u0E49"),t.out.say(`\u0E2B\u0E23\u0E37\u0E2D\u0E15\u0E34\u0E14\u0E15\u0E31\u0E49\u0E07\u0E14\u0E49\u0E27\u0E22 npm:
16
+
17
+ ${m}`)}function Q(t){return`${_t(t)}
18
+
19
+ \u0E25\u0E2D\u0E07\u0E23\u0E31\u0E19\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07\u0E19\u0E35\u0E49\u0E14\u0E49\u0E27\u0E22\u0E15\u0E31\u0E27\u0E40\u0E2D\u0E07:
20
+
21
+ ${m}`}async function Yt(t,e){if(!await Pr(t))return null;await $r(t);let r=await N(t);if(r===null||!B(r,t.version))return null;if(z(t,r),!await O(t))return Z(t),t.out.say(),null;if(!t.interactive)return t.out.say("\u0E23\u0E31\u0E19 `pple upgrade` \u0E40\u0E21\u0E37\u0E48\u0E2D\u0E04\u0E38\u0E13\u0E1E\u0E23\u0E49\u0E2D\u0E21"),t.out.say(),null;if(!await t.confirm("\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 pple \u0E15\u0E2D\u0E19\u0E19\u0E35\u0E49\u0E40\u0E25\u0E22\u0E44\u0E2B\u0E21?"))return t.out.say(),null;let n=await j(t,r);return n.code!==0?await vr(t,r,n):(t.out.say(`pple \u0E40\u0E1B\u0E47\u0E19\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19 ${r} \u0E41\u0E25\u0E49\u0E27 \u0E01\u0E33\u0E25\u0E31\u0E07\u0E17\u0E33\u0E07\u0E32\u0E19\u0E15\u0E48\u0E2D\u0E08\u0E32\u0E01\u0E17\u0E35\u0E48\u0E04\u0E49\u0E32\u0E07\u0E44\u0E27\u0E49\u2026`),t.out.say(),t.reexec(e))}async function vr(t,e,r){return t.out.say(`\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 pple \u0E40\u0E1B\u0E47\u0E19 ${e} \u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08`),t.out.say(Q(r)),t.out.say(),await t.confirm(`\u0E43\u0E0A\u0E49 pple ${t.version} \u0E17\u0E33\u0E07\u0E32\u0E19\u0E15\u0E48\u0E2D\u0E44\u0E1B\u0E01\u0E48\u0E2D\u0E19\u0E44\u0E2B\u0E21?`)?(t.out.say(),null):(t.out.say("\u0E2B\u0E22\u0E38\u0E14\u0E41\u0E25\u0E49\u0E27 \u0E44\u0E21\u0E48\u0E21\u0E35\u0E2D\u0E30\u0E44\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07"),1)}async function Pr(t){if(!t.updateChecks||!await Er(t))return!1;let e=await Wt(X.join(t.configDir,Vt));return typeof e?.lastCheckedAt!="number"?!0:t.now()-e.lastCheckedAt>=yr}async function $r(t){let e={lastCheckedAt:t.now()};await W.mkdir(t.configDir,{recursive:!0}).then(()=>W.writeFile(X.join(t.configDir,Vt),`${JSON.stringify(e,null,2)}
22
+ `)).catch(()=>{})}async function Er(t){return(await Wt(X.join(t.configDir,wr)))?.updateCheck!==!1}async function Wt(t){let e=await W.readFile(t,"utf8").catch(()=>null);if(e===null)return null;try{return JSON.parse(e)}catch{return null}}async function Xt(t){let e=await N(t);if(e===null)throw new s("\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D npm \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E15\u0E23\u0E27\u0E08\u0E2B\u0E32\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E43\u0E2B\u0E21\u0E48\u0E02\u0E2D\u0E07 pple \u0E44\u0E21\u0E48\u0E44\u0E14\u0E49",`\u0E15\u0E23\u0E27\u0E08\u0E2A\u0E2D\u0E1A\u0E01\u0E32\u0E23\u0E40\u0E0A\u0E37\u0E48\u0E2D\u0E21\u0E15\u0E48\u0E2D\u0E2D\u0E34\u0E19\u0E40\u0E17\u0E2D\u0E23\u0E4C\u0E40\u0E19\u0E47\u0E15 \u0E2B\u0E23\u0E37\u0E2D\u0E2D\u0E31\u0E1B\u0E40\u0E01\u0E23\u0E14\u0E42\u0E14\u0E22\u0E15\u0E23\u0E07:
23
+
24
+ ${m}`);if(!B(e,t.version)){t.out.say(`\u0E04\u0E38\u0E13\u0E43\u0E0A\u0E49 pple \u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E25\u0E48\u0E32\u0E2A\u0E38\u0E14\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27 (${t.version})`);return}if(!await O(t)){z(t,e),t.out.say(),Z(t);return}t.out.say(`\u0E01\u0E33\u0E25\u0E31\u0E07\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 pple ${t.version} \u2192 ${e}\u2026`);let r=await j(t,e);if(r.code!==0)throw new s(`\u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 pple \u0E40\u0E1B\u0E47\u0E19 ${e} \u0E44\u0E21\u0E48\u0E2A\u0E33\u0E40\u0E23\u0E47\u0E08`,Q(r));t.out.say(`pple \u0E40\u0E1B\u0E47\u0E19\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19 ${e} \u0E41\u0E25\u0E49\u0E27`)}var zt=`pple \u2014 \u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E25\u0E30\u0E2A\u0E48\u0E07\u0E41\u0E2D\u0E1B\u0E02\u0E36\u0E49\u0E19 PPLE Platform
25
+
26
+ pple auth login \u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E14\u0E49\u0E27\u0E22 PPLE ID \u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13
27
+ pple auth logout \u0E25\u0E1A\u0E01\u0E32\u0E23\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E2D\u0E2D\u0E01\u0E08\u0E32\u0E01\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E19\u0E35\u0E49
28
+ pple whoami \u0E14\u0E39\u0E27\u0E48\u0E32\u0E01\u0E33\u0E25\u0E31\u0E07\u0E40\u0E02\u0E49\u0E32\u0E2A\u0E39\u0E48\u0E23\u0E30\u0E1A\u0E1A\u0E14\u0E49\u0E27\u0E22\u0E1A\u0E31\u0E0D\u0E0A\u0E35\u0E43\u0E14
29
+
30
+ pple init \u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E41\u0E25\u0E30\u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E42\u0E04\u0E49\u0E14\u0E1A\u0E19\u0E40\u0E04\u0E23\u0E37\u0E48\u0E2D\u0E07\u0E19\u0E35\u0E49
31
+ pple init --name "App" \u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E42\u0E14\u0E22\u0E44\u0E21\u0E48\u0E15\u0E49\u0E2D\u0E07\u0E16\u0E32\u0E21 (\u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A agent/\u0E2A\u0E04\u0E23\u0E34\u0E1B\u0E15\u0E4C)
32
+ pple init <app> \u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E41\u0E2D\u0E1B\u0E17\u0E35\u0E48\u0E21\u0E35\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27\u0E1A\u0E19\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21
33
+ pple deploy [-m "note"] \u0E2A\u0E48\u0E07\u0E01\u0E32\u0E23\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13\u0E02\u0E36\u0E49\u0E19\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19\u0E08\u0E23\u0E34\u0E07
34
+ pple info [<slug>] \u0E14\u0E39\u0E2A\u0E16\u0E32\u0E19\u0E30 \u0E01\u0E32\u0E23\u0E43\u0E0A\u0E49\u0E07\u0E32\u0E19 \u0E01\u0E32\u0E23\u0E14\u0E35\u0E1E\u0E25\u0E2D\u0E22 \u0E41\u0E25\u0E30\u0E04\u0E35\u0E22\u0E4C env \u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49
35
+
36
+ pple env list \u0E14\u0E39\u0E15\u0E31\u0E27\u0E41\u0E1B\u0E23\u0E41\u0E25\u0E30 secret \u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B\u0E19\u0E35\u0E49
37
+ pple env set <KEY> [VAL] \u0E15\u0E31\u0E49\u0E07\u0E04\u0E48\u0E32\u0E15\u0E31\u0E27\u0E41\u0E1B\u0E23 (\u0E2B\u0E23\u0E37\u0E2D --secret) \u0E23\u0E31\u0E1A\u0E04\u0E48\u0E32\u0E08\u0E32\u0E01 arg, --file \u0E2B\u0E23\u0E37\u0E2D stdin
38
+ pple env delete <KEY> \u0E25\u0E1A\u0E15\u0E31\u0E27\u0E41\u0E1B\u0E23\u0E2B\u0E23\u0E37\u0E2D secret
39
+
40
+ pple upgrade \u0E2D\u0E31\u0E1B\u0E40\u0E14\u0E15 pple \u0E40\u0E1B\u0E47\u0E19\u0E40\u0E27\u0E2D\u0E23\u0E4C\u0E0A\u0E31\u0E19\u0E25\u0E48\u0E32\u0E2A\u0E38\u0E14
41
+
42
+ \u0E15\u0E31\u0E27\u0E40\u0E25\u0E37\u0E2D\u0E01
43
+ -m, --message <note> \u0E2A\u0E34\u0E48\u0E07\u0E17\u0E35\u0E48\u0E40\u0E1B\u0E25\u0E35\u0E48\u0E22\u0E19\u0E41\u0E1B\u0E25\u0E07 \u0E41\u0E2A\u0E14\u0E07\u0E43\u0E19\u0E1B\u0E23\u0E30\u0E27\u0E31\u0E15\u0E34\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B
44
+ --name <App Name> \u0E2A\u0E23\u0E49\u0E32\u0E07\u0E41\u0E2D\u0E1B\u0E43\u0E2B\u0E21\u0E48\u0E14\u0E49\u0E27\u0E22\u0E0A\u0E37\u0E48\u0E2D\u0E19\u0E35\u0E49 (pple init)
45
+ --dir <folder> \u0E15\u0E33\u0E41\u0E2B\u0E19\u0E48\u0E07\u0E17\u0E35\u0E48\u0E08\u0E30\u0E27\u0E32\u0E07\u0E42\u0E04\u0E49\u0E14\u0E02\u0E2D\u0E07\u0E41\u0E2D\u0E1B (pple init)
46
+ --file <path> \u0E2D\u0E48\u0E32\u0E19\u0E04\u0E48\u0E32 env \u0E08\u0E32\u0E01\u0E44\u0E1F\u0E25\u0E4C (pple env set)
47
+ --secret \u0E40\u0E01\u0E47\u0E1A\u0E04\u0E48\u0E32\u0E40\u0E1B\u0E47\u0E19 secret \u0E41\u0E1A\u0E1A\u0E40\u0E02\u0E35\u0E22\u0E19\u0E2D\u0E22\u0E48\u0E32\u0E07\u0E40\u0E14\u0E35\u0E22\u0E27 (pple env set)
48
+ -h, --help \u0E41\u0E2A\u0E14\u0E07\u0E27\u0E34\u0E18\u0E35\u0E43\u0E0A\u0E49\u0E19\u0E35\u0E49
49
+ `;async function Zt(t,e){try{if(Jt(t)){let r=await Yt(e,t);if(r!==null)return r}return await Dr(t,e),0}catch(r){if(r instanceof s)return e.out.fail(r),1;throw r}}async function Dr(t,e){let r=[...t];if(r.length===0||r[0]==="--help"||r[0]==="-h"){e.out.say(zt);return}let n=r.shift();switch(n){case"auth":{let i=r.shift();if(i==="login")return ft(e);if(i==="logout")return mt(e);if(i==="whoami")return G(e);throw tt(`auth ${i??""}`.trim())}case"whoami":return G(e);case"init":{let i=M(r,"--dir"),o=M(r,"--name"),u=r.shift();if(o!==void 0&&u)throw new s("`pple init` \u0E23\u0E31\u0E1A\u0E44\u0E14\u0E49\u0E40\u0E09\u0E1E\u0E32\u0E30\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B\u0E43\u0E2B\u0E21\u0E48 \u0E2B\u0E23\u0E37\u0E2D\u0E41\u0E2D\u0E1B\u0E17\u0E35\u0E48\u0E21\u0E35\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27 \u0E2D\u0E22\u0E48\u0E32\u0E07\u0E43\u0E14\u0E2D\u0E22\u0E48\u0E32\u0E07\u0E2B\u0E19\u0E36\u0E48\u0E07\u0E40\u0E17\u0E48\u0E32\u0E19\u0E31\u0E49\u0E19",'\u0E43\u0E0A\u0E49 `pple init --name "\u0E0A\u0E37\u0E48\u0E2D\u0E41\u0E2D\u0E1B\u0E02\u0E2D\u0E07\u0E04\u0E38\u0E13"` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E2A\u0E23\u0E49\u0E32\u0E07\u0E43\u0E2B\u0E21\u0E48 \u0E2B\u0E23\u0E37\u0E2D `pple init <app>` \u0E2A\u0E33\u0E2B\u0E23\u0E31\u0E1A\u0E41\u0E2D\u0E1B\u0E17\u0E35\u0E48\u0E21\u0E35\u0E2D\u0E22\u0E39\u0E48\u0E41\u0E25\u0E49\u0E27');return Ht(e,{slug:u,name:o,dir:i})}case"deploy":{let i=M(r,"--message","-m");return Rt(e,{message:i})}case"info":{let i=r.shift();return Bt(e,i)}case"env":{let i=r.shift();if(i==="list")return It(e);if(i==="set"){let o=kr(r,"--secret"),u=M(r,"--file"),a=r.shift(),c=r.shift();if(!a)throw new s("`pple env set` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38 KEY","\u0E15\u0E31\u0E27\u0E2D\u0E22\u0E48\u0E32\u0E07: `pple env set API_URL https://example.com`");return Lt(e,{key:a,value:c,secret:o,file:u})}if(i==="delete"){let o=r.shift();if(!o)throw new s("`pple env delete` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38 KEY","\u0E15\u0E31\u0E27\u0E2D\u0E22\u0E48\u0E32\u0E07: `pple env delete API_URL`");return Nt(e,o)}throw tt(`env ${i??""}`.trim())}case"upgrade":return Xt(e);case"help":e.out.say(zt);return;default:throw tt(n??"")}}function tt(t){return new s(`\u0E44\u0E21\u0E48\u0E21\u0E35\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07 \`pple ${t}\``,"\u0E23\u0E31\u0E19 `pple --help` \u0E40\u0E1E\u0E37\u0E48\u0E2D\u0E14\u0E39\u0E04\u0E33\u0E2A\u0E31\u0E48\u0E07\u0E17\u0E31\u0E49\u0E07\u0E2B\u0E21\u0E14")}function M(t,e,r){let n=t.findIndex(o=>o===e||r&&o===r);if(n===-1)return;let[,i]=t.splice(n,2);if(i===void 0||i.startsWith("-"))throw new s(`\`${e}\` \u0E15\u0E49\u0E2D\u0E07\u0E23\u0E30\u0E1A\u0E38\u0E04\u0E48\u0E32\u0E15\u0E32\u0E21\u0E2B\u0E25\u0E31\u0E07`);return i}function kr(t,e){let r=t.indexOf(e);return r===-1?!1:(t.splice(r,1),!0)}import{spawn as ae}from"node:child_process";import ue from"node:readline/promises";import{existsSync as Qt,readFileSync as Ar}from"node:fs";import f from"node:path";import{fileURLToPath as _r}from"node:url";var C={apiBase:"https://api.ppleth.ai",ssoBase:"https://id.peoplesparty.or.th",clientId:"382216793067947795",repoBase:"https://github.com",registryBase:"https://registry.npmjs.org"};function te(t){return{apiBase:t.PPLE_API_BASE??C.apiBase,ssoBase:t.PPLE_SSO_BASE??C.ssoBase,clientId:t.PPLE_CLIENT_ID??C.clientId,repoBase:t.PPLE_REPO_BASE??C.repoBase,registryBase:t.PPLE_REGISTRY_BASE??C.registryBase}}function ee(t,e){let r=t.XDG_CONFIG_HOME?.trim();return f.join(r&&r!==""?r:f.join(e,".config"),"pple")}function re(t){let e=t.PPLE_NO_UPDATE_CHECK?.trim().toLowerCase();return!e||e==="0"||e==="false"}function h(){return f.dirname(f.dirname(_r(import.meta.url)))}function ne(){try{let t=Ar(f.join(h(),"package.json"),"utf8");return String(JSON.parse(t).version??"0.0.0")}catch{return"0.0.0"}}function ie(t){let e=t.PPLE_TEMPLATE_DIR?.trim();if(e)return e;let r=f.join(h(),"templates","golden-path");return Qt(r)?r:f.join(f.dirname(h()),"template")}function oe(t){let e=t.PPLE_SKILLS_DIR?.trim();if(e)return e;let r=f.join(h(),"skills","pple-platform");return Qt(r)?r:f.join(f.dirname(h()),"skills","pple-platform")}function se(){return f.join(h(),"askpass","pple-askpass.mjs")}function le(t,e,r){return new Promise((n,i)=>{let o=ae(t,e,{cwd:r.cwd,env:{...process.env,...r.env},stdio:["ignore","pipe","pipe"]}),u="",a="";o.stdout.on("data",c=>u+=String(c)),o.stderr.on("data",c=>a+=String(c)),o.on("error",i),o.on("close",c=>n({code:c??0,stdout:u,stderr:a}))})}async function br(t){let e=process.platform==="darwin"?"open":process.platform==="win32"?"start":"xdg-open";await le(e,[t],{cwd:process.cwd()}).catch(()=>{})}async function Cr(t){let e=ue.createInterface({input:process.stdin,output:process.stdout});try{let r=await e.question(`${t} [y/N] `);return/^y(es)?$/i.test(r.trim())}finally{e.close()}}async function xr(t){let e=ue.createInterface({input:process.stdin,output:process.stdout});try{return await e.question(`${t} `)}finally{e.close()}}async function Tr(){let t=[];for await(let e of process.stdin)t.push(typeof e=="string"?Buffer.from(e):e);return Buffer.concat(t).toString("utf8")}function Sr(t){return new Promise((e,r)=>{let n=ae(process.execPath,[process.argv[1],...t],{stdio:"inherit"});n.on("error",r),n.on("close",i=>e(i??0))})}function ce(t,e){return{fetch:globalThis.fetch.bind(globalThis),now:()=>Date.now(),sleep:r=>new Promise(n=>setTimeout(n,r)),cwd:process.cwd(),configDir:ee(process.env,e),out:t,openBrowser:br,run:le,templateDir:ie(process.env),skillsDir:oe(process.env),packageDir:h(),version:ne(),interactive:process.stdin.isTTY===!0&&process.stdout.isTTY===!0,confirm:Cr,ask:xr,readStdin:Tr,reexec:Sr,updateChecks:re(process.env),gitAskpass:se(),config:te(process.env)}}function pe(t,e){return{say(r=""){t(`${r}
50
+ `)},fail(r){e(`${r.message}
51
+ `),r.hint&&e(`${r.hint}
52
+ `)}}}var Ir=pe(t=>process.stdout.write(t),t=>process.stderr.write(t));try{process.exitCode=await Zt(process.argv.slice(2),ce(Ir,Rr.homedir()))}catch(t){process.stderr.write(`\u0E40\u0E01\u0E34\u0E14\u0E02\u0E49\u0E2D\u0E1C\u0E34\u0E14\u0E1E\u0E25\u0E32\u0E14\u0E20\u0E32\u0E22\u0E43\u0E19 pple CLI \u0E01\u0E23\u0E38\u0E13\u0E32\u0E2A\u0E48\u0E07\u0E02\u0E49\u0E2D\u0E04\u0E27\u0E32\u0E21\u0E19\u0E35\u0E49\u0E43\u0E2B\u0E49\u0E17\u0E35\u0E21\u0E41\u0E1E\u0E25\u0E15\u0E1F\u0E2D\u0E23\u0E4C\u0E21:
53
+ `),process.stderr.write(`${t instanceof Error?t.stack??t.message:String(t)}
54
+ `),process.exitCode=1}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pplethai/cli",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -17,7 +17,7 @@
17
17
  "templates"
18
18
  ],
19
19
  "scripts": {
20
- "build": "npm run build:template && npm run build:skills && tsc -p tsconfig.build.json",
20
+ "build": "npm run build:template && npm run build:skills && node scripts/bundle.mjs",
21
21
  "build:template": "node scripts/bundle-template.mjs",
22
22
  "build:skills": "node scripts/bundle-skills.mjs",
23
23
  "typecheck": "tsc --noEmit",
@@ -26,6 +26,7 @@
26
26
  },
27
27
  "devDependencies": {
28
28
  "@types/node": "^22.10.0",
29
+ "esbuild": "^0.28.1",
29
30
  "typescript": "^5.8.0",
30
31
  "vitest": "^4.1.10"
31
32
  },
@@ -14,14 +14,14 @@ reinventing a design-system setup from `pple-erp` or other older apps.
14
14
  import "@pplethai/components/styles.css";
15
15
  import "./app.css";
16
16
 
17
- import { Button, Card, CardContent, Logo } from "@pplethai/components";
17
+ import { Button, Card, CardContent, Navbar } from "@pplethai/components";
18
18
  ```
19
19
 
20
20
  Package entry points:
21
21
 
22
22
  | Import | Contents |
23
23
  | ------ | -------- |
24
- | `@pplethai/components` | UI primitives, layout, brand (`Logo`, …), `cn()`, toasts |
24
+ | `@pplethai/components` | UI primitives, layout, brand (`Navbar`, `Logo`, …), `cn()`, toasts |
25
25
  | `@pplethai/components/form` | react-hook-form helpers when you need forms |
26
26
  | `@pplethai/components/styles.css` | Brand tokens — import once |
27
27
 
@@ -34,6 +34,11 @@ the bare `@pplethai/components` import to `dist/index.js`.
34
34
  - Put **page layout** in `web/app.css` (mobile-first, safe-area padding for
35
35
  the WebView). Do not fight the design-system stylesheet with a second
36
36
  full Tailwind stack unless you need it.
37
+ - Top-level chrome uses Shared `<Navbar>` (see `web/App.tsx`). Do not hand-roll
38
+ a header/app bar with `Logo`. With a client router, pass `renderHomeLink` /
39
+ `renderLink` (as in pple-erp); otherwise default `<a href>` links are fine.
40
+ Navbar is `position: fixed` below the `md` breakpoint — pad the page content
41
+ accordingly (the template's `.screen` already does).
37
42
  - Compose screens from design-system components (`Card`, `Button`, `Input`,
38
43
  `Textarea`, `Badge`, `Alert`, …) like the demo cards in `web/App.tsx`.
39
44
  - **Colors and type** come from CSS variables in `styles.css`
@@ -19,6 +19,7 @@
19
19
  "@pplethai/components": "^1.4.3",
20
20
  "@pplethai/pple-today-miniapp-sdk": "^0.1.4",
21
21
  "hono": "^4.12.30",
22
+ "lucide-react": "^0.469.0",
22
23
  "react": "^19.2.0",
23
24
  "react-dom": "^19.2.0",
24
25
  "react-hook-form": "^7.81.0",
@@ -1,20 +1,27 @@
1
1
  import {
2
- Badge,
3
2
  Button,
4
3
  Card,
5
4
  CardContent,
6
5
  CardDescription,
7
6
  CardHeader,
8
7
  CardTitle,
8
+ DropdownMenu,
9
+ DropdownMenuContent,
10
+ DropdownMenuItem,
11
+ DropdownMenuLabel,
12
+ DropdownMenuSeparator,
13
+ DropdownMenuTrigger,
14
+ Icon,
9
15
  Input,
10
- Logo,
16
+ Navbar,
11
17
  Spinner,
12
18
  Textarea,
13
19
  showToast,
14
20
  } from "@pplethai/components";
21
+ import { ChevronDown, LogOut, Plus, Send, Upload, User } from "lucide-react";
15
22
  import { useEffect, useRef, useState } from "react";
16
23
  import type { Me, Note, UploadedFile } from "../shared/api";
17
- import { api, apiJson } from "./pple";
24
+ import { api, apiJson, logout } from "./pple";
18
25
 
19
26
  function bytes(n: number): string {
20
27
  if (n < 1024) return `${n} B`;
@@ -26,35 +33,89 @@ function message(e: unknown): string {
26
33
  return e instanceof Error ? e.message : String(e);
27
34
  }
28
35
 
36
+ // Starter nav — replace with your routes. With a client router, pass
37
+ // renderHomeLink / renderLink (see pple-erp's Navbar wrapper).
38
+ const NAV_ITEMS = [{ href: "/", label: "หน้าหลัก", end: true }];
39
+
29
40
  export function App() {
30
41
  const [me, setMe] = useState<Me | null>(null);
31
42
 
32
43
  useEffect(() => {
33
44
  apiJson<Me>("/api/me").then(setMe).catch((e) => showToast({
34
- title: "Could not load your profile",
45
+ title: "โหลดโปรไฟล์ไม่สำเร็จ",
35
46
  description: message(e),
36
47
  variant: "error",
37
48
  }));
38
49
  }, []);
39
50
 
51
+ const displayName = me?.actor.name ?? me?.actor.sub ?? "";
52
+ const roleLabels = me
53
+ ? [me.effective.activeRole, ...me.effective.extraRoles]
54
+ : [];
55
+
40
56
  return (
41
- <main className="screen">
42
- <header className="appbar">
43
- <Logo className="appbar__logo" title="People's Party" />
44
- <span className="appbar__title">PPLE App</span>
45
- {me && <Badge>{me.actor.name ?? me.actor.sub}</Badge>}
46
- </header>
57
+ <>
58
+ <Navbar
59
+ title="PPLE App"
60
+ pathname={window.location.pathname}
61
+ items={NAV_ITEMS}
62
+ mobileMenuAriaLabel={{ open: "เปิดเมนู", close: "ปิดเมนู" }}
63
+ navAriaLabel="เมนูหลัก"
64
+ >
65
+ {me && (
66
+ <DropdownMenu>
67
+ <DropdownMenuTrigger asChild>
68
+ <Button variant="outline" size="default" className="gap-2">
69
+ <Icon icon={User} />
70
+ <span>{displayName}</span>
71
+ <Icon icon={ChevronDown} size="sm" />
72
+ </Button>
73
+ </DropdownMenuTrigger>
74
+ <DropdownMenuContent align="end" className="w-64">
75
+ <DropdownMenuLabel>
76
+ <div className="font-medium">{displayName}</div>
77
+ {me.actor.mobile && (
78
+ <div className="text-xs text-muted-foreground font-normal">
79
+ {me.actor.mobile}
80
+ </div>
81
+ )}
82
+ {me.effective.isDelegated && (
83
+ <div className="text-xs text-muted-foreground font-normal">
84
+ (ปฏิบัติงานแทน — สิทธิ์เป็นของหัวหน้า)
85
+ </div>
86
+ )}
87
+ </DropdownMenuLabel>
88
+ <DropdownMenuSeparator />
89
+ <DropdownMenuLabel className="text-xs text-muted-foreground font-normal">
90
+ บทบาทของคุณ
91
+ </DropdownMenuLabel>
92
+ {roleLabels.map((label) => (
93
+ <DropdownMenuItem key={label} disabled className="opacity-70">
94
+ {label}
95
+ </DropdownMenuItem>
96
+ ))}
97
+ <DropdownMenuSeparator />
98
+ <DropdownMenuItem onClick={() => void logout()}>
99
+ <Icon icon={LogOut} />
100
+ ออกจากระบบ
101
+ </DropdownMenuItem>
102
+ </DropdownMenuContent>
103
+ </DropdownMenu>
104
+ )}
105
+ </Navbar>
47
106
 
48
- <div className="stack">
49
- <p className="muted">
50
- This is the golden-path template. Each card below exercises one
51
- platform capability. Replace them with your own app.
52
- </p>
53
- <NotesCard />
54
- <FilesCard />
55
- <NotifyCard />
56
- </div>
57
- </main>
107
+ <main className="screen">
108
+ <div className="stack">
109
+ <p className="muted">
110
+ นี่คือเทมเพลตเริ่มต้น แต่ละการ์ดด้านล่างแสดงความสามารถหนึ่งอย่างของ
111
+ แพลตฟอร์ม แทนที่ด้วยแอปของคุณเองได้เลย
112
+ </p>
113
+ <NotesCard />
114
+ <FilesCard />
115
+ <NotifyCard />
116
+ </div>
117
+ </main>
118
+ </>
58
119
  );
59
120
  }
60
121
 
@@ -68,7 +129,7 @@ function NotesCard() {
68
129
  apiJson<{ notes: Note[] }>("/api/notes")
69
130
  .then((r) => setNotes(r.notes))
70
131
  .catch((e) => {
71
- showToast({ title: "Could not load notes", description: message(e), variant: "error" });
132
+ showToast({ title: "โหลดบันทึกไม่สำเร็จ", description: message(e), variant: "error" });
72
133
  // Land on the empty state. Leaving this null would spin forever.
73
134
  setNotes([]);
74
135
  });
@@ -89,7 +150,7 @@ function NotesCard() {
89
150
  setBody("");
90
151
  await load();
91
152
  } catch (e) {
92
- showToast({ title: "Could not save note", description: message(e), variant: "error" });
153
+ showToast({ title: "บันทึกไม่สำเร็จ", description: message(e), variant: "error" });
93
154
  } finally {
94
155
  setSaving(false);
95
156
  }
@@ -98,32 +159,35 @@ function NotesCard() {
98
159
  return (
99
160
  <Card className="card">
100
161
  <CardHeader>
101
- <CardTitle>Notes</CardTitle>
102
- <CardDescription>Reads and writes your app's D1 database.</CardDescription>
162
+ <CardTitle>บันทึก</CardTitle>
163
+ <CardDescription>อ่านและเขียนฐานข้อมูล D1 ของแอป</CardDescription>
103
164
  </CardHeader>
104
165
  <CardContent>
105
166
  <div className="stack">
106
167
  <div className="row">
107
168
  <Input
108
169
  value={body}
109
- placeholder="Write a note…"
170
+ placeholder="เขียนบันทึก…"
110
171
  onChange={(e) => setBody(e.target.value)}
111
172
  onKeyDown={(e) => e.key === "Enter" && add()}
112
173
  />
113
174
  <Button onClick={add} disabled={saving || !body.trim()}>
114
- {saving ? <Spinner /> : "Add"}
175
+ {saving ? <Spinner /> : <Icon icon={Plus} />}
176
+ เพิ่ม
115
177
  </Button>
116
178
  </div>
117
179
  {notes === null ? (
118
180
  <Spinner />
119
181
  ) : notes.length === 0 ? (
120
- <p className="muted">No notes yet.</p>
182
+ <p className="muted">ยังไม่มีบันทึก</p>
121
183
  ) : (
122
184
  <ul className="list">
123
185
  {notes.map((n) => (
124
186
  <li key={n.id} className="list__item">
125
187
  <span>{n.body}</span>
126
- <span className="muted">{new Date(n.createdAt).toLocaleString()}</span>
188
+ <span className="muted">
189
+ {new Date(n.createdAt).toLocaleString("th-TH")}
190
+ </span>
127
191
  </li>
128
192
  ))}
129
193
  </ul>
@@ -144,7 +208,7 @@ function FilesCard() {
144
208
  apiJson<{ files: UploadedFile[] }>("/api/files")
145
209
  .then((r) => setFiles(r.files))
146
210
  .catch((e) => {
147
- showToast({ title: "Could not load files", description: message(e), variant: "error" });
211
+ showToast({ title: "โหลดไฟล์ไม่สำเร็จ", description: message(e), variant: "error" });
148
212
  // Land on the empty state. Leaving this null would spin forever.
149
213
  setFiles([]);
150
214
  });
@@ -159,11 +223,11 @@ function FilesCard() {
159
223
  const fd = new FormData();
160
224
  fd.append("file", file);
161
225
  const res = await api("/api/files", { method: "POST", body: fd });
162
- if (!res.ok) throw new Error(`upload failed (${res.status})`);
226
+ if (!res.ok) throw new Error(`อัปโหลดไม่สำเร็จ (${res.status})`);
163
227
  if (inputRef.current) inputRef.current.value = "";
164
228
  await load();
165
229
  } catch (e) {
166
- showToast({ title: "Could not upload file", description: message(e), variant: "error" });
230
+ showToast({ title: "อัปโหลดไฟล์ไม่สำเร็จ", description: message(e), variant: "error" });
167
231
  } finally {
168
232
  setUploading(false);
169
233
  }
@@ -172,27 +236,34 @@ function FilesCard() {
172
236
  return (
173
237
  <Card className="card">
174
238
  <CardHeader>
175
- <CardTitle>Files</CardTitle>
176
- <CardDescription>Uploads to your app's R2 bucket.</CardDescription>
239
+ <CardTitle>ไฟล์</CardTitle>
240
+ <CardDescription>อัปโหลดไปยังบัคเก็ต R2 ของแอป</CardDescription>
177
241
  </CardHeader>
178
242
  <CardContent>
179
243
  <div className="stack">
180
244
  <div className="row">
181
- {/* Disabled while uploading, so picking a second file can't start
182
- a concurrent upload. */}
245
+ {/* Hidden native picker; the design-system Button opens it. Disabled
246
+ while uploading so a second pick can't start a concurrent upload. */}
183
247
  <input
184
248
  ref={inputRef}
185
249
  type="file"
186
- className="file-input"
250
+ className="hidden"
187
251
  onChange={upload}
188
252
  disabled={uploading}
189
253
  />
190
- {uploading && <Spinner />}
254
+ <Button
255
+ variant="outline"
256
+ disabled={uploading}
257
+ onClick={() => inputRef.current?.click()}
258
+ >
259
+ {uploading ? <Spinner /> : <Icon icon={Upload} />}
260
+ เลือกไฟล์
261
+ </Button>
191
262
  </div>
192
263
  {files === null ? (
193
264
  <Spinner />
194
265
  ) : files.length === 0 ? (
195
- <p className="muted">No files yet.</p>
266
+ <p className="muted">ยังไม่มีไฟล์</p>
196
267
  ) : (
197
268
  <ul className="list">
198
269
  {files.map((f) => (
@@ -226,20 +297,20 @@ function NotifyCard() {
226
297
  });
227
298
  const data = (await res.json().catch(() => ({}))) as { error?: string };
228
299
  if (res.ok) {
229
- showToast({ title: "Notification sent", variant: "success" });
300
+ showToast({ title: "ส่งการแจ้งเตือนแล้ว", variant: "success" });
230
301
  setTitle("");
231
302
  setBody("");
232
303
  } else if (data.error === "notifications_not_configured") {
233
304
  showToast({
234
- title: "Notifications not configured",
235
- description: "Set NOTIFY_API_BASE and NOTIFY_API_KEY to send for real.",
305
+ title: "ยังไม่ได้ตั้งค่าการแจ้งเตือน",
306
+ description: "ตั้งค่า NOTIFY_API_BASE และ NOTIFY_API_KEY เพื่อส่งจริง",
236
307
  variant: "warning",
237
308
  });
238
309
  } else {
239
- showToast({ title: "Could not send", description: data.error, variant: "error" });
310
+ showToast({ title: "ส่งไม่สำเร็จ", description: data.error, variant: "error" });
240
311
  }
241
312
  } catch (e) {
242
- showToast({ title: "Could not send", description: message(e), variant: "error" });
313
+ showToast({ title: "ส่งไม่สำเร็จ", description: message(e), variant: "error" });
243
314
  } finally {
244
315
  setSending(false);
245
316
  }
@@ -248,18 +319,27 @@ function NotifyCard() {
248
319
  return (
249
320
  <Card className="card">
250
321
  <CardHeader>
251
- <CardTitle>Notify your users</CardTitle>
322
+ <CardTitle>แจ้งเตือนผู้ใช้</CardTitle>
252
323
  <CardDescription>
253
- Sends an audience-bound push to your App Users — content only, no
254
- phone numbers.
324
+ ส่งการแจ้งเตือนแบบผูกกับกลุ่มผู้ใช้แอป — ส่งเฉพาะเนื้อหา
325
+ ไม่ส่งหมายเลขโทรศัพท์
255
326
  </CardDescription>
256
327
  </CardHeader>
257
328
  <CardContent>
258
329
  <div className="stack">
259
- <Input value={title} placeholder="Title" onChange={(e) => setTitle(e.target.value)} />
260
- <Textarea value={body} placeholder="Message" onChange={(e) => setBody(e.target.value)} />
330
+ <Input
331
+ value={title}
332
+ placeholder="หัวข้อ"
333
+ onChange={(e) => setTitle(e.target.value)}
334
+ />
335
+ <Textarea
336
+ value={body}
337
+ placeholder="ข้อความ"
338
+ onChange={(e) => setBody(e.target.value)}
339
+ />
261
340
  <Button onClick={send} disabled={sending || !title.trim() || !body.trim()}>
262
- {sending ? <Spinner /> : "Send notification"}
341
+ {sending ? <Spinner /> : <Icon icon={Send} />}
342
+ ส่งการแจ้งเตือน
263
343
  </Button>
264
344
  </div>
265
345
  </CardContent>