@voobase/cli 0.1.1-nonprod.2092 → 0.1.1-nonprod.2100

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.
@@ -2452,7 +2452,7 @@ Set-Acl -LiteralPath $credentialPath -AclObject $acl
2452
2452
  </div>
2453
2453
  </body>
2454
2454
  </html>`}function escapeHtml(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function discoverOidcEndpoints(issuer){let discoveryUrl=`${issuer.endsWith("/")?issuer.slice(0,-1):issuer}/.well-known/openid-configuration`,response=await fetch(discoveryUrl);if(!response.ok)throw new Error(`\u83B7\u53D6 OIDC discovery \u5931\u8D25: ${response.status}`);let document=await response.json();if(!document.authorization_endpoint||!document.token_endpoint)throw new Error("OIDC discovery \u7F3A\u5C11\u6388\u6743\u6216 token \u7AEF\u70B9");return{authorization_endpoint:document.authorization_endpoint,device_authorization_endpoint:document.device_authorization_endpoint,token_endpoint:document.token_endpoint}}function getCredentialPath(){return resolveCliStateFilePath("credentials.json")}function getCliContextPath(){return resolveCliStateFilePath("context.json")}function getCliStateDir(){return resolveCliStateDir()}var CliLegacyCredentialStore=class{platform;backend="file";constructor(platform){this.platform=platform}exists(){return existsSync10(getCredentialPath())}read(){return new FileCredentialStore(getCredentialPath(),{platform:this.platform}).read()}write(value){withCliStateFileWriteFallback({fileName:"credentials.json",operation:"\u5199\u5165",write:({filePath})=>new FileCredentialStore(filePath,{platform:this.platform}).write(value)})}delete(){new FileCredentialStore(getCredentialPath(),{platform:this.platform}).delete()}};function resolveCredentialStores(options={}){let stateDir=options.stateDir??getCliStateDir(),platform=options.platform??process.platform,profileName=options.profileName??getDistributionProfile().name,legacyStore=options.legacyStore??(options.stateDir?new FileCredentialStore(join6(stateDir,"credentials.json"),{platform}):new CliLegacyCredentialStore(platform)),hasInjectedStore=Object.prototype.hasOwnProperty.call(options,"secureStore")||Object.prototype.hasOwnProperty.call(options,"legacyStore"),backendPreference=options.backendPreference??(hasInjectedStore?{isFilePreferred:()=>!1,preferFile:()=>{},clear:()=>{}}:new FileCredentialBackendPreference(join6(stateDir,"credential-backend-preference.json")));if(Object.prototype.hasOwnProperty.call(options,"secureStore"))return{secureStore:options.secureStore??null,legacyStore,backendPreference};if(profileName==="developer"||profileName==="test-only")return{secureStore:null,legacyStore,backendPreference};let selectedStore=createCredentialStore({platform,stateDir,profileName});return{secureStore:selectedStore.backend==="file"?null:selectedStore,legacyStore,backendPreference}}function markCredentialOrigin(credentials,backend){return Object.defineProperty(credentials,credentialOriginBackend,{value:backend,enumerable:!1,configurable:!0}),credentials}function getCredentialOrigin(credentials){return credentials[credentialOriginBackend]}function emitCredentialStoreWarnings(warnings,backend){if(warnings.length===0&&backend!=="file"){let report2=inspectCredentialSecurity({credentialsPath:getCredentialPath(),credentialsExist:existsSync10(getCredentialPath()),backend,probeWindowsAcl:!1});emitCredentialSecurityWarnings(report2);return}let report=inspectCredentialSecurity({credentialsPath:getCredentialPath(),credentialsExist:existsSync10(getCredentialPath()),backend,probeWindowsAcl:!1}),existingCodes=new Set(report.findings.map(finding=>finding.code));for(let code2 of warnings){if(existingCodes.has(code2))continue;let detail=credentialStoreWarningDetail(code2);report.findings.push({code:code2,level:code2==="credential_store_corrupted"?"error":"warning",...detail})}report.status=report.findings.some(finding=>finding.level==="error")?"error":report.findings.length>0?"warning":"ok",report.code=report.findings[0]?.code??"credential_security_ok",emitCredentialSecurityWarnings(report)}function credentialStoreWarningDetail(code2){switch(code2){case"credential_migration_pending":return{message:"\u68C0\u6D4B\u5230\u65E7\u7248\u660E\u6587\u51ED\u636E\uFF0C\u5F53\u524D\u767B\u5F55\u6001\u4ECD\u53EF\u7EE7\u7EED\u4F7F\u7528\u3002",action:"\u8FD0\u884C `platform credentials migrate` \u5B8C\u6210\u5F53\u524D\u5E73\u53F0\u7684\u51ED\u636E\u8FC1\u79FB\u6216\u654F\u611F\u5B57\u6BB5\u51C0\u5316\u3002"};case"credential_migration_failed":return{message:"\u51ED\u636E\u5B89\u5168\u8FC1\u79FB\u672A\u5B8C\u6210\uFF0C\u5DF2\u4FDD\u7559\u539F\u6709\u53EF\u7528\u767B\u5F55\u6001\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u72B6\u6001\u540E\u91CD\u8BD5\u8FC1\u79FB\u3002"};case"credential_store_corrupted":return{message:"\u7CFB\u7EDF\u5B89\u5168\u5B58\u50A8\u4E2D\u7684 CLI \u51ED\u636E\u65E0\u6CD5\u8BFB\u53D6\uFF0C\u5DF2\u5C1D\u8BD5\u517C\u5BB9\u51ED\u636E\u3002",action:"\u5982\u65E0\u517C\u5BB9\u51ED\u636E\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`\u3002"};default:return{message:"\u7CFB\u7EDF\u5B89\u5168\u5B58\u50A8\u5F53\u524D\u4E0D\u53EF\u7528\uFF0C\u5DF2\u4F7F\u7528\u517C\u5BB9\u6587\u4EF6\u4E14\u672C\u6B21\u547D\u4EE4\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u72B6\u6001\u5E76\u5728\u6062\u590D\u540E\u91CD\u8BD5\u8FC1\u79FB\u3002"}}}function loadStoredCredentials(storageOptions={}){let stores=resolveCredentialStores(storageOptions),result=readCredentialsWithFallback(stores);return emitCredentialStoreWarnings(result.warnings,result.backend),result.credentials&&result.backend!=="none"?markCredentialOrigin(result.credentials,result.backend):null}function selectApiToken(credentials){if(looksLikeJwt(credentials.access_token)&&isJwtCurrent(credentials.access_token))return credentials.access_token;throw new CliSessionExpiredError("control-api access token \u4E0D\u53EF\u7528")}function loadStoredCliContext(){let cliContextPath=getCliContextPath();return existsSync10(cliContextPath)?JSON.parse(readFileSync9(cliContextPath,"utf8")):null}function persistCredentials(credentials,storageOptions={}){let stores=resolveCredentialStores(storageOptions),result=writeCredentialsWithFallback(credentials,stores);return markCredentialOrigin(credentials,result.backend),emitCredentialStoreWarnings(result.warnings,result.backend),result}function migrateStoredCredentials(storageOptions={}){let stores=resolveCredentialStores(storageOptions),result=migrateLegacyCredentials(stores);return emitCredentialStoreWarnings(result.warnings,result.backend),result}function inspectStoredCredentialSecurity(storageOptions={}){let stores=resolveCredentialStores(storageOptions),credentialsPath=getCredentialPath(),legacyExists=stores.legacyStore.exists?.()??existsSync10(credentialsPath),backend=legacyExists?"file":"none",secureWarning=null;if(stores.secureStore?.exists)try{stores.secureStore.exists()&&(backend=stores.secureStore.backend)}catch(error){secureWarning=error instanceof Error&&"code"in error&&error.code==="credential_store_corrupted"?"credential_store_corrupted":"credential_secure_store_unavailable"}let report=inspectCredentialSecurity({credentialsPath,credentialsExist:legacyExists,backend});return secureWarning&&!report.findings.some(finding=>finding.code===secureWarning)&&(report.findings.push({code:secureWarning,level:secureWarning==="credential_store_corrupted"?"error":"warning",...credentialStoreWarningDetail(secureWarning)}),report.status=secureWarning==="credential_store_corrupted"?"error":"warning",report.code=report.findings[0]?.code??secureWarning),report}function clearStoredAuthentication(storageOptions={}){let stateDir=storageOptions.stateDir??getCliStateDir(),stores=resolveCredentialStores({...storageOptions,stateDir}),cleared=[],failed=[],attempt=(target,operation)=>{try{operation(),cleared.push(target)}catch{failed.push({target})}};stores.secureStore&&attempt(stores.secureStore.backend,()=>stores.secureStore.delete()),attempt("legacy_file",()=>stores.legacyStore.delete()),attempt("account_context",()=>deleteFileIfPresent(join6(stateDir,"context.json"))),attempt("warning_state",()=>deleteFileIfPresent(join6(stateDir,"credential-warning-state.json"))),attempt("backend_preference",()=>deleteFileIfPresent(join6(stateDir,"credential-backend-preference.json")));try{let temporaryFailures=deleteCredentialTemporaryFiles(stateDir,storageOptions.temporaryFileDeleter??deleteFileIfPresent);temporaryFailures.length===0&&cleared.push("orphan_temporary_files"),failed.push(...temporaryFailures.map(name=>({target:`orphan_temporary_file:${name}`})))}catch{failed.push({target:"orphan_temporary_files"})}return{status:failed.length>0?"partial":"cleared",cleared,failed}}function deleteFileIfPresent(filePath){try{unlinkSync4(filePath)}catch(error){if(error.code!=="ENOENT")throw error}}function deleteCredentialTemporaryFiles(stateDir,deleter){let entries;try{entries=readdirSync2(stateDir,{withFileTypes:!0,encoding:"utf8"})}catch(error){if(error.code==="ENOENT")return[];throw error}let failed=[];for(let entry of entries)if(!(!entry.isFile()||!/^(?:credentials\.json|credentials\.dpapi|credential-warning-state\.json|credential-backend-preference\.json)\.tmp-[a-z0-9-]+$/iu.test(entry.name)))try{deleter(join6(stateDir,entry.name))}catch{failed.push(entry.name)}return failed}function persistRefreshedCredentials(nextCredentials,previousCredentials,storageOptions){let stores=resolveCredentialStores(storageOptions);if(getCredentialOrigin(previousCredentials)==="file"){stores.legacyStore.write(toFileFallbackCredentials(nextCredentials)),markCredentialOrigin(nextCredentials,"file");let result={backend:"file",warnings:[],legacyDeleted:!1};return emitCredentialStoreWarnings(result.warnings,result.backend),result}return persistCredentials(nextCredentials,{...storageOptions,...stores})}function resolveStoredClientId(credentials){return credentials.client_id?.trim()||readAuthConfigValue(AUTH_CLI_CLIENT_ID_KEYS)||readAuthConfigValue(AUTH_TENANT_CLIENT_ID_KEYS)}function readJwtExpiryMs(token){if(!looksLikeJwt(token))return null;try{let[,payload]=token.split("."),decoded=JSON.parse(Buffer.from(payload,"base64url").toString("utf8"));return typeof decoded.exp=="number"&&Number.isFinite(decoded.exp)?decoded.exp*1e3:null}catch{return null}}function isJwtCurrent(token,now=Date.now()){let expiresAt=readJwtExpiryMs(token);return expiresAt!==null&&expiresAt>now}function isCredentialExpired(credentials,now=Date.now()){if(looksLikeJwt(credentials.access_token)){let accessTokenExpiry=readJwtExpiryMs(credentials.access_token);return accessTokenExpiry===null||accessTokenExpiry-TOKEN_REFRESH_SKEW_MS<=now}return!0}function canUsePatExchange(credentials,now=Date.now()){if(credentials.credential_mode!=="pat_exchange"||!credentials.exchange_subject_token||!credentials.exchange_subject_token_type||!resolveStoredClientId(credentials)||!credentials.mode_expires_at)return!1;let expiresAt=Date.parse(credentials.mode_expires_at);return Number.isFinite(expiresAt)&&expiresAt>now}async function refreshCredentials(credentials,storageOptions){let issuer=process.env.OIDC_ISSUER?.trim()||getDistributionProfile().defaults?.OIDC_ISSUER?.trim();if(!issuer)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11 OIDC_ISSUER\uFF0C\u65E0\u6CD5\u81EA\u52A8\u5237\u65B0 CLI \u51ED\u636E\u3002");let clientId=resolveStoredClientId(credentials);if(!clientId)throw new Error("\u5F53\u524D\u51ED\u636E\u7F3A\u5C11 client_id\uFF0C\u65E0\u6CD5\u81EA\u52A8\u5237\u65B0 CLI \u51ED\u636E\u3002");if(!credentials.refresh_token)throw new Error("\u5F53\u524D\u51ED\u636E\u7F3A\u5C11 refresh_token\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`\u3002");let endpoints=await discoverOidcEndpoints(issuer),body=new URLSearchParams;body.set("grant_type","refresh_token"),body.set("client_id",clientId),body.set("refresh_token",credentials.refresh_token),applyApiResource(body,process.env.OIDC_AUDIENCE?.trim()||getDistributionProfile().defaults?.OIDC_AUDIENCE?.trim());let response=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body}),payload=await response.json();if(!response.ok)throw mapTokenFailureToAuthError({error:payload.error,errorDescription:payload.error_description,fallback:"\u5237\u65B0 CLI token \u5931\u8D25"});if(typeof payload.access_token!="string"||payload.access_token.length===0)throw new Error("\u5237\u65B0\u540E\u7684 token \u54CD\u5E94\u7F3A\u5C11 access_token");let nextCredentials={access_token:payload.access_token,id_token:typeof payload.id_token=="string"?payload.id_token:credentials.id_token,refresh_token:typeof payload.refresh_token=="string"?payload.refresh_token:credentials.refresh_token,client_id:clientId,token_type:payload.token_type??credentials.token_type,expires_in:typeof payload.expires_in=="number"?payload.expires_in:credentials.expires_in,scope:payload.scope??credentials.scope,issued_at:new Date().toISOString(),credential_mode:credentials.credential_mode??"interactive",exchange_subject_token:credentials.exchange_subject_token,exchange_subject_token_type:credentials.exchange_subject_token_type,mode_expires_at:credentials.mode_expires_at};return selectApiToken(nextCredentials),persistRefreshedCredentials(nextCredentials,credentials,storageOptions),nextCredentials}async function exchangePatCredentials(credentials,storageOptions){let issuer=process.env.OIDC_ISSUER?.trim()||getDistributionProfile().defaults?.OIDC_ISSUER?.trim();if(!issuer)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11 OIDC_ISSUER\uFF0C\u65E0\u6CD5\u81EA\u52A8\u5237\u65B0 PAT \u51ED\u636E\u3002");let clientId=resolveStoredClientId(credentials);if(!clientId)throw new Error("\u5F53\u524D PAT \u51ED\u636E\u7F3A\u5C11 client_id\uFF0C\u65E0\u6CD5\u81EA\u52A8\u5237\u65B0\u3002");if(!credentials.exchange_subject_token||!credentials.exchange_subject_token_type)throw new Error("\u5F53\u524D PAT \u51ED\u636E\u7F3A\u5C11 subject_token\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login --pat <token>`\u3002");if(credentials.mode_expires_at){let hardExpiry=Date.parse(credentials.mode_expires_at);if(Number.isFinite(hardExpiry)&&hardExpiry<=Date.now())throw new Error("\u5F53\u524D PAT \u767B\u5F55\u5DF2\u8D85\u8FC7 7 \u5929\u6709\u6548\u671F\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login --pat <token>`\u3002")}let endpoints=await discoverOidcEndpoints(issuer),body=new URLSearchParams;body.set("grant_type","urn:ietf:params:oauth:grant-type:token-exchange"),body.set("client_id",clientId),body.set("subject_token",credentials.exchange_subject_token),body.set("subject_token_type",credentials.exchange_subject_token_type),body.set("requested_token_type","urn:ietf:params:oauth:token-type:access_token"),credentials.scope?.trim()&&body.set("scope",credentials.scope.trim()),applyApiResource(body,process.env.OIDC_AUDIENCE?.trim()||getDistributionProfile().defaults?.OIDC_AUDIENCE?.trim());let response=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body}),payload=await response.json();if(!response.ok)throw mapTokenFailureToAuthError({error:payload.error,errorDescription:payload.error_description,fallback:"PAT \u4EA4\u6362 access token \u5931\u8D25"});if(typeof payload.access_token!="string"||payload.access_token.length===0)throw new Error("PAT \u4EA4\u6362\u540E\u7684 token \u54CD\u5E94\u7F3A\u5C11 access_token");let nextCredentials={access_token:payload.access_token,id_token:typeof payload.id_token=="string"?payload.id_token:credentials.id_token,client_id:clientId,token_type:payload.token_type??credentials.token_type,expires_in:typeof payload.expires_in=="number"?payload.expires_in:credentials.expires_in,scope:payload.scope??credentials.scope,issued_at:new Date().toISOString(),credential_mode:"pat_exchange",exchange_subject_token:credentials.exchange_subject_token,exchange_subject_token_type:credentials.exchange_subject_token_type,mode_expires_at:credentials.mode_expires_at};return selectApiToken(nextCredentials),persistRefreshedCredentials(nextCredentials,credentials,storageOptions),nextCredentials}async function loadStoredCredentialsEnsuringFresh(options={}){let storageOptions=options.storage??{},credentials=loadStoredCredentials(storageOptions);if(!credentials)return null;let expired=isCredentialExpired(credentials);if(!options.forceRefresh&&!expired)return credentials;if(credentials.refresh_token)try{return refreshCredentials(credentials,storageOptions)}catch(error){maybeWrapCredentialRefreshError(error)}if(canUsePatExchange(credentials))try{return exchangePatCredentials(credentials,storageOptions)}catch(error){maybeWrapCredentialRefreshError(error)}if(expired)throw new Error("\u5F53\u524D\u51ED\u636E\u5DF2\u8FC7\u671F\u4E14\u4E0D\u652F\u6301\u81EA\u52A8\u5237\u65B0\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login` \u6216 `platform login --pat <token>`\u3002");return credentials}function persistCliContext(context){withCliStateFileWriteFallback({fileName:"context.json",operation:"\u5199\u5165",write:({filePath,stateDir})=>{mkdirSync5(stateDir,{recursive:!0}),writeFileSync5(filePath,`${JSON.stringify({...context,updated_at:new Date().toISOString()},null,2)}
2455
- `,"utf8"),chmodSync3(filePath,384)}})}async function performDeviceCodeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer);if(!endpoints.device_authorization_endpoint)throw new Error("OIDC discovery \u7F3A\u5C11 Device Flow \u7AEF\u70B9");let authBody=new URLSearchParams;authBody.set("client_id",config2.clientId),authBody.set("scope",config2.scopes.join(" ")),applyApiResource(authBody,config2.audience);let deviceResponse=await fetch(endpoints.device_authorization_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:authBody}),devicePayload=await deviceResponse.json();if(!deviceResponse.ok)throw new Error(devicePayload.error_description??devicePayload.error??"\u7533\u8BF7 device_code \u5931\u8D25");await config2.onPrompt?.({verificationUri:devicePayload.verification_uri_complete??devicePayload.verification_uri??config2.issuer,userCode:devicePayload.user_code,expiresIn:devicePayload.expires_in});let intervalSeconds=Math.max(devicePayload.interval??5,1),deadline=Date.now()+devicePayload.expires_in*1e3;for(;Date.now()<deadline;){await sleep(intervalSeconds*1e3);let tokenBody=new URLSearchParams;tokenBody.set("grant_type","urn:ietf:params:oauth:grant-type:device_code"),tokenBody.set("device_code",devicePayload.device_code),tokenBody.set("client_id",config2.clientId);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:tokenBody}),tokenPayload=await tokenResponse.json();if(tokenResponse.ok)return{access_token:tokenPayload.access_token,id_token:tokenPayload.id_token,refresh_token:tokenPayload.refresh_token,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope,issued_at:new Date().toISOString(),verificationUri:devicePayload.verification_uri_complete??devicePayload.verification_uri??config2.issuer,userCode:devicePayload.user_code};if(tokenPayload.error!=="authorization_pending"){if(tokenPayload.error==="slow_down"){await sleep(intervalSeconds*1e3);continue}throw new Error(tokenPayload.error_description??tokenPayload.error??"\u8F6E\u8BE2 token \u5931\u8D25")}}throw new Error("Device Code \u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`")}async function performAuthorizationCodeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer),redirectUrl=new URL(config2.redirectUri);if(redirectUrl.protocol!=="http:")throw new Error("CLI \u6D4F\u89C8\u5668\u6388\u6743\u4EC5\u652F\u6301 http \u56DE\u8C03\u5730\u5740");let state=randomBytes3(16).toString("base64url"),nonce=randomBytes3(16).toString("base64url"),codeVerifier=randomBytes3(32).toString("base64url"),codeChallenge=createHash5("sha256").update(codeVerifier).digest("base64url"),authorizationUrl=new URL(endpoints.authorization_endpoint);authorizationUrl.searchParams.set("client_id",config2.clientId),authorizationUrl.searchParams.set("redirect_uri",config2.redirectUri),authorizationUrl.searchParams.set("response_type","code"),authorizationUrl.searchParams.set("scope",config2.scopes.join(" ")),authorizationUrl.searchParams.set("state",state),authorizationUrl.searchParams.set("nonce",nonce),authorizationUrl.searchParams.set("code_challenge",codeChallenge),authorizationUrl.searchParams.set("code_challenge_method","S256");let normalizedPrompt=normalizeAuthorizationPrompt(config2.scopes,config2.prompt);normalizedPrompt&&authorizationUrl.searchParams.set("prompt",normalizedPrompt),applyApiResource(authorizationUrl.searchParams,config2.audience);let callbackResult=await new Promise((resolve20,reject)=>{let timeout=setTimeout(()=>{server.close(()=>{}),reject(new Error("\u6D4F\u89C8\u5668\u6388\u6743\u8D85\u65F6\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`"))},3e5),server=createServer((req,res)=>{let url=new URL(req.url??"/",config2.redirectUri);if(url.pathname!==redirectUrl.pathname){res.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),res.end("Not Found");return}let returnedState=url.searchParams.get("state"),error=url.searchParams.get("error"),code2=url.searchParams.get("code");if(error){clearTimeout(timeout);let errMsg=url.searchParams.get("error_description")??error;res.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginFailureHtml(errMsg)),server.close(()=>{}),reject(new Error(errMsg));return}if(!code2||returnedState!==state){clearTimeout(timeout),res.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginFailureHtml("\u6D4F\u89C8\u5668\u56DE\u8C03\u7F3A\u5C11\u6388\u6743\u7801\u6216 state \u4E0D\u5339\u914D\u3002")),server.close(()=>{}),reject(new Error("\u6D4F\u89C8\u5668\u56DE\u8C03\u7F3A\u5C11 code \u6216 state \u4E0D\u5339\u914D"));return}clearTimeout(timeout),res.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginSuccessHtml()),server.close(()=>{}),resolve20({code:code2})});server.on("error",error=>{clearTimeout(timeout),reject(error)}),server.listen(Number(redirectUrl.port||80),redirectUrl.hostname,async()=>{try{await config2.onPrompt?.({authorizationUrl:authorizationUrl.toString(),redirectUri:config2.redirectUri})}catch(error){clearTimeout(timeout),server.close(()=>{}),reject(error)}})}),tokenBody=new URLSearchParams;tokenBody.set("grant_type","authorization_code"),tokenBody.set("client_id",config2.clientId),tokenBody.set("code",callbackResult.code),tokenBody.set("redirect_uri",config2.redirectUri),tokenBody.set("code_verifier",codeVerifier),applyApiResource(tokenBody,config2.audience);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:tokenBody}),tokenPayload=await tokenResponse.json();if(!tokenResponse.ok)throw new Error(tokenPayload.error_description??tokenPayload.error??"\u6388\u6743\u7801\u6362\u53D6 token \u5931\u8D25");return{access_token:tokenPayload.access_token,id_token:tokenPayload.id_token,refresh_token:tokenPayload.refresh_token,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope,issued_at:new Date().toISOString(),authorizationUrl:authorizationUrl.toString(),redirectUri:config2.redirectUri}}async function performPatTokenExchangeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer),body=new URLSearchParams;body.set("grant_type","urn:ietf:params:oauth:grant-type:token-exchange"),body.set("client_id",config2.clientId),body.set("subject_token",config2.subjectToken),body.set("subject_token_type",config2.subjectTokenType??"urn:logto:token-type:personal_access_token"),body.set("requested_token_type","urn:ietf:params:oauth:token-type:access_token"),config2.scopes.length>0&&body.set("scope",config2.scopes.join(" ")),applyApiResource(body,config2.audience);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body}),tokenPayload=await tokenResponse.json();if(!tokenResponse.ok)throw new Error(tokenPayload.error_description??tokenPayload.error??"PAT \u4EA4\u6362 token \u5931\u8D25");return{access_token:tokenPayload.access_token,id_token:typeof tokenPayload.id_token=="string"?tokenPayload.id_token:void 0,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope??config2.scopes.join(" "),issued_at:new Date().toISOString(),credential_mode:"pat_exchange",exchange_subject_token:config2.subjectToken,exchange_subject_token_type:config2.subjectTokenType??"urn:logto:token-type:personal_access_token",mode_expires_at:new Date(Date.now()+PAT_LOGIN_VALIDITY_MS).toISOString()}}async function fetchWhoAmI(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,tenantId:args.tenantId,capability:"auth",requestClass:"control"}).getWhoAmI()}async function fetchTenantOverview(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,tenantId:args.tenantId,capability:"dashboard",requestClass:"control"}).getTenantOverview()}async function listTenantWorkspaces(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,capability:"auth",requestClass:"control"}).listTenantWorkspaces()}function looksLikeJwt(token){if(!token)return!1;let parts=token.split(".");return parts.length>=2&&parts.every(part=>part.length>0)}import{existsSync as existsSync11,mkdirSync as mkdirSync6,mkdtempSync as mkdtempSync2,readdirSync as readdirSync3,readFileSync as readFileSync10,renameSync as renameSync3,rmSync,statSync as statSync2,writeFileSync as writeFileSync6}from"node:fs";import{createServer as createNetServer}from"node:net";import{basename as basename3,dirname as dirname7,join as join7,relative as relative2,resolve as resolve7}from"node:path";import YAML from"yaml";var DEFAULT_APP_TEMPLATE_KEY="frontend-app-vite";function normalizeAppTemplateKey(value){if(typeof value>"u"||value.trim().length===0)return;let normalized=value.trim();if(normalized==="frontend-app-vite")return"frontend-app-vite";if(normalized==="backend-app-node")return"backend-app-node";throw new Error(`\u4E0D\u652F\u6301\u7684\u5E94\u7528\u6A21\u677F: ${normalized}\u3002\u5F53\u524D\u4EC5\u652F\u6301 \`frontend-app-vite\`\u3001\`backend-app-node\`\u3002\u65E7\u6A21\u677F\u5DF2\u4E0B\u7EBF\u3002`)}var PLATFORM_DIRECTORY=".platform",APP_MANIFEST_FILE="app.yaml",LEGACY_BINDING_FILE=join7(PLATFORM_DIRECTORY,"config.json"),SOURCE_CONTEXT_FILE=join7(PLATFORM_DIRECTORY,"source-context.json"),PLATFORM_BLOCKS_LOCKFILE=join7(PLATFORM_DIRECTORY,"platform-blocks.lock.json").replace(/\\/g,"/"),SOURCE_WORKSPACE_BYTES_LIMIT=50*1024*1024,SOURCE_WORKSPACE_ASSET_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".ico",".bmp",".avif",".mp4",".mp3",".wav",".ogg",".pdf",".woff",".woff2",".ttf",".otf",".eot",".zip",".gz"]);function ensureDirectory(directory){mkdirSync6(directory,{recursive:!0})}function writeFileIfMissing(path3,content){if(existsSync11(path3))throw new Error(`\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${path3}`);ensureDirectory(dirname7(path3)),writeFileSync6(path3,content,"utf8")}function listFilesRecursively(root,current=root){if(!existsSync11(current)||!statSync2(current).isDirectory())return[];let files=[];for(let entry of readdirSync3(current,{withFileTypes:!0})){let absolutePath=join7(current,entry.name);if(entry.isDirectory()){files.push(...listFilesRecursively(root,absolutePath));continue}entry.isFile()&&files.push(relative2(root,absolutePath))}return files.sort((left,right)=>left.localeCompare(right))}function seedRuntimeSdkVendor(targetDir){let workspaceRoot=findWorkspaceRoot(),runtimeSdkDistDir=join7(workspaceRoot,"packages","runtime-sdk","dist");if(!existsSync11(runtimeSdkDistDir)||!statSync2(runtimeSdkDistDir).isDirectory())throw new Error(`\u7F3A\u5C11\u6D4F\u89C8\u5668\u4FA7 runtime-sdk \u6784\u5EFA\u4EA7\u7269\uFF1A${runtimeSdkDistDir}\u3002\u8BF7\u5148\u6267\u884C \`pnpm --filter @platform/runtime-sdk build\`\uFF0C\u518D\u91CD\u65B0\u521D\u59CB\u5316\u8F7B\u5E94\u7528\u6A21\u677F\u3002`);let created=[];for(let relativePath of listFilesRecursively(runtimeSdkDistDir)){let sourcePath=join7(runtimeSdkDistDir,relativePath),outputPath=join7(targetDir,"vendor","runtime-sdk",relativePath);writeFileIfMissing(outputPath,readFileSync10(sourcePath,"utf8")),created.push(relative2(process.cwd(),outputPath))}return created}function normalizeAppManifest(input){let name=typeof input?.name=="string"&&input.name.trim().length>0?input.name.trim():"light-app",moduleName=typeof input?.module=="string"&&input.module.trim().length>0?input.module.trim():"light-app",templateKey=typeof input?.template_key=="string"&&input.template_key.trim().length>0?input.template_key.trim():DEFAULT_APP_TEMPLATE_KEY,normalizedEnvironments=Array.isArray(input?.environments)&&input.environments.length>0?input.environments.map(environment=>typeof environment?.name=="string"&&environment.name.trim().length>0?{name:environment.name.trim()}:null).filter(environment=>environment!==null):[];return{name,version:typeof input?.version=="string"&&input.version.trim().length>0?input.version.trim():"0.1.0",module:moduleName,template_key:templateKey,dev:{auto_restart:input?.dev?.auto_restart===!0},entry:{command:typeof input?.entry?.command=="string"&&input.entry.command.trim().length>0?input.entry.command.trim():"npm run dev",port:typeof input?.entry?.port=="number"&&Number.isFinite(input.entry.port)&&input.entry.port>0?input.entry.port:3e3,health_check:typeof input?.entry?.health_check=="string"&&input.entry.health_check.trim().length>0?input.entry.health_check.trim():"/healthz"},required_skills:Array.isArray(input?.required_skills)?input.required_skills.filter(Boolean):["db","auth"],permissions:Array.isArray(input?.permissions)?input.permissions.filter(Boolean):["app:read","app:write","app:publish"],env_vars:Array.isArray(input?.env_vars)?input.env_vars.filter(Boolean):["PORT","NODE_ENV","APP_ID","APP_ENV","TENANT_ID","DATABASE_URL","DATABASE_SCHEMA","CONTROL_API_BASE_URL"],runtime:{cpu:typeof input?.runtime?.cpu=="string"&&input.runtime.cpu.trim().length>0?input.runtime.cpu.trim():"250m",memory_mb:typeof input?.runtime?.memory_mb=="number"&&Number.isFinite(input.runtime.memory_mb)&&input.runtime.memory_mb>0?input.runtime.memory_mb:256},environments:normalizedEnvironments.length>0?normalizedEnvironments:[{name:"preview"},{name:"prod"}]}}function initProject(targetDir,_appName,templateKey=DEFAULT_APP_TEMPLATE_KEY){let absoluteTargetDir=resolve7(getInvocationCwd(),targetDir);ensureDirectory(absoluteTargetDir);let createdFiles=[],normalizedTemplateKey=normalizeAppTemplateKey(templateKey)??DEFAULT_APP_TEMPLATE_KEY,scaffoldFiles=normalizedTemplateKey==="frontend-app-vite"?assembleFrontendAppViteTemplate():normalizedTemplateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();for(let file of scaffoldFiles){let outputPath=join7(absoluteTargetDir,file.path);writeFileIfMissing(outputPath,file.content),createdFiles.push(relative2(getInvocationCwd(),outputPath))}let vendorCreated=scaffoldFiles.some(file=>file.path.startsWith("vendor/runtime-sdk/")||file.path.startsWith("src/vendor/runtime-sdk/"))?[]:seedRuntimeSdkVendor(absoluteTargetDir);return[...createdFiles,...vendorCreated]}function scaffoldAppDebugSurface(startDir,scaffold){let appRoot=findAppRoot(startDir),appJsPath=join7(appRoot,"src","app.js");if(!existsSync11(appJsPath))throw new Error(`\u672A\u627E\u5230\u5E94\u7528\u5165\u53E3\u6587\u4EF6: ${appJsPath}`);let spec=getAppDebugScaffoldSpec(scaffold),createdFiles=[],updatedFiles=[],targetFilePath=join7(appRoot,spec.filePath);existsSync11(targetFilePath)||(ensureDirectory(dirname7(targetFilePath)),writeFileSync6(targetFilePath,spec.source,"utf8"),createdFiles.push(relative2(appRoot,targetFilePath).replace(/\\/g,"/")));let appSource=readFileSync10(appJsPath,"utf8"),nextSource=injectDebugRouteIntoAppSource(appSource,spec);return nextSource!==appSource&&(writeFileSync6(appJsPath,nextSource,"utf8"),updatedFiles.push(relative2(appRoot,appJsPath).replace(/\\/g,"/"))),{appRoot,createdFiles,updatedFiles,routePath:spec.routePath}}function readAppManifest(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),manifestPath=join7(appRoot,APP_MANIFEST_FILE),raw=readFileSync10(manifestPath,"utf8"),manifest=normalizeAppManifest(YAML.parse(raw));if(!manifest||typeof manifest!="object")throw new Error(`\u65E0\u6548\u7684 app.yaml: ${manifestPath}`);return{directory:appRoot,path:manifestPath,manifest}}function readLegacyBinding(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),bindingPath=join7(appRoot,LEGACY_BINDING_FILE);if(!existsSync11(bindingPath))return null;let raw=JSON.parse(readFileSync10(bindingPath,"utf8")),binding={schema_version:typeof raw.schema_version=="number"?raw.schema_version:1,tenant_id:raw.tenant_id??"",app_id:raw.app_id??"",env:raw.env??"preview",linked_at:raw.linked_at??new Date(0).toISOString(),workspace_name:raw.workspace_name,app_name:raw.app_name,app_display_name:raw.app_display_name,validated_at:raw.validated_at};return{path:bindingPath,binding}}function readBinding(startDir=getInvocationCwd()){let sourceContext=readSourceContext(startDir);if(sourceContext?.sourceContext.tenant_id&&sourceContext.sourceContext.app_id){let context=sourceContext.sourceContext;return{path:sourceContext.path,binding:{schema_version:1,tenant_id:context.tenant_id,app_id:context.app_id,env:context.env||"preview",linked_at:context.linked_at??context.checked_out_at??context.updated_at,workspace_name:context.workspace_name,app_name:context.app_name,app_display_name:context.app_display_name,validated_at:context.validated_at}}}return readLegacyBinding(startDir)}function writeBinding(startDir,binding){let result=updateSourceContext(startDir,{tenant_id:binding.tenant_id,app_id:binding.app_id,env:binding.env,workspace_name:binding.workspace_name,app_name:binding.app_name,app_display_name:binding.app_display_name,validated_at:binding.validated_at,linked_at:new Date().toISOString()});return{appRoot:result.appRoot,path:result.path}}function readSourceContext(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),sourceContextPath=join7(appRoot,SOURCE_CONTEXT_FILE);if(!existsSync11(sourceContextPath))return null;let raw=JSON.parse(readFileSync10(sourceContextPath,"utf8")),sourceContext={schema_version:typeof raw.schema_version=="number"?raw.schema_version:1,tenant_id:raw.tenant_id??"",app_id:raw.app_id??"",env:raw.env??"preview",linked_at:raw.linked_at,validated_at:raw.validated_at,workspace_name:raw.workspace_name,app_name:raw.app_name,app_display_name:raw.app_display_name,template_key:raw.template_key,default_directory:raw.default_directory,generated_from_template:typeof raw.generated_from_template=="boolean"?raw.generated_from_template:void 0,base_source_version_id:raw.base_source_version_id,checked_out_at:raw.checked_out_at,last_submitted_source_version_id:raw.last_submitted_source_version_id,last_submitted_at:raw.last_submitted_at,last_preview_source_version_id:raw.last_preview_source_version_id,last_preview_build_id:raw.last_preview_build_id,last_preview_generated_at:raw.last_preview_generated_at,control_plane:raw.control_plane&&typeof raw.control_plane=="object"?raw.control_plane:void 0,updated_at:raw.updated_at??new Date(0).toISOString()};return{path:sourceContextPath,sourceContext}}function writeSourceContext(startDir,sourceContext){let appRoot=findAppRoot(startDir),path3=join7(appRoot,SOURCE_CONTEXT_FILE);return ensureDirectory(dirname7(path3)),writeFileSync6(path3,`${JSON.stringify({schema_version:1,...sourceContext,updated_at:new Date().toISOString()},null,2)}
2455
+ `,"utf8"),chmodSync3(filePath,384)}})}async function performDeviceCodeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer);if(!endpoints.device_authorization_endpoint)throw new Error("OIDC discovery \u7F3A\u5C11 Device Flow \u7AEF\u70B9");let authBody=new URLSearchParams;authBody.set("client_id",config2.clientId),authBody.set("scope",config2.scopes.join(" ")),applyApiResource(authBody,config2.audience);let deviceResponse=await fetch(endpoints.device_authorization_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:authBody}),devicePayload=await deviceResponse.json();if(!deviceResponse.ok)throw new Error(devicePayload.error_description??devicePayload.error??"\u7533\u8BF7 device_code \u5931\u8D25");await config2.onPrompt?.({verificationUri:devicePayload.verification_uri_complete??devicePayload.verification_uri??config2.issuer,userCode:devicePayload.user_code,expiresIn:devicePayload.expires_in});let intervalSeconds=Math.max(devicePayload.interval??5,1),deadline=Date.now()+devicePayload.expires_in*1e3;for(;Date.now()<deadline;){await sleep(intervalSeconds*1e3);let tokenBody=new URLSearchParams;tokenBody.set("grant_type","urn:ietf:params:oauth:grant-type:device_code"),tokenBody.set("device_code",devicePayload.device_code),tokenBody.set("client_id",config2.clientId);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:tokenBody}),tokenPayload=await tokenResponse.json();if(tokenResponse.ok)return{access_token:tokenPayload.access_token,id_token:tokenPayload.id_token,refresh_token:tokenPayload.refresh_token,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope,issued_at:new Date().toISOString(),verificationUri:devicePayload.verification_uri_complete??devicePayload.verification_uri??config2.issuer,userCode:devicePayload.user_code};if(tokenPayload.error!=="authorization_pending"){if(tokenPayload.error==="slow_down"){await sleep(intervalSeconds*1e3);continue}throw new Error(tokenPayload.error_description??tokenPayload.error??"\u8F6E\u8BE2 token \u5931\u8D25")}}throw new Error("Device Code \u5DF2\u8FC7\u671F\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`")}async function performAuthorizationCodeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer),redirectUrl=new URL(config2.redirectUri);if(redirectUrl.protocol!=="http:")throw new Error("CLI \u6D4F\u89C8\u5668\u6388\u6743\u4EC5\u652F\u6301 http \u56DE\u8C03\u5730\u5740");let state=randomBytes3(16).toString("base64url"),nonce=randomBytes3(16).toString("base64url"),codeVerifier=randomBytes3(32).toString("base64url"),codeChallenge=createHash5("sha256").update(codeVerifier).digest("base64url"),authorizationUrl=new URL(endpoints.authorization_endpoint);authorizationUrl.searchParams.set("client_id",config2.clientId),authorizationUrl.searchParams.set("redirect_uri",config2.redirectUri),authorizationUrl.searchParams.set("response_type","code"),authorizationUrl.searchParams.set("scope",config2.scopes.join(" ")),authorizationUrl.searchParams.set("state",state),authorizationUrl.searchParams.set("nonce",nonce),authorizationUrl.searchParams.set("code_challenge",codeChallenge),authorizationUrl.searchParams.set("code_challenge_method","S256");let normalizedPrompt=normalizeAuthorizationPrompt(config2.scopes,config2.prompt);normalizedPrompt&&authorizationUrl.searchParams.set("prompt",normalizedPrompt),applyApiResource(authorizationUrl.searchParams,config2.audience);let callbackPort=Number(redirectUrl.port||80),callbackResult=await new Promise((resolve20,reject)=>{let server=createServer((req,res)=>{let url=new URL(req.url??"/",config2.redirectUri);if(url.pathname!==redirectUrl.pathname){res.writeHead(404,{"Content-Type":"text/plain; charset=utf-8"}),res.end("Not Found");return}let returnedState=url.searchParams.get("state"),error=url.searchParams.get("error"),code2=url.searchParams.get("code");if(error){let errMsg=url.searchParams.get("error_description")??error;res.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginFailureHtml(errMsg),()=>rejectLogin(new Error(errMsg)));return}if(!code2||returnedState!==state){res.writeHead(400,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginFailureHtml("\u6D4F\u89C8\u5668\u56DE\u8C03\u7F3A\u5C11\u6388\u6743\u7801\u6216 state \u4E0D\u5339\u914D\u3002"),()=>rejectLogin(new Error("\u6D4F\u89C8\u5668\u56DE\u8C03\u7F3A\u5C11 code \u6216 state \u4E0D\u5339\u914D")));return}res.writeHead(200,{"Content-Type":"text/html; charset=utf-8"}),res.end(getLoginSuccessHtml(),()=>resolveLogin({code:code2}))}),settled=!1,timeout,waitingInterval,cleanupAndSettle=settle=>{if(!settled){if(settled=!0,timeout&&clearTimeout(timeout),waitingInterval&&clearInterval(waitingInterval),server.listening){server.close(()=>settle()),server.closeAllConnections();return}settle()}},resolveLogin=result=>{cleanupAndSettle(()=>resolve20(result))},rejectLogin=error=>{cleanupAndSettle(()=>reject(error))};timeout=setTimeout(()=>rejectLogin(new Error("\u6D4F\u89C8\u5668\u6388\u6743\u8D85\u65F6\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`")),Math.max(config2.timeoutMs??300*1e3,1)),server.on("error",error=>{if(error.code==="EADDRINUSE"){rejectLogin(new Error(`CLI \u767B\u5F55\u56DE\u8C03\u7AEF\u53E3 ${redirectUrl.hostname}:${callbackPort} \u5DF2\u88AB\u5360\u7528\uFF1B\u8BF7\u5173\u95ED\u5360\u7528\u8BE5\u7AEF\u53E3\u7684\u65E7\u767B\u5F55\u8FDB\u7A0B\u540E\u91CD\u8BD5\u3002`));return}rejectLogin(error)}),server.listen(callbackPort,redirectUrl.hostname,()=>{config2.onWaiting&&(waitingInterval=setInterval(()=>{Promise.resolve().then(()=>config2.onWaiting?.()).catch(rejectLogin)},Math.max(config2.waitingIntervalMs??6e4,1)),waitingInterval.unref()),Promise.resolve().then(()=>config2.onPrompt?.({authorizationUrl:authorizationUrl.toString(),redirectUri:config2.redirectUri})).catch(rejectLogin)})}),tokenBody=new URLSearchParams;tokenBody.set("grant_type","authorization_code"),tokenBody.set("client_id",config2.clientId),tokenBody.set("code",callbackResult.code),tokenBody.set("redirect_uri",config2.redirectUri),tokenBody.set("code_verifier",codeVerifier),applyApiResource(tokenBody,config2.audience);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:tokenBody}),tokenPayload=await tokenResponse.json();if(!tokenResponse.ok)throw new Error(tokenPayload.error_description??tokenPayload.error??"\u6388\u6743\u7801\u6362\u53D6 token \u5931\u8D25");return{access_token:tokenPayload.access_token,id_token:tokenPayload.id_token,refresh_token:tokenPayload.refresh_token,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope,issued_at:new Date().toISOString(),authorizationUrl:authorizationUrl.toString(),redirectUri:config2.redirectUri}}async function performPatTokenExchangeLogin(config2){let endpoints=await discoverOidcEndpoints(config2.issuer),body=new URLSearchParams;body.set("grant_type","urn:ietf:params:oauth:grant-type:token-exchange"),body.set("client_id",config2.clientId),body.set("subject_token",config2.subjectToken),body.set("subject_token_type",config2.subjectTokenType??"urn:logto:token-type:personal_access_token"),body.set("requested_token_type","urn:ietf:params:oauth:token-type:access_token"),config2.scopes.length>0&&body.set("scope",config2.scopes.join(" ")),applyApiResource(body,config2.audience);let tokenResponse=await fetch(endpoints.token_endpoint,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body}),tokenPayload=await tokenResponse.json();if(!tokenResponse.ok)throw new Error(tokenPayload.error_description??tokenPayload.error??"PAT \u4EA4\u6362 token \u5931\u8D25");return{access_token:tokenPayload.access_token,id_token:typeof tokenPayload.id_token=="string"?tokenPayload.id_token:void 0,client_id:config2.clientId,token_type:tokenPayload.token_type,expires_in:tokenPayload.expires_in,scope:tokenPayload.scope??config2.scopes.join(" "),issued_at:new Date().toISOString(),credential_mode:"pat_exchange",exchange_subject_token:config2.subjectToken,exchange_subject_token_type:config2.subjectTokenType??"urn:logto:token-type:personal_access_token",mode_expires_at:new Date(Date.now()+PAT_LOGIN_VALIDITY_MS).toISOString()}}async function fetchWhoAmI(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,tenantId:args.tenantId,capability:"auth",requestClass:"control"}).getWhoAmI()}async function fetchTenantOverview(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,tenantId:args.tenantId,capability:"dashboard",requestClass:"control"}).getTenantOverview()}async function listTenantWorkspaces(args){return createControlApiSdk({baseUrl:args.baseUrl,accessToken:args.accessToken,capability:"auth",requestClass:"control"}).listTenantWorkspaces()}function looksLikeJwt(token){if(!token)return!1;let parts=token.split(".");return parts.length>=2&&parts.every(part=>part.length>0)}import{existsSync as existsSync11,mkdirSync as mkdirSync6,mkdtempSync as mkdtempSync2,readdirSync as readdirSync3,readFileSync as readFileSync10,renameSync as renameSync3,rmSync,statSync as statSync2,writeFileSync as writeFileSync6}from"node:fs";import{createServer as createNetServer}from"node:net";import{basename as basename3,dirname as dirname7,join as join7,relative as relative2,resolve as resolve7}from"node:path";import YAML from"yaml";var DEFAULT_APP_TEMPLATE_KEY="frontend-app-vite";function normalizeAppTemplateKey(value){if(typeof value>"u"||value.trim().length===0)return;let normalized=value.trim();if(normalized==="frontend-app-vite")return"frontend-app-vite";if(normalized==="backend-app-node")return"backend-app-node";throw new Error(`\u4E0D\u652F\u6301\u7684\u5E94\u7528\u6A21\u677F: ${normalized}\u3002\u5F53\u524D\u4EC5\u652F\u6301 \`frontend-app-vite\`\u3001\`backend-app-node\`\u3002\u65E7\u6A21\u677F\u5DF2\u4E0B\u7EBF\u3002`)}var PLATFORM_DIRECTORY=".platform",APP_MANIFEST_FILE="app.yaml",LEGACY_BINDING_FILE=join7(PLATFORM_DIRECTORY,"config.json"),SOURCE_CONTEXT_FILE=join7(PLATFORM_DIRECTORY,"source-context.json"),PLATFORM_BLOCKS_LOCKFILE=join7(PLATFORM_DIRECTORY,"platform-blocks.lock.json").replace(/\\/g,"/"),SOURCE_WORKSPACE_BYTES_LIMIT=50*1024*1024,SOURCE_WORKSPACE_ASSET_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".ico",".bmp",".avif",".mp4",".mp3",".wav",".ogg",".pdf",".woff",".woff2",".ttf",".otf",".eot",".zip",".gz"]);function ensureDirectory(directory){mkdirSync6(directory,{recursive:!0})}function writeFileIfMissing(path3,content){if(existsSync11(path3))throw new Error(`\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${path3}`);ensureDirectory(dirname7(path3)),writeFileSync6(path3,content,"utf8")}function listFilesRecursively(root,current=root){if(!existsSync11(current)||!statSync2(current).isDirectory())return[];let files=[];for(let entry of readdirSync3(current,{withFileTypes:!0})){let absolutePath=join7(current,entry.name);if(entry.isDirectory()){files.push(...listFilesRecursively(root,absolutePath));continue}entry.isFile()&&files.push(relative2(root,absolutePath))}return files.sort((left,right)=>left.localeCompare(right))}function seedRuntimeSdkVendor(targetDir){let workspaceRoot=findWorkspaceRoot(),runtimeSdkDistDir=join7(workspaceRoot,"packages","runtime-sdk","dist");if(!existsSync11(runtimeSdkDistDir)||!statSync2(runtimeSdkDistDir).isDirectory())throw new Error(`\u7F3A\u5C11\u6D4F\u89C8\u5668\u4FA7 runtime-sdk \u6784\u5EFA\u4EA7\u7269\uFF1A${runtimeSdkDistDir}\u3002\u8BF7\u5148\u6267\u884C \`pnpm --filter @platform/runtime-sdk build\`\uFF0C\u518D\u91CD\u65B0\u521D\u59CB\u5316\u8F7B\u5E94\u7528\u6A21\u677F\u3002`);let created=[];for(let relativePath of listFilesRecursively(runtimeSdkDistDir)){let sourcePath=join7(runtimeSdkDistDir,relativePath),outputPath=join7(targetDir,"vendor","runtime-sdk",relativePath);writeFileIfMissing(outputPath,readFileSync10(sourcePath,"utf8")),created.push(relative2(process.cwd(),outputPath))}return created}function normalizeAppManifest(input){let name=typeof input?.name=="string"&&input.name.trim().length>0?input.name.trim():"light-app",moduleName=typeof input?.module=="string"&&input.module.trim().length>0?input.module.trim():"light-app",templateKey=typeof input?.template_key=="string"&&input.template_key.trim().length>0?input.template_key.trim():DEFAULT_APP_TEMPLATE_KEY,normalizedEnvironments=Array.isArray(input?.environments)&&input.environments.length>0?input.environments.map(environment=>typeof environment?.name=="string"&&environment.name.trim().length>0?{name:environment.name.trim()}:null).filter(environment=>environment!==null):[];return{name,version:typeof input?.version=="string"&&input.version.trim().length>0?input.version.trim():"0.1.0",module:moduleName,template_key:templateKey,dev:{auto_restart:input?.dev?.auto_restart===!0},entry:{command:typeof input?.entry?.command=="string"&&input.entry.command.trim().length>0?input.entry.command.trim():"npm run dev",port:typeof input?.entry?.port=="number"&&Number.isFinite(input.entry.port)&&input.entry.port>0?input.entry.port:3e3,health_check:typeof input?.entry?.health_check=="string"&&input.entry.health_check.trim().length>0?input.entry.health_check.trim():"/healthz"},required_skills:Array.isArray(input?.required_skills)?input.required_skills.filter(Boolean):["db","auth"],permissions:Array.isArray(input?.permissions)?input.permissions.filter(Boolean):["app:read","app:write","app:publish"],env_vars:Array.isArray(input?.env_vars)?input.env_vars.filter(Boolean):["PORT","NODE_ENV","APP_ID","APP_ENV","TENANT_ID","DATABASE_URL","DATABASE_SCHEMA","CONTROL_API_BASE_URL"],runtime:{cpu:typeof input?.runtime?.cpu=="string"&&input.runtime.cpu.trim().length>0?input.runtime.cpu.trim():"250m",memory_mb:typeof input?.runtime?.memory_mb=="number"&&Number.isFinite(input.runtime.memory_mb)&&input.runtime.memory_mb>0?input.runtime.memory_mb:256},environments:normalizedEnvironments.length>0?normalizedEnvironments:[{name:"preview"},{name:"prod"}]}}function initProject(targetDir,_appName,templateKey=DEFAULT_APP_TEMPLATE_KEY){let absoluteTargetDir=resolve7(getInvocationCwd(),targetDir);ensureDirectory(absoluteTargetDir);let createdFiles=[],normalizedTemplateKey=normalizeAppTemplateKey(templateKey)??DEFAULT_APP_TEMPLATE_KEY,scaffoldFiles=normalizedTemplateKey==="frontend-app-vite"?assembleFrontendAppViteTemplate():normalizedTemplateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();for(let file of scaffoldFiles){let outputPath=join7(absoluteTargetDir,file.path);writeFileIfMissing(outputPath,file.content),createdFiles.push(relative2(getInvocationCwd(),outputPath))}let vendorCreated=scaffoldFiles.some(file=>file.path.startsWith("vendor/runtime-sdk/")||file.path.startsWith("src/vendor/runtime-sdk/"))?[]:seedRuntimeSdkVendor(absoluteTargetDir);return[...createdFiles,...vendorCreated]}function scaffoldAppDebugSurface(startDir,scaffold){let appRoot=findAppRoot(startDir),appJsPath=join7(appRoot,"src","app.js");if(!existsSync11(appJsPath))throw new Error(`\u672A\u627E\u5230\u5E94\u7528\u5165\u53E3\u6587\u4EF6: ${appJsPath}`);let spec=getAppDebugScaffoldSpec(scaffold),createdFiles=[],updatedFiles=[],targetFilePath=join7(appRoot,spec.filePath);existsSync11(targetFilePath)||(ensureDirectory(dirname7(targetFilePath)),writeFileSync6(targetFilePath,spec.source,"utf8"),createdFiles.push(relative2(appRoot,targetFilePath).replace(/\\/g,"/")));let appSource=readFileSync10(appJsPath,"utf8"),nextSource=injectDebugRouteIntoAppSource(appSource,spec);return nextSource!==appSource&&(writeFileSync6(appJsPath,nextSource,"utf8"),updatedFiles.push(relative2(appRoot,appJsPath).replace(/\\/g,"/"))),{appRoot,createdFiles,updatedFiles,routePath:spec.routePath}}function readAppManifest(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),manifestPath=join7(appRoot,APP_MANIFEST_FILE),raw=readFileSync10(manifestPath,"utf8"),manifest=normalizeAppManifest(YAML.parse(raw));if(!manifest||typeof manifest!="object")throw new Error(`\u65E0\u6548\u7684 app.yaml: ${manifestPath}`);return{directory:appRoot,path:manifestPath,manifest}}function readLegacyBinding(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),bindingPath=join7(appRoot,LEGACY_BINDING_FILE);if(!existsSync11(bindingPath))return null;let raw=JSON.parse(readFileSync10(bindingPath,"utf8")),binding={schema_version:typeof raw.schema_version=="number"?raw.schema_version:1,tenant_id:raw.tenant_id??"",app_id:raw.app_id??"",env:raw.env??"preview",linked_at:raw.linked_at??new Date(0).toISOString(),workspace_name:raw.workspace_name,app_name:raw.app_name,app_display_name:raw.app_display_name,validated_at:raw.validated_at};return{path:bindingPath,binding}}function readBinding(startDir=getInvocationCwd()){let sourceContext=readSourceContext(startDir);if(sourceContext?.sourceContext.tenant_id&&sourceContext.sourceContext.app_id){let context=sourceContext.sourceContext;return{path:sourceContext.path,binding:{schema_version:1,tenant_id:context.tenant_id,app_id:context.app_id,env:context.env||"preview",linked_at:context.linked_at??context.checked_out_at??context.updated_at,workspace_name:context.workspace_name,app_name:context.app_name,app_display_name:context.app_display_name,validated_at:context.validated_at}}}return readLegacyBinding(startDir)}function writeBinding(startDir,binding){let result=updateSourceContext(startDir,{tenant_id:binding.tenant_id,app_id:binding.app_id,env:binding.env,workspace_name:binding.workspace_name,app_name:binding.app_name,app_display_name:binding.app_display_name,validated_at:binding.validated_at,linked_at:new Date().toISOString()});return{appRoot:result.appRoot,path:result.path}}function readSourceContext(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),sourceContextPath=join7(appRoot,SOURCE_CONTEXT_FILE);if(!existsSync11(sourceContextPath))return null;let raw=JSON.parse(readFileSync10(sourceContextPath,"utf8")),sourceContext={schema_version:typeof raw.schema_version=="number"?raw.schema_version:1,tenant_id:raw.tenant_id??"",app_id:raw.app_id??"",env:raw.env??"preview",linked_at:raw.linked_at,validated_at:raw.validated_at,workspace_name:raw.workspace_name,app_name:raw.app_name,app_display_name:raw.app_display_name,template_key:raw.template_key,default_directory:raw.default_directory,generated_from_template:typeof raw.generated_from_template=="boolean"?raw.generated_from_template:void 0,base_source_version_id:raw.base_source_version_id,checked_out_at:raw.checked_out_at,last_submitted_source_version_id:raw.last_submitted_source_version_id,last_submitted_at:raw.last_submitted_at,last_preview_source_version_id:raw.last_preview_source_version_id,last_preview_build_id:raw.last_preview_build_id,last_preview_generated_at:raw.last_preview_generated_at,control_plane:raw.control_plane&&typeof raw.control_plane=="object"?raw.control_plane:void 0,updated_at:raw.updated_at??new Date(0).toISOString()};return{path:sourceContextPath,sourceContext}}function writeSourceContext(startDir,sourceContext){let appRoot=findAppRoot(startDir),path3=join7(appRoot,SOURCE_CONTEXT_FILE);return ensureDirectory(dirname7(path3)),writeFileSync6(path3,`${JSON.stringify({schema_version:1,...sourceContext,updated_at:new Date().toISOString()},null,2)}
2456
2456
  `,"utf8"),{appRoot,path:path3}}function updateSourceContext(startDir,patch){let appRoot=findAppRoot(startDir),existing=readSourceContext(appRoot)?.sourceContext,legacyBinding=readLegacyBinding(appRoot)?.binding;return writeSourceContext(appRoot,{tenant_id:patch.tenant_id??existing?.tenant_id??legacyBinding?.tenant_id??"",app_id:patch.app_id??existing?.app_id??legacyBinding?.app_id??"",env:patch.env??existing?.env??legacyBinding?.env??"preview",linked_at:patch.linked_at??existing?.linked_at??legacyBinding?.linked_at,validated_at:patch.validated_at??existing?.validated_at??legacyBinding?.validated_at,workspace_name:patch.workspace_name??existing?.workspace_name??legacyBinding?.workspace_name,app_name:patch.app_name??existing?.app_name??legacyBinding?.app_name,app_display_name:patch.app_display_name??existing?.app_display_name??legacyBinding?.app_display_name,template_key:patch.template_key??existing?.template_key,default_directory:patch.default_directory??existing?.default_directory,generated_from_template:typeof patch.generated_from_template=="boolean"?patch.generated_from_template:existing?.generated_from_template,base_source_version_id:patch.base_source_version_id??existing?.base_source_version_id,checked_out_at:patch.checked_out_at??existing?.checked_out_at,last_submitted_source_version_id:patch.last_submitted_source_version_id??existing?.last_submitted_source_version_id,last_submitted_at:patch.last_submitted_at??existing?.last_submitted_at,last_preview_source_version_id:patch.last_preview_source_version_id??existing?.last_preview_source_version_id,last_preview_build_id:patch.last_preview_build_id??existing?.last_preview_build_id,last_preview_generated_at:patch.last_preview_generated_at??existing?.last_preview_generated_at,control_plane:patch.control_plane??existing?.control_plane})}function checkoutSourceWorkspace(targetDir,files,sourceContext){let absoluteTargetDir=resolve7(getInvocationCwd(),targetDir);if(validatePortableWorkspacePaths(files),existsSync11(absoluteTargetDir))throw new Error(`\u76EE\u6807\u76EE\u5F55\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6\uFF08\u5305\u62EC\u7A7A\u76EE\u5F55\uFF09: ${absoluteTargetDir}`);let parentDir=dirname7(absoluteTargetDir);ensureDirectory(parentDir);let stagingDir=mkdtempSync2(join7(parentDir,`.${basename3(absoluteTargetDir)}.platform-checkout-`));try{for(let file of files){let normalizedPath=normalizePortableWorkspacePath(file.path);writeFileIfMissing(join7(stagingDir,normalizedPath),file.content)}let now=new Date().toISOString();if(writeFileIfMissing(join7(stagingDir,SOURCE_CONTEXT_FILE),`${JSON.stringify({schema_version:1,...sourceContext,linked_at:sourceContext.linked_at??now,updated_at:now},null,2)}
2457
2457
  `),existsSync11(absoluteTargetDir))throw new Error(`\u76EE\u6807\u76EE\u5F55\u5728\u68C0\u51FA\u8FC7\u7A0B\u4E2D\u88AB\u521B\u5EFA\uFF0C\u62D2\u7EDD\u8986\u76D6: ${absoluteTargetDir}`);renameSync3(stagingDir,absoluteTargetDir)}catch(error){throw rmSync(stagingDir,{recursive:!0,force:!0}),error}return files.map(file=>relative2(getInvocationCwd(),join7(absoluteTargetDir,normalizePortableWorkspacePath(file.path))))}function validatePortableWorkspacePaths(files){let canonicalPaths=new Map;for(let file of files){let normalizedPath=normalizePortableWorkspacePath(file.path);if(normalizedPath.toLowerCase()===SOURCE_CONTEXT_FILE.replace(/\\/gu,"/").toLowerCase())throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5\uFF08CLI \u4FDD\u7559\u8DEF\u5F84\uFF09: ${file.path}`);let canonicalPath=normalizedPath.normalize("NFC").toLowerCase(),collision=canonicalPaths.get(canonicalPath);if(collision)throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u51B2\u7A81: ${collision} <-> ${file.path}`);canonicalPaths.set(canonicalPath,file.path)}for(let[canonicalPath,originalPath]of canonicalPaths){let segments=canonicalPath.split("/");for(let index=1;index<segments.length;index+=1){let parentPath=segments.slice(0,index).join("/"),parentOriginalPath=canonicalPaths.get(parentPath);if(parentOriginalPath)throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u51B2\u7A81\uFF08\u6587\u4EF6\u4E0E\u76EE\u5F55\u91CD\u540D\uFF09: ${parentOriginalPath} <-> ${originalPath}`)}}}function normalizePortableWorkspacePath(inputPath){let normalizedSeparators=inputPath.replace(/\\/gu,"/");if(!normalizedSeparators||normalizedSeparators.startsWith("/")||/^[A-Za-z]:/u.test(normalizedSeparators))throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5: ${inputPath}`);let segments=normalizedSeparators.split("/");for(let segment of segments){if(!segment||segment==="."||segment==="..")throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5: ${inputPath}`);if(/[<>:"|?*\u0000-\u001F]/u.test(segment))throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u5305\u542B Windows \u975E\u6CD5\u5B57\u7B26: ${inputPath}`);if(/[. ]$/u.test(segment))throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u542B\u5C3E\u968F\u70B9\u6216\u7A7A\u683C: ${inputPath}`);let baseName=segment.split(".")[0]??segment;if(/^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/iu.test(baseName))throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u4F7F\u7528 Windows \u4FDD\u7559\u540D: ${inputPath}`)}return segments.map(segment=>segment.normalize("NFC")).join("/")}function collectSourceWorkspaceFiles(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),files=walkSourceWorkspace(appRoot,appRoot);return{appRoot,files}}function assertSourceWorkspaceCloudUploadPolicy(appRoot,commandLabel){let stats=scanSourceWorkspaceUploadPolicy(appRoot,appRoot);if(stats.sourceBytes>SOURCE_WORKSPACE_BYTES_LIMIT)throw new Error(`\u5F53\u524D\u6E90\u7801\u5305\u4F53\u79EF ${stats.sourceBytes} bytes\uFF0C\u8D85\u8FC7\u4E91\u7AEF\u6E90\u7801\u4E0A\u4F20\u4E0A\u9650 ${SOURCE_WORKSPACE_BYTES_LIMIT} bytes\u3002`);if(stats.assetHits.length>0)throw new Error([`\u68C0\u6D4B\u5230\u672C\u5730\u7D20\u6750\u8D44\u6E90\uFF0C\u5F53\u524D \`${commandLabel}\` \u4E0D\u8D1F\u8D23\u7D20\u6750\u4E0A\u4F20\u56DE\u5199\u3002`,"Agent \u8BF7\u5148\u53C2\u8003 Skill \u6587\u6863 `design-import.md` \u6267\u884C\u8BBE\u8BA1\u6E90\u7801\u9884\u5904\u7406\uFF0C\u5C06\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u7D20\u6750\u5E93\u5E76\u628A\u6E90\u7801\u6539\u5199\u4E3A\u7D20\u6750\u5E93\u5F15\u7528\u540E\u518D\u8BD5\u3002",`\u793A\u4F8B\u547D\u4E2D: ${stats.assetHits.slice(0,10).join(", ")}`].join(`
2458
2458
  `));return stats}function detectPathBaseRuntimeViolations(files){let violations=[],textFilePattern=/\.(?:[cm]?[jt]sx?|html?|css)$/i,patterns=[{kind:"root_relative_fetch",regex:/\bfetch\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_http_client",regex:/\baxios(?:\.(?:get|post|put|patch|delete|head|options))?\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_href",regex:/\bhref\s*=\s*['"]\/(?!\/)/g},{kind:"root_relative_src",regex:/\bsrc\s*=\s*['"]\/(?!\/)/g}];for(let file of files){if(!textFilePattern.test(file.path)||/^README\.md$/i.test(file.path)||isPlatformDevSupportFile(file.path))continue;let lines=file.content.split(/\r?\n/);for(let index=0;index<lines.length;index+=1){let line=lines[index];for(let pattern of patterns)pattern.regex.lastIndex=0,pattern.regex.test(line)&&violations.push({path:file.path,line:index+1,kind:pattern.kind,snippet:line.trim().slice(0,180)})}}return violations}function isPlatformDevSupportFile(path3){return path3.startsWith("src/platform/dev/")||path3.startsWith("src/web/platform/dev/")||path3.startsWith("src/server/platform/dev/")}function scanSourceWorkspaceUploadPolicy(appRoot,currentDir){let entries=readdirSync3(currentDir,{withFileTypes:!0}),sourceBytes=0,assetHits=[];for(let entry of entries){let absolutePath=join7(currentDir,entry.name),relativePath=relative2(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,entry.isDirectory())){if(entry.isDirectory()){let nested=scanSourceWorkspaceUploadPolicy(appRoot,absolutePath);sourceBytes+=nested.sourceBytes,assetHits.push(...nested.assetHits);continue}entry.isFile()&&(sourceBytes+=statSync2(absolutePath).size,isSourceWorkspaceAssetPath(relativePath)&&assetHits.push(relativePath))}}return{sourceBytes,assetHits}}function shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(!normalized)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")?!0:new Set([".git",".platform","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)}function isSourceWorkspaceAssetPath(relativePath){let lower=relativePath.toLowerCase(),dotIndex=lower.lastIndexOf(".");return dotIndex<0?!1:SOURCE_WORKSPACE_ASSET_EXTENSIONS.has(lower.slice(dotIndex))}function walkSourceWorkspace(appRoot,currentDir){let entries=readdirSync3(currentDir,{withFileTypes:!0}),files=[];for(let entry of entries){let absolutePath=join7(currentDir,entry.name),relativePath=relative2(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspacePath(relativePath,entry.isDirectory())){if(entry.isDirectory()){files.push(...walkSourceWorkspace(appRoot,absolutePath));continue}entry.isFile()&&files.push({path:relativePath,content:readFileSync10(absolutePath,"utf8")})}}return files.sort((left,right)=>left.path.localeCompare(right.path))}function shouldIgnoreSourceWorkspacePath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(normalized.length===0)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")&&topLevel!==".platform"||new Set([".git","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)?!0:topLevel===".platform"?isDirectory?normalized===".platform/platform-blocks.history":normalized!==PLATFORM_BLOCKS_LOCKFILE:!!(!isDirectory&&new Set([".DS_Store",".env",".env.local",".env.dev",".env.ci"]).has(normalized))}function findAppRoot(startDir=getInvocationCwd()){let current=resolve7(getInvocationCwd(),startDir);for(;;){let manifestPath=join7(current,APP_MANIFEST_FILE);if(existsSync11(manifestPath)&&statSync2(manifestPath).isFile())return current;let parent=dirname7(current);if(parent===current)throw new Error("\u672A\u627E\u5230 app.yaml\u3002\u4F18\u5148\u5EFA\u8BAE\u5148\u6267\u884C `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u5F97\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u82E5\u4F60\u660E\u786E\u8981\u5728\u5F53\u524D\u7A7A\u76EE\u5F55\u521D\u59CB\u5316\uFF0C\u518D\u6267\u884C `platform init <project-name>`\u3002");current=parent}}function getAppDebugScaffoldSpec(scaffold){return scaffold==="auth-debug"?{kind:scaffold,routePath:"/debug/auth",filePath:"src/lib/debug-auth-page.js",importLine:'import { renderAuthDebugPage } from "./lib/debug-auth-page.js";',renderCall:"renderAuthDebugPage()",source:buildAuthDebugPageSource()}:scaffold==="cms-debug"?{kind:scaffold,routePath:"/debug/cms",filePath:"src/lib/debug-cms-page.js",importLine:'import { renderCmsDebugPage } from "./lib/debug-cms-page.js";',renderCall:"renderCmsDebugPage()",source:buildCmsDebugPageSource()}:scaffold==="db-debug"?{kind:scaffold,routePath:"/debug/db",filePath:"src/lib/debug-db-page.js",importLine:'import { renderDbDebugPage } from "./lib/debug-db-page.js";',renderCall:"renderDbDebugPage()",source:buildDbDebugPageSource(),extraRouteBlocks:[[' if (pathname === "/api/debug/db-context" && req.method === "GET") {'," sendJson(res, 200, {"," app_id: config.appId,"," tenant_id: config.tenantId || null,"," env: config.appEnv,"," request_id: requestId,"," database_ready: Boolean(config.databaseUrl),"," database_schema: config.databaseSchema || null,"," database_capability_version: process.env.DATABASE_CAPABILITY_VERSION || null,"," database_runtime_role: process.env.DATABASE_RUNTIME_ROLE || null,"," database_migrator_role: process.env.DATABASE_MIGRATOR_ROLE || null"," });"," return;"," }",""].join(`
@@ -2529,7 +2529,8 @@ ${unavailable?"[curl_unavailable] ":"[curl_failed] "}${curlMessage}`,{cause:erro
2529
2529
  `)}function formatAuthMethodLabel(method){switch(method){case"admin_provisioned_password":return"\u90AE\u7BB1\u5BC6\u7801";case"email_magic_link":return"\u90AE\u7BB1 Magic Link";case"phone_sms_otp":return"\u624B\u673A\u9A8C\u8BC1\u7801";case"wechat_oauth":return"\u5FAE\u4FE1\u767B\u5F55"}}function appendDiagnosticFields(message,input){let lines=[message];return typeof input.detail?.feature_key=="string"&&lines.push(`Feature: ${input.detail.feature_key}`),input.code&&lines.push(`Code: ${input.code}`),input.requestId&&lines.push(`Request ID: ${input.requestId}`),lines.join(`
2530
2530
  `)}function formatAuthorizationCodeLoginPrompt(input){return input.opened?`\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002
2531
2531
  `:[input.source==="cli-app"?"\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002":"\u4F7F\u7528 workbench \u914D\u7F6E\u56DE\u9000\u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u5F3A\u5236 prompt=login consent \u4EE5\u907F\u514D\u590D\u7528\u9519\u8BEF SSO \u4F1A\u8BDD\u5E76\u6362\u53D6 refresh token\u3002","\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",`\u6388\u6743\u5730\u5740: ${input.authorizationUrl}`,`\u56DE\u8C03\u5730\u5740: ${input.redirectUri}`,input.source==="workbench-fallback"?"\u82E5\u56DE\u8C03\u7AEF\u53E3\u88AB\u672C\u5730 workbench \u5360\u7528\uFF0C\u8BF7\u5148\u6682\u65F6\u505C\u6B62\u5BF9\u5E94\u670D\u52A1\u540E\u91CD\u8BD5\u3002":"\u8BF7\u786E\u8BA4\u8BE5\u56DE\u8C03\u5730\u5740\u5DF2\u5728\u4E13\u7528 CLI App \u4E2D\u6CE8\u518C\u3002",""].join(`
2532
- `)}function normalizeAuthTemplate(value){if(value!==void 0){if(AUTH_CONFIGURE_TEMPLATE_VALUES.includes(value))return value;throw new Error(`\u65E0\u6548\u7684 \`--template\`\uFF0C\u4EC5\u652F\u6301 ${AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT}\u3002`)}}function buildAuthConfigurePayload(options){let templatePayload=buildTemplatePayload(options.template);if(options.enablePhoneSmsOtp===!1&&templatePayload.enable_phone_sms_otp===!0)throw new Error("\u5F53\u524D `--template` \u4F9D\u8D56 `phone_sms_otp`\uFF0C\u4E0D\u80FD\u540C\u65F6\u4F20 `--disable-phone-sms-otp`\u3002");return{auth_enabled:options.enable?!0:void 0,user_store_id:options.userStoreId,auth_template:templatePayload.auth_template,enable_admin_provisioned_password:options.enableAdminProvisionedPassword,enable_phone_sms_otp:typeof options.enablePhoneSmsOtp=="boolean"?options.enablePhoneSmsOtp:templatePayload.enable_phone_sms_otp,enabled_sign_in_methods:templatePayload.enabled_sign_in_methods,default_sign_in_method:templatePayload.default_sign_in_method,registration_mode:templatePayload.registration_mode}}function hasAuthConfigureChanges(payload){return payload.auth_enabled!==void 0||payload.user_store_id!==void 0||payload.auth_template!==void 0||payload.enable_admin_provisioned_password!==void 0||payload.enable_phone_sms_otp!==void 0||payload.enabled_sign_in_methods!==void 0||payload.default_sign_in_method!==void 0||payload.registration_mode!==void 0}function buildTemplatePayload(template){switch(template){case"phone_sms_otp_only":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["phone_sms_otp"],default_sign_in_method:"phone_sms_otp",registration_mode:"open"};case"email_magic_link_and_phone_sms_otp":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["email_magic_link","phone_sms_otp"],default_sign_in_method:"email_magic_link",registration_mode:"open"};case"email_magic_link_only":case"admin_password_only":case"email_magic_link_and_admin_password":return{auth_template:template};default:return{}}}var BUILD_POLL_INTERVAL_MS=1500,BUILD_POLL_TIMEOUT_MS=18e4;async function runBuildCommand(args){if(hasHelpFlag3(args)){printBuildHelp(args.rest[0]);return}let subcommand=args.rest[0];if(subcommand!=="get"&&subcommand!=="events"&&subcommand!=="validate"&&subcommand!=="run")throw new Error("`platform build` \u4EC5\u652F\u6301 `run`\u3001`get <build-id>`\u3001`events <build-id>` \u6216 `validate --source-version <srcver>`\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let binding;try{binding=readBinding(process.cwd())?.binding}catch{binding=null}let tenantId=readStringOption3(args,"tenant")??binding?.tenant_id,buildId=args.rest[1]??readStringOption3(args,"build");if((subcommand==="get"||subcommand==="events")&&!buildId)throw new Error(`\`platform build ${subcommand}\` \u9700\u8981 <build-id>\uFF0C\u6216\u4F20\u5165 \`--build <build-id>\`\u3002`);let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"});if(subcommand==="run"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!tenantId||!appId||!sourceVersionId)throw new Error("`platform build run` \u9700\u8981 `--source-version <srcver>`\uFF0C\u4EE5\u53CA\u5DF2\u7ED1\u5B9A\u76EE\u5F55\u6216 `--tenant` / `--app`\u3002");let requestedBy=await resolveRequestedBy(sdk),buildConfig=await resolveBuildRunConfig(sdk,appId,sourceVersionId,readBuildConfig(args.options)),created=await sdk.createBuild({tenant_id:tenantId,app_id:appId,source_version_id:sourceVersionId,requested_by:requestedBy,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildRunError(error,appId,sourceVersionId)}),wait=args.options.wait===!0;if(args.options.json===!0&&!wait){process.stdout.write(`${JSON.stringify(created,null,2)}
2532
+ `)}function formatAuthorizationCodeLoginWaiting(){return`\u4ECD\u5728\u7B49\u5F85\u6D4F\u89C8\u5668\u6388\u6743\uFF0C\u8BF7\u5728\u5DF2\u6253\u5F00\u7684\u6D4F\u89C8\u5668\u4E2D\u5B8C\u6210\u767B\u5F55\u3002
2533
+ `}function normalizeAuthTemplate(value){if(value!==void 0){if(AUTH_CONFIGURE_TEMPLATE_VALUES.includes(value))return value;throw new Error(`\u65E0\u6548\u7684 \`--template\`\uFF0C\u4EC5\u652F\u6301 ${AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT}\u3002`)}}function buildAuthConfigurePayload(options){let templatePayload=buildTemplatePayload(options.template);if(options.enablePhoneSmsOtp===!1&&templatePayload.enable_phone_sms_otp===!0)throw new Error("\u5F53\u524D `--template` \u4F9D\u8D56 `phone_sms_otp`\uFF0C\u4E0D\u80FD\u540C\u65F6\u4F20 `--disable-phone-sms-otp`\u3002");return{auth_enabled:options.enable?!0:void 0,user_store_id:options.userStoreId,auth_template:templatePayload.auth_template,enable_admin_provisioned_password:options.enableAdminProvisionedPassword,enable_phone_sms_otp:typeof options.enablePhoneSmsOtp=="boolean"?options.enablePhoneSmsOtp:templatePayload.enable_phone_sms_otp,enabled_sign_in_methods:templatePayload.enabled_sign_in_methods,default_sign_in_method:templatePayload.default_sign_in_method,registration_mode:templatePayload.registration_mode}}function hasAuthConfigureChanges(payload){return payload.auth_enabled!==void 0||payload.user_store_id!==void 0||payload.auth_template!==void 0||payload.enable_admin_provisioned_password!==void 0||payload.enable_phone_sms_otp!==void 0||payload.enabled_sign_in_methods!==void 0||payload.default_sign_in_method!==void 0||payload.registration_mode!==void 0}function buildTemplatePayload(template){switch(template){case"phone_sms_otp_only":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["phone_sms_otp"],default_sign_in_method:"phone_sms_otp",registration_mode:"open"};case"email_magic_link_and_phone_sms_otp":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["email_magic_link","phone_sms_otp"],default_sign_in_method:"email_magic_link",registration_mode:"open"};case"email_magic_link_only":case"admin_password_only":case"email_magic_link_and_admin_password":return{auth_template:template};default:return{}}}var BUILD_POLL_INTERVAL_MS=1500,BUILD_POLL_TIMEOUT_MS=18e4;async function runBuildCommand(args){if(hasHelpFlag3(args)){printBuildHelp(args.rest[0]);return}let subcommand=args.rest[0];if(subcommand!=="get"&&subcommand!=="events"&&subcommand!=="validate"&&subcommand!=="run")throw new Error("`platform build` \u4EC5\u652F\u6301 `run`\u3001`get <build-id>`\u3001`events <build-id>` \u6216 `validate --source-version <srcver>`\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let binding;try{binding=readBinding(process.cwd())?.binding}catch{binding=null}let tenantId=readStringOption3(args,"tenant")??binding?.tenant_id,buildId=args.rest[1]??readStringOption3(args,"build");if((subcommand==="get"||subcommand==="events")&&!buildId)throw new Error(`\`platform build ${subcommand}\` \u9700\u8981 <build-id>\uFF0C\u6216\u4F20\u5165 \`--build <build-id>\`\u3002`);let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"});if(subcommand==="run"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!tenantId||!appId||!sourceVersionId)throw new Error("`platform build run` \u9700\u8981 `--source-version <srcver>`\uFF0C\u4EE5\u53CA\u5DF2\u7ED1\u5B9A\u76EE\u5F55\u6216 `--tenant` / `--app`\u3002");let requestedBy=await resolveRequestedBy(sdk),buildConfig=await resolveBuildRunConfig(sdk,appId,sourceVersionId,readBuildConfig(args.options)),created=await sdk.createBuild({tenant_id:tenantId,app_id:appId,source_version_id:sourceVersionId,requested_by:requestedBy,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildRunError(error,appId,sourceVersionId)}),wait=args.options.wait===!0;if(args.options.json===!0&&!wait){process.stdout.write(`${JSON.stringify(created,null,2)}
2533
2534
  `);return}if(!wait){printBuildStarted(created);return}let completed=await waitForBuild(sdk,created.id);if(args.options.json===!0){process.stdout.write(`${JSON.stringify(completed,null,2)}
2534
2535
  `);return}printBuildCompletion(completed);return}if(subcommand==="get"){let result2=await sdk.getBuild(buildId).catch(error=>{throw formatBuildCommandError(error,"get",buildId)});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
2535
2536
  `);return}printBuild(result2);return}if(subcommand==="validate"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!appId||!sourceVersionId)throw new Error("`platform build validate` \u9700\u8981 `--app <app-id>` \u4E0E `--source-version <srcver>`\uFF1B\u82E5\u5F53\u524D\u76EE\u5F55\u5DF2\u7ED1\u5B9A\uFF0C\u53EF\u7701\u7565 `--app`\u3002");let buildConfig=readBuildConfig(args.options),result2=await sdk.getBuildPrecheck(appId,{source_version_id:sourceVersionId,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildValidateError(error,appId,sourceVersionId)});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
@@ -2761,9 +2762,9 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2761
2762
  `):process7.stdout.write([result.status==="cleared"?"\u672C\u5730 CLI \u767B\u5F55\u6001\u5DF2\u6E05\u7406\u3002":"\u672C\u5730 CLI \u767B\u5F55\u6001\u5DF2\u90E8\u5206\u6E05\u7406\u3002",`state \u76EE\u5F55: ${stateDir}`,"\u5DF2\u4FDD\u7559: environment profile\u3001\u9879\u76EE\u5185 .platform/source-context.json",...result.failed.length>0?[`\u672A\u6E05\u7406\u9879: ${result.failed.map(item=>item.target).join(", ")}`,"\u5EFA\u8BAE\uFF1A\u5173\u95ED\u5360\u7528\u7A0B\u5E8F\u6216\u89E3\u9501\u7CFB\u7EDF\u5B89\u5168\u5B58\u50A8\u540E\u91CD\u8BD5 `platform logout`\u3002"]:[],""].join(`
2762
2763
  `)),result.status==="partial"&&(process7.exitCode=2)}async function runLogin(args){let issuer=readRequiredEnv("OIDC_ISSUER"),audience=process7.env.OIDC_AUDIENCE?.trim(),scopes=(process7.env.LOGTO_CLI_SCOPES??"openid profile offline_access").split(/\s+/u).filter(Boolean),cliClientId=readAuthConfigValue(AUTH_CLI_CLIENT_ID_KEYS),browserLoginConfig=resolveBrowserLoginConfig(),pat=readOption2(args,"pat")?.trim(),credentials;if(pat){if(!cliClientId)throw new Error("`platform login --pat` \u9700\u8981\u5DF2\u914D\u7F6E `AUTH_CLI_CLIENT_ID`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_APP_ID`\uFF09\u3002");credentials=await performPatTokenExchangeLogin({issuer,clientId:cliClientId,audience,scopes,subjectToken:pat});let persistence2=persistCredentials(credentials);process7.stdout.write(["PAT \u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5B58\u50A8\u540E\u7AEF: ${persistence2.backend}`,...persistence2.backend==="file"?["\u6CE8\u610F: \u4E3A\u5B89\u5168\u8D77\u89C1\u4E0D\u4F1A\u4FDD\u5B58\u539F\u59CB PAT\uFF0C\u5F53\u524D access token \u5230\u671F\u540E\u9700\u91CD\u65B0\u767B\u5F55\u3002"]:["\u8BF4\u660E: \u5F53\u524D\u4E3A\u673A\u5668\u51ED\u636E\u6A21\u5F0F\uFF0CCLI \u4F1A\u5728 7 \u5929\u7A97\u53E3\u5185\u81EA\u52A8\u91CD\u65B0\u4EA4\u6362 access token\u3002"],"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami"," 2. \u5982\u9700\u957F\u671F\u4EBA\u5DE5\u5F00\u53D1\uFF0C\u4F18\u5148\u6539\u7528 `platform login` \u6D4F\u89C8\u5668\u767B\u5F55",""].join(`
2763
2764
  `));return}if(cliClientId)try{credentials=await performDeviceCodeLogin({issuer,clientId:cliClientId,audience,scopes,onPrompt:async({verificationUri,userCode,expiresIn})=>{let{opened}=await openExternal(verificationUri);process7.stdout.write((opened?["\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",""]:["\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",`\u9A8C\u8BC1\u5730\u5740: ${verificationUri}`,`User Code: ${userCode}`,`\u6709\u6548\u671F: ${expiresIn} \u79D2`,""]).join(`
2764
- `))}})}catch(error){if(!shouldFallbackToBrowserLogin(error))throw error;if(!browserLoginConfig)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11\u53EF\u7528\u4E8E\u6D4F\u89C8\u5668\u767B\u5F55\u7684\u914D\u7F6E\uFF0C\u8BF7\u8865\u9F50 `AUTH_CLI_REDIRECT_URI`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_REDIRECT_URI`\uFF09\uFF0C\u6216\u63D0\u4F9B `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}else{if(!browserLoginConfig)throw new Error("\u7F3A\u5C11\u6D4F\u89C8\u5668\u767B\u5F55\u914D\u7F6E\uFF1A\u8BF7\u4F18\u5148\u8865\u9F50 `AUTH_CLI_CLIENT_ID / AUTH_CLI_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_*`\uFF09\uFF1B\u82E5\u6682\u65F6\u65E0\u6CD5\u63D0\u4F9B\uFF0C\u518D\u8865\u9F50 `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");process7.stdout.write(browserLoginConfig.source==="cli-app"?`\u5F53\u524D\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002
2765
+ `))}})}catch(error){if(!shouldFallbackToBrowserLogin(error))throw error;if(!browserLoginConfig)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11\u53EF\u7528\u4E8E\u6D4F\u89C8\u5668\u767B\u5F55\u7684\u914D\u7F6E\uFF0C\u8BF7\u8865\u9F50 `AUTH_CLI_REDIRECT_URI`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_REDIRECT_URI`\uFF09\uFF0C\u6216\u63D0\u4F9B `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onWaiting:()=>{process7.stdout.write(formatAuthorizationCodeLoginWaiting())},onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}else{if(!browserLoginConfig)throw new Error("\u7F3A\u5C11\u6D4F\u89C8\u5668\u767B\u5F55\u914D\u7F6E\uFF1A\u8BF7\u4F18\u5148\u8865\u9F50 `AUTH_CLI_CLIENT_ID / AUTH_CLI_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_*`\uFF09\uFF1B\u82E5\u6682\u65F6\u65E0\u6CD5\u63D0\u4F9B\uFF0C\u518D\u8865\u9F50 `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");process7.stdout.write(browserLoginConfig.source==="cli-app"?`\u5F53\u524D\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002
2765
2766
  `:`\u672A\u914D\u7F6E\u5B8C\u6574\u4E13\u7528 CLI \u6D4F\u89C8\u5668\u767B\u5F55\u53C2\u6570\uFF0C\u81EA\u52A8\u56DE\u9000\u590D\u7528 workbench \u767B\u5F55\u914D\u7F6E\uFF0C\u5E76\u5F3A\u5236 prompt=login consent\u3002
2766
- `),credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}let persistence=persistCredentials({...credentials,credential_mode:"interactive"}),autoSelectedTenant=null,autoSelectionNote=null;try{let workspaces=await listTenantWorkspaces({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials)});autoSelectedTenant=chooseDefaultTenantWorkspace(workspaces.items),autoSelectedTenant?persistActiveTenantSelection(autoSelectedTenant):workspaces.items.length>1&&(autoSelectionNote="\u68C0\u6D4B\u5230\u591A\u4E2A\u53EF\u7528\u79DF\u6237\uFF0C\u672A\u81EA\u52A8\u5207\u6362\u9ED8\u8BA4\u79DF\u6237\uFF1B\u8BF7\u6267\u884C `platform tenant use <tenant-id>`\u3002")}catch(error){autoSelectionNote=`\u9ED8\u8BA4\u79DF\u6237\u81EA\u52A8\u9009\u62E9\u5931\u8D25\uFF1A${error.message}`}process7.stdout.write(["\u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5B58\u50A8\u540E\u7AEF: ${persistence.backend}`,...autoSelectedTenant?[`\u9ED8\u8BA4\u79DF\u6237\u5DF2\u81EA\u52A8\u8BBE\u7F6E: ${autoSelectedTenant.tenant_id} (${autoSelectedTenant.name})`,`\u4E0A\u4E0B\u6587\u5DF2\u5199\u5165: ${getCliContextPath()}`]:autoSelectionNote?[autoSelectionNote]:[],"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami",' 2. \u65B0\u5EFA\u5E94\u7528\uFF1Aplatform app create --tenant <tenant-id> --name "<app-name>" --dir <project-name>'," 3. \u7F16\u8F91\u5DF2\u6709\u5E94\u7528\uFF1Aplatform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," 4. cd <project-name> && platform dev"," 5. \u9ED8\u8BA4\u5148\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1B\u771F\u5B9E build / preview \u8054\u8C03\u5C5E\u4E8E\u9AD8\u7EA7\u8DEF\u5F84",""].join(`
2767
+ `),credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onWaiting:()=>{process7.stdout.write(formatAuthorizationCodeLoginWaiting())},onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}let persistence=persistCredentials({...credentials,credential_mode:"interactive"}),autoSelectedTenant=null,autoSelectionNote=null;try{let workspaces=await listTenantWorkspaces({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials)});autoSelectedTenant=chooseDefaultTenantWorkspace(workspaces.items),autoSelectedTenant?persistActiveTenantSelection(autoSelectedTenant):workspaces.items.length>1&&(autoSelectionNote="\u68C0\u6D4B\u5230\u591A\u4E2A\u53EF\u7528\u79DF\u6237\uFF0C\u672A\u81EA\u52A8\u5207\u6362\u9ED8\u8BA4\u79DF\u6237\uFF1B\u8BF7\u6267\u884C `platform tenant use <tenant-id>`\u3002")}catch(error){autoSelectionNote=`\u9ED8\u8BA4\u79DF\u6237\u81EA\u52A8\u9009\u62E9\u5931\u8D25\uFF1A${error.message}`}process7.stdout.write(["\u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5B58\u50A8\u540E\u7AEF: ${persistence.backend}`,...autoSelectedTenant?[`\u9ED8\u8BA4\u79DF\u6237\u5DF2\u81EA\u52A8\u8BBE\u7F6E: ${autoSelectedTenant.tenant_id} (${autoSelectedTenant.name})`,`\u4E0A\u4E0B\u6587\u5DF2\u5199\u5165: ${getCliContextPath()}`]:autoSelectionNote?[autoSelectionNote]:[],"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami",' 2. \u65B0\u5EFA\u5E94\u7528\uFF1Aplatform app create --tenant <tenant-id> --name "<app-name>" --dir <project-name>'," 3. \u7F16\u8F91\u5DF2\u6709\u5E94\u7528\uFF1Aplatform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," 4. cd <project-name> && platform dev"," 5. \u9ED8\u8BA4\u5148\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1B\u771F\u5B9E build / preview \u8054\u8C03\u5C5E\u4E8E\u9AD8\u7EA7\u8DEF\u5F84",""].join(`
2767
2768
  `))}async function runWhoAmI(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let tenantId=resolveTenantContext(args),payload=await fetchWhoAmI({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials),tenantId});process7.stdout.write(`${JSON.stringify(payload,null,2)}
2768
2769
  `)}async function runTenant(args){let subcommand=args.rest[0]??"current";if(subcommand==="current"){let context=loadStoredCliContext();if(!context?.active_tenant_id){process7.stdout.write(`\u5F53\u524D\u672A\u8BBE\u7F6E\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\u3002
2769
2770
  `);return}process7.stdout.write([`\u5F53\u524D\u9ED8\u8BA4\u79DF\u6237: ${context.active_tenant_id}`,`\u79DF\u6237\u540D\u79F0: ${context.active_tenant_name??"-"}`,`\u66F4\u65B0\u65F6\u95F4: ${context.updated_at}`,`\u4E0A\u4E0B\u6587\u6587\u4EF6: ${getCliContextPath()}`,""].join(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@voobase/cli",
3
- "version": "0.1.1-nonprod.2092",
3
+ "version": "0.1.1-nonprod.2100",
4
4
  "private": false,
5
5
  "platformDistributionProfile": {
6
6
  "name": "nonprod",
@@ -56,10 +56,10 @@
56
56
  "bundleDependencies": [],
57
57
  "platformDistributionBuild": {
58
58
  "channel": "nonprod",
59
- "version": "0.1.1-nonprod.2092",
60
- "sequence": 2092,
61
- "gitSha": "54b83a4",
62
- "fullGitSha": "54b83a474f4c240b03992f5c164d2ff78d49b2c8",
63
- "buildId": "0.1.1-nonprod.2092+54b83a4"
59
+ "version": "0.1.1-nonprod.2100",
60
+ "sequence": 2100,
61
+ "gitSha": "8bc1491",
62
+ "fullGitSha": "8bc1491ad80f446bec2c96a2b799aade08e0a49b",
63
+ "buildId": "0.1.1-nonprod.2100+8bc1491"
64
64
  }
65
65
  }