@voobase/cli 0.1.1-nonprod.2070 → 0.1.1-nonprod.2073
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/dist-bundle/index.mjs +10 -12
- package/package.json +6 -6
package/dist-bundle/index.mjs
CHANGED
|
@@ -2249,14 +2249,12 @@ foreach ($rule in $acl.GetAccessRules($true, $true, [System.Security.Principal.S
|
|
|
2249
2249
|
dacl_present = ($null -ne $rawDescriptor.DiscretionaryAcl)
|
|
2250
2250
|
rules = $rules
|
|
2251
2251
|
} | ConvertTo-Json -Compress -Depth 4
|
|
2252
|
-
`;function inspectCredentialSecurity(options={}){let platform=options.platform??process.platform,stateLocation=options.stateLocation??resolveCliStateLocation(options.stateResolution),credentialPath=options.credentialsPath??join4(stateLocation.dir,"credentials.json"),credentialsExist=options.credentialsExist??existsSync7(credentialPath),backend=options.backend??(credentialsExist?"file":"none");if(!credentialsExist&&backend==="none")return{status:"ok",code:"credential_security_ok",backend,legacy_plaintext:!1,state:serializeStateLocation(stateLocation),credential_path:credentialPath,permissions:{status:"not_applicable",detail:"no_local_credentials"},findings:[]};let findings=[];stateLocation.insideWorkspace&&findings.push({code:"credential_state_in_workspace",level:"warning",message:"CLI \u51ED\u636E\u72B6\u6001\u76EE\u5F55\u4F4D\u4E8E\u5F53\u524D\u5DE5\u4F5C\u533A\u5185\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u5C06 PLATFORM_STATE_DIR \u8C03\u6574\u5230\u5F53\u524D\u7528\u6237\u4E13\u5C5E\u76EE\u5F55\u540E\u91CD\u65B0\u767B\u5F55\u3002"}),credentialsExist&&findings.push({code:"credential_store_legacy_plaintext",level:"warning",message:"CLI \u51ED\u636E\u4ECD\u4FDD\u5B58\u5728\u517C\u5BB9\u660E\u6587\u6587\u4EF6\u4E2D\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u5B89\u5168\u72B6\u6001\u4E0E\u8FC1\u79FB\u5EFA\u8BAE\u3002"});let permissions=credentialsExist?inspectCredentialPermissions(credentialPath,platform,options):{status:"not_applicable",detail:"no_legacy_plaintext"};return permissions.status==="warning"?findings.push({code:"credential_acl_too_broad",level:"warning",message:"\u51ED\u636E\u6587\u4EF6\u6743\u9650\u53EF\u80FD\u5141\u8BB8\u975E\u9884\u671F\u672C\u673A\u4E3B\u4F53\u8BFB\u53D6\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u8DEF\u5F84\uFF0C\u5E76\u6536\u7D27\u8BE5\u6587\u4EF6\u53CA\u7236\u76EE\u5F55\u6743\u9650\u3002"}):permissions.status==="unknown"&&findings.push({code:"credential_acl_unverified",level:"warning",message:"\u5F53\u524D\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u51ED\u636E\u6587\u4EF6\u6743\u9650\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u8BCA\u65AD\u8BE6\u60C5\u3002"}),{status:findings.some(finding=>finding.level==="error")?"error":findings.length>0?"warning":"ok",code:findings[0]?.code??"credential_security_ok",backend,legacy_plaintext:credentialsExist,state:serializeStateLocation(stateLocation),credential_path:credentialPath,permissions,findings}}function formatCredentialSecurityReportText(report){let lines=["credential security diagnostics:",`- status: ${report.status}`,`- code: ${report.code}`,`- backend: ${report.backend}`,`- state_dir: ${report.state.dir}`,`- state_source: ${report.state.source}`,`- credential_path: ${report.credential_path}`,`- legacy_plaintext: ${report.legacy_plaintext}`,`- permissions: ${report.permissions.status} (${report.permissions.detail})`];for(let finding of report.findings)lines.push(`- warning [${finding.code}]: ${finding.message}`),lines.push(`- action: ${finding.action}`);return`${lines.join(`
|
|
2252
|
+
`;function inspectCredentialSecurity(options={}){let platform=options.platform??process.platform,stateLocation=options.stateLocation??resolveCliStateLocation(options.stateResolution),credentialPath=options.credentialsPath??join4(stateLocation.dir,"credentials.json"),credentialsExist=options.credentialsExist??existsSync7(credentialPath),backend=options.backend??(credentialsExist?"file":"none");if(!credentialsExist&&backend==="none")return{status:"ok",code:"credential_security_ok",backend,legacy_plaintext:!1,state:serializeStateLocation(stateLocation),credential_path:credentialPath,permissions:{status:"not_applicable",detail:"no_local_credentials"},findings:[]};let findings=[];stateLocation.insideWorkspace&&findings.push({code:"credential_state_in_workspace",level:"warning",message:"CLI \u51ED\u636E\u72B6\u6001\u76EE\u5F55\u4F4D\u4E8E\u5F53\u524D\u5DE5\u4F5C\u533A\u5185\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u5C06 PLATFORM_STATE_DIR \u8C03\u6574\u5230\u5F53\u524D\u7528\u6237\u4E13\u5C5E\u76EE\u5F55\u540E\u91CD\u65B0\u767B\u5F55\u3002"}),credentialsExist&&platform==="win32"&&findings.push({code:"credential_store_legacy_plaintext",level:"warning",message:"CLI \u51ED\u636E\u4ECD\u4FDD\u5B58\u5728\u517C\u5BB9\u660E\u6587\u6587\u4EF6\u4E2D\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u5B89\u5168\u72B6\u6001\u4E0E\u8FC1\u79FB\u5EFA\u8BAE\u3002"});let permissions=credentialsExist?inspectCredentialPermissions(credentialPath,platform,options):{status:"not_applicable",detail:"no_legacy_plaintext"};return permissions.status==="warning"?findings.push({code:"credential_acl_too_broad",level:"warning",message:"\u51ED\u636E\u6587\u4EF6\u6743\u9650\u53EF\u80FD\u5141\u8BB8\u975E\u9884\u671F\u672C\u673A\u4E3B\u4F53\u8BFB\u53D6\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u8DEF\u5F84\uFF0C\u5E76\u6536\u7D27\u8BE5\u6587\u4EF6\u53CA\u7236\u76EE\u5F55\u6743\u9650\u3002"}):permissions.status==="unknown"&&findings.push({code:"credential_acl_unverified",level:"warning",message:"\u5F53\u524D\u65E0\u6CD5\u53EF\u9760\u5224\u65AD\u51ED\u636E\u6587\u4EF6\u6743\u9650\uFF0C\u672C\u6B21\u547D\u4EE4\u5C06\u7EE7\u7EED\u6267\u884C\u3002",action:"\u8FD0\u884C `platform diagnostics credentials` \u67E5\u770B\u8BCA\u65AD\u8BE6\u60C5\u3002"}),{status:findings.some(finding=>finding.level==="error")?"error":findings.length>0?"warning":"ok",code:findings[0]?.code??"credential_security_ok",backend,legacy_plaintext:credentialsExist&&platform==="win32",state:serializeStateLocation(stateLocation),credential_path:credentialPath,permissions,findings}}function formatCredentialSecurityReportText(report){let lines=["credential security diagnostics:",`- status: ${report.status}`,`- code: ${report.code}`,`- backend: ${report.backend}`,`- state_dir: ${report.state.dir}`,`- state_source: ${report.state.source}`,`- credential_path: ${report.credential_path}`,`- legacy_plaintext: ${report.legacy_plaintext}`,`- permissions: ${report.permissions.status} (${report.permissions.detail})`];for(let finding of report.findings)lines.push(`- warning [${finding.code}]: ${finding.message}`),lines.push(`- action: ${finding.action}`);return`${lines.join(`
|
|
2253
2253
|
`)}
|
|
2254
2254
|
`}function emitCredentialSecurityWarnings(report,options={}){let warningFindings=report.findings.filter(finding=>finding.level==="warning");if(warningFindings.length===0)return!1;let now=options.now??new Date,fingerprint=createCredentialWarningFingerprint(report),readState=options.readState??(()=>readCredentialWarningState(report.state.dir)),writeState=options.writeState??(state=>writeCredentialWarningState(report.state.dir,state)),previous=readState(),lastNotifiedAt=previous?Date.parse(previous.last_notified_at):Number.NaN;if(previous?.fingerprint===fingerprint&&Number.isFinite(lastNotifiedAt)&&now.getTime()-lastNotifiedAt>=0&&now.getTime()-lastNotifiedAt<(options.intervalMs??DEFAULT_WARNING_INTERVAL_MS))return!1;let message=warningFindings.flatMap(finding=>[`[${finding.code}] ${finding.message}`,`\u5EFA\u8BAE\uFF1A${finding.action}`]).join(`
|
|
2255
2255
|
`);(options.emit??(value=>process.stderr.write(`${value}
|
|
2256
2256
|
`)))(message);try{writeState({fingerprint,last_notified_at:now.toISOString()})}catch{}return!0}function createCredentialWarningFingerprint(report){return createHash3("sha256").update(JSON.stringify({backend:report.backend,state_dir:report.state.dir,state_source:report.state.source,inside_workspace:report.state.inside_workspace,permission_detail:report.permissions.detail,findings:report.findings.map(finding=>finding.code).sort()})).digest("hex")}function readCredentialWarningState(stateDir){try{let payload=JSON.parse(readFileSync7(join4(stateDir,CREDENTIAL_WARNING_STATE_FILE),"utf8"));if(typeof payload.fingerprint=="string"&&typeof payload.last_notified_at=="string")return{fingerprint:payload.fingerprint,last_notified_at:payload.last_notified_at}}catch{}return null}function writeCredentialWarningState(stateDir,state){mkdirSync2(stateDir,{recursive:!0});let targetPath=join4(stateDir,CREDENTIAL_WARNING_STATE_FILE),temporaryPath=`${targetPath}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;writeFileSync3(temporaryPath,`${JSON.stringify(state,null,2)}
|
|
2257
|
-
`,"utf8");try{chmodSync(temporaryPath,384),renameSync(temporaryPath,targetPath)}catch(error){try{existsSync7(temporaryPath)&&unlinkSync(temporaryPath)}catch{}throw error}}function inspectCredentialPermissions(credentialPath,platform,options){if(platform==="win32"){if(options.probeWindowsAcl===!1)return{status:"unknown",detail:"windows_acl_probe_deferred"};try{return(options.windowsAclInspector??inspectWindowsCredentialAcl)(credentialPath)}catch{return{status:"unknown",detail:"windows_acl_probe_failed"}}}try{let stat2=(options.statCredential??(path3=>{let value=lstatSync2(path3);return{mode:value.mode,uid:value.uid,isFile:value.isFile()}}))(credentialPath);if(stat2.isFile===!1)return{status:"unknown",detail:"credential_path_not_regular_file"};let currentUid=options.currentUid??(typeof process.getuid=="function"?process.getuid():void 0),mode=stat2.mode&511;return currentUid===void 0?{status:"unknown",detail:"posix_current_uid_unavailable"}:(mode&63)===0&&stat2.uid===currentUid?{status:"secure",detail:"owner_read_write_only"}:{status:"warning",detail:(mode&63)!==0?"posix_mode_too_broad":"posix_owner_mismatch"}}catch{return{status:"unknown",detail:"posix_permission_probe_failed"}}}function inspectWindowsCredentialAcl(credentialPath){let result=spawnSync(resolveWindowsPowerShellExecutable(),["-NoLogo","-NoProfile","-NonInteractive","-Command",WINDOWS_ACL_SCRIPT],{encoding:"utf8",env:{...process.env,VOOBASE_CREDENTIAL_PATH:credentialPath},shell:!1,timeout:5e3,windowsHide:!0});if(result.error||result.status!==0)return{status:"unknown",detail:result.error?.code==="ETIMEDOUT"?"windows_acl_probe_timeout":"windows_acl_probe_failed"};try{return classifyWindowsAclPayload(JSON.parse(result.stdout.trim()))}catch{}return{status:"unknown",detail:"windows_acl_probe_invalid_output"}}function classifyWindowsAclPayload(value){if(!isWindowsAclPayload(value))return{status:"unknown",detail:"windows_acl_probe_invalid_output"};if(value.owner_sid!==value.current_sid)return{status:"warning",detail:"windows_acl_owner_mismatch"};if(!value.dacl_present)return{status:"warning",detail:"windows_null_dacl"};let allowedReadSids=new Set([value.current_sid,"S-1-5-18","S-1-5-32-544"]);return value.rules.some(rule=>rule.type===0&&(rule.rights&1)!==0&&!allowedReadSids.has(rule.sid))?{status:"warning",detail:"unexpected_read_acl"}:{status:"secure",detail:"current_user_acl"}}function isWindowsAclPayload(value){if(!value||typeof value!="object")return!1;let payload=value;return typeof payload.owner_sid=="string"&&typeof payload.current_sid=="string"&&typeof payload.dacl_present=="boolean"&&Array.isArray(payload.rules)&&payload.rules.every(rule=>!!rule&&typeof rule=="object"&&typeof rule.sid=="string"&&typeof rule.type=="number"&&typeof rule.rights=="number")}function serializeStateLocation(stateLocation){return{dir:stateLocation.dir,source:stateLocation.source,inside_workspace:stateLocation.insideWorkspace}}import{createHash as createHash4,randomBytes as randomBytes2}from"node:crypto";import{spawnSync as
|
|
2258
|
-
${serialized}
|
|
2259
|
-
`);this.assertSucceeded(result)}delete(){let result=this.run(["delete-generic-password","-a",this.options.account,"-s",this.options.service]);result.status!==44&&this.assertSucceeded(result)}run(args,input){return this.spawnSyncImpl("/usr/bin/security",args,{encoding:"utf8",input,shell:!1,timeout:8e3,windowsHide:!0,maxBuffer:2*1024*1024})}assertSucceeded(result){if(!result.error&&result.status===0)return;let code2=result.error?.code,reason=code2==="ENOENT"?"command_missing":code2==="ETIMEDOUT"?"timeout":result.status===36||result.status===51?"access_denied":"operation_failed";throw new CredentialStoreUnavailableError(this.backend,reason)}};import{spawnSync as spawnSync3}from"node:child_process";import{existsSync as existsSync8,mkdirSync as mkdirSync3,unlinkSync as unlinkSync2}from"node:fs";import{dirname as dirname5}from"node:path";var DPAPI_SCRIPT=String.raw`
|
|
2257
|
+
`,"utf8");try{chmodSync(temporaryPath,384),renameSync(temporaryPath,targetPath)}catch(error){try{existsSync7(temporaryPath)&&unlinkSync(temporaryPath)}catch{}throw error}}function inspectCredentialPermissions(credentialPath,platform,options){if(platform==="win32"){if(options.probeWindowsAcl===!1)return{status:"unknown",detail:"windows_acl_probe_deferred"};try{return(options.windowsAclInspector??inspectWindowsCredentialAcl)(credentialPath)}catch{return{status:"unknown",detail:"windows_acl_probe_failed"}}}try{let stat2=(options.statCredential??(path3=>{let value=lstatSync2(path3);return{mode:value.mode,uid:value.uid,isFile:value.isFile()}}))(credentialPath);if(stat2.isFile===!1)return{status:"unknown",detail:"credential_path_not_regular_file"};let currentUid=options.currentUid??(typeof process.getuid=="function"?process.getuid():void 0),mode=stat2.mode&511;return currentUid===void 0?{status:"unknown",detail:"posix_current_uid_unavailable"}:(mode&63)===0&&stat2.uid===currentUid?{status:"secure",detail:"owner_read_write_only"}:{status:"warning",detail:(mode&63)!==0?"posix_mode_too_broad":"posix_owner_mismatch"}}catch{return{status:"unknown",detail:"posix_permission_probe_failed"}}}function inspectWindowsCredentialAcl(credentialPath){let result=spawnSync(resolveWindowsPowerShellExecutable(),["-NoLogo","-NoProfile","-NonInteractive","-Command",WINDOWS_ACL_SCRIPT],{encoding:"utf8",env:{...process.env,VOOBASE_CREDENTIAL_PATH:credentialPath},shell:!1,timeout:5e3,windowsHide:!0});if(result.error||result.status!==0)return{status:"unknown",detail:result.error?.code==="ETIMEDOUT"?"windows_acl_probe_timeout":"windows_acl_probe_failed"};try{return classifyWindowsAclPayload(JSON.parse(result.stdout.trim()))}catch{}return{status:"unknown",detail:"windows_acl_probe_invalid_output"}}function classifyWindowsAclPayload(value){if(!isWindowsAclPayload(value))return{status:"unknown",detail:"windows_acl_probe_invalid_output"};if(value.owner_sid!==value.current_sid)return{status:"warning",detail:"windows_acl_owner_mismatch"};if(!value.dacl_present)return{status:"warning",detail:"windows_null_dacl"};let allowedReadSids=new Set([value.current_sid,"S-1-5-18","S-1-5-32-544"]);return value.rules.some(rule=>rule.type===0&&(rule.rights&1)!==0&&!allowedReadSids.has(rule.sid))?{status:"warning",detail:"unexpected_read_acl"}:{status:"secure",detail:"current_user_acl"}}function isWindowsAclPayload(value){if(!value||typeof value!="object")return!1;let payload=value;return typeof payload.owner_sid=="string"&&typeof payload.current_sid=="string"&&typeof payload.dacl_present=="boolean"&&Array.isArray(payload.rules)&&payload.rules.every(rule=>!!rule&&typeof rule=="object"&&typeof rule.sid=="string"&&typeof rule.type=="number"&&typeof rule.rights=="number")}function serializeStateLocation(stateLocation){return{dir:stateLocation.dir,source:stateLocation.source,inside_workspace:stateLocation.insideWorkspace}}import{createHash as createHash4,randomBytes as randomBytes2}from"node:crypto";import{spawnSync as spawnSync3}from"node:child_process";import{chmodSync as chmodSync2,existsSync as existsSync9,mkdirSync as mkdirSync4,readFileSync as readFileSync8,renameSync as renameSync2,unlinkSync as unlinkSync3,writeFileSync as writeFileSync4}from"node:fs";import{dirname as dirname6,join as join5,resolve as resolve6}from"node:path";import{spawnSync as spawnSync2}from"node:child_process";import{existsSync as existsSync8,mkdirSync as mkdirSync3,unlinkSync as unlinkSync2}from"node:fs";import{dirname as dirname5}from"node:path";var DPAPI_SCRIPT=String.raw`
|
|
2260
2258
|
$ErrorActionPreference = 'Stop'
|
|
2261
2259
|
[void](Add-Type -AssemblyName System.Security -PassThru)
|
|
2262
2260
|
[Console]::InputEncoding = [System.Text.Encoding]::UTF8
|
|
@@ -2294,9 +2292,9 @@ if ($operation -eq 'read') {
|
|
|
2294
2292
|
exit 0
|
|
2295
2293
|
}
|
|
2296
2294
|
throw 'unsupported credential operation'
|
|
2297
|
-
`,WindowsDpapiCredentialStore=class{options;backend="dpapi";spawnSyncImpl;constructor(options){this.options=options,this.spawnSyncImpl=options.spawnSyncImpl??
|
|
2295
|
+
`,WindowsDpapiCredentialStore=class{options;backend="dpapi";spawnSyncImpl;constructor(options){this.options=options,this.spawnSyncImpl=options.spawnSyncImpl??spawnSync2}exists(){return existsSync8(this.options.blobPath)}read(){if(!existsSync8(this.options.blobPath))return null;let result=this.run("read");this.assertSucceeded(result);try{return parseStoredCredentials(result.stdout.trim(),this.backend)}catch(error){throw error instanceof CredentialStoreCorruptedError?error:new CredentialStoreCorruptedError(this.backend)}}write(value){mkdirSync3(dirname5(this.options.blobPath),{recursive:!0});let result=this.run("write",JSON.stringify(value));this.assertSucceeded(result)}delete(){try{unlinkSync2(this.options.blobPath)}catch(error){if(error.code!=="ENOENT")throw new CredentialStoreUnavailableError(this.backend,"operation_failed")}}run(operation,input){return this.spawnSyncImpl(resolveWindowsPowerShellExecutable(),["-NoLogo","-NoProfile","-NonInteractive","-Command",DPAPI_SCRIPT],{encoding:"utf8",input,env:{...process.env,VOOBASE_CREDENTIAL_OPERATION:operation,VOOBASE_CREDENTIAL_PATH:this.options.blobPath,VOOBASE_CREDENTIAL_SERVICE:this.options.service},shell:!1,timeout:8e3,windowsHide:!0,maxBuffer:2*1024*1024})}assertSucceeded(result){if(!result.error&&result.status===0)return;let code2=result.error?.code,reason=code2==="ENOENT"?"command_missing":code2==="ETIMEDOUT"?"timeout":result.status===5?"access_denied":"operation_failed";throw new CredentialStoreUnavailableError(this.backend,reason)}};var CredentialStoreUnavailableError=class extends Error{backend;reason;code="credential_secure_store_unavailable";constructor(backend,reason){super(`Credential store ${backend} is unavailable (${reason}).`),this.backend=backend,this.reason=reason,this.name="CredentialStoreUnavailableError"}},CredentialStoreCorruptedError=class extends Error{backend;code="credential_store_corrupted";constructor(backend){super(`Credential store ${backend} contains invalid data.`),this.backend=backend,this.name="CredentialStoreCorruptedError"}},FileCredentialStore=class{filePath;options;backend="file";constructor(filePath,options={}){this.filePath=filePath,this.options=options}exists(){return existsSync9(this.filePath)}read(){if(!existsSync9(this.filePath))return null;try{return parseStoredCredentials(readFileSync8(this.filePath,"utf8"),this.backend)}catch(error){throw error instanceof CredentialStoreCorruptedError?error:new CredentialStoreUnavailableError(this.backend,"operation_failed")}}write(value){let parentDir=dirname6(this.filePath);mkdirSync4(parentDir,{recursive:!0});let temporaryPath=`${this.filePath}.tmp-${process.pid}-${randomBytes2(4).toString("hex")}`;try{writeFileSync4(temporaryPath,"",{encoding:"utf8",flag:"wx",mode:384}),chmodSync2(temporaryPath,384)}catch{throw tryDeleteFile(temporaryPath),new CredentialStoreUnavailableError(this.backend,"operation_failed")}if((this.options.platform??process.platform)==="win32"){let aclHardened=!1;try{aclHardened=(this.options.windowsAclHardener??hardenWindowsCredentialFileAcl)(temporaryPath)}catch{aclHardened=!1}if(!aclHardened)try{(this.options.onSecurityWarning??defaultFileStoreSecurityWarning)("credential_acl_unverified")}catch{}}try{writeFileSync4(temporaryPath,`${JSON.stringify(value,null,2)}
|
|
2298
2296
|
`,{encoding:"utf8",flag:"r+"}),renameSync2(temporaryPath,this.filePath)}catch{throw tryDeleteFile(temporaryPath),new CredentialStoreUnavailableError(this.backend,"operation_failed")}}delete(){tryDeleteFile(this.filePath)}},FileCredentialBackendPreference=class{filePath;constructor(filePath){this.filePath=filePath}isFilePreferred(){try{return JSON.parse(readFileSync8(this.filePath,"utf8")).preferred_backend==="file"}catch{return!1}}preferFile(){let parentDir=dirname6(this.filePath);mkdirSync4(parentDir,{recursive:!0});let temporaryPath=`${this.filePath}.tmp-${process.pid}-${randomBytes2(4).toString("hex")}`;try{writeFileSync4(temporaryPath,`${JSON.stringify({preferred_backend:"file",reason:"secure_cleanup_failed"},null,2)}
|
|
2299
|
-
`,{encoding:"utf8",flag:"wx",mode:384}),chmodSync2(temporaryPath,384),renameSync2(temporaryPath,this.filePath)}catch{throw tryDeleteFile(temporaryPath),new CredentialStoreUnavailableError("file","operation_failed")}}clear(){tryDeleteFile(this.filePath)}};function readCredentialsWithFallback(options){if(options.backendPreference?.isFilePreferred()){let preferredCredentials=options.legacyStore.read();if(preferredCredentials)return{credentials:preferredCredentials,backend:options.legacyStore.backend,warnings:["credential_secure_store_unavailable"]};try{options.backendPreference.clear()}catch{}}let secureFailure;if(options.secureStore)try{let secureCredentials=options.secureStore.read();if(secureCredentials)return{credentials:secureCredentials,backend:options.secureStore.backend,warnings:[]}}catch(error){secureFailure=error}try{let legacyCredentials=options.legacyStore.read();if(legacyCredentials)return{credentials:legacyCredentials,backend:options.legacyStore.backend,warnings:deduplicateWarnings([secureFailure?classifySecureStoreFailureWithLegacyFallback(secureFailure):"credential_migration_pending"])}}catch(error){throw error instanceof CredentialStoreCorruptedError||error instanceof CredentialStoreUnavailableError?error:new CredentialStoreUnavailableError("file","operation_failed")}if(secureFailure)throw secureFailure instanceof CredentialStoreCorruptedError||secureFailure instanceof CredentialStoreUnavailableError?secureFailure:new CredentialStoreUnavailableError(options.secureStore?.backend??"file","operation_failed");return{credentials:null,backend:"none",warnings:[]}}function writeCredentialsWithFallback(value,options){if(options.secureStore)try{options.secureStore.write(value);let verified=options.secureStore.read();if(!verified||!credentialsEqual(value,verified))throw new CredentialStoreCorruptedError(options.secureStore.backend);try{options.legacyStore.delete();try{options.backendPreference?.clear()}catch{}return{backend:options.secureStore.backend,warnings:[],legacyDeleted:!0}}catch{return{backend:options.secureStore.backend,warnings:["credential_migration_failed"],legacyDeleted:!1}}}catch{options.legacyStore.write(toFileFallbackCredentials(value));let secureDeleted=!1;try{options.secureStore.delete(),secureDeleted=!0}catch{secureDeleted=!1}if(secureDeleted)try{options.backendPreference?.clear()}catch{}else{if(!options.backendPreference)throw new CredentialStoreUnavailableError(options.secureStore.backend,"operation_failed");options.backendPreference.preferFile()}return{backend:options.legacyStore.backend,warnings:["credential_secure_store_unavailable"],legacyDeleted:!1}}return options.legacyStore.write(toFileFallbackCredentials(value)),{backend:options.legacyStore.backend,warnings:[],legacyDeleted:!1}}function migrateLegacyCredentials(options){let legacyCredentials;try{legacyCredentials=options.legacyStore.read()}catch{return{status:"failed",backend:"file",warnings:["credential_migration_failed"],legacyDeleted:!1}}if(!legacyCredentials){if(!options.secureStore)return{status:"not_needed",backend:"none",warnings:[],legacyDeleted:!1};try{return{status:"not_needed",backend:options.secureStore.read()?options.secureStore.backend:"none",warnings:[],legacyDeleted:!1}}catch(error){return{status:"failed",backend:options.secureStore.backend,warnings:[classifySecureStoreFailure(error)],legacyDeleted:!1}}}if(!options.secureStore)return{status:"failed",backend:"file",warnings:["
|
|
2297
|
+
`,{encoding:"utf8",flag:"wx",mode:384}),chmodSync2(temporaryPath,384),renameSync2(temporaryPath,this.filePath)}catch{throw tryDeleteFile(temporaryPath),new CredentialStoreUnavailableError("file","operation_failed")}}clear(){tryDeleteFile(this.filePath)}};function readCredentialsWithFallback(options){if(options.backendPreference?.isFilePreferred()){let preferredCredentials=options.legacyStore.read();if(preferredCredentials)return{credentials:preferredCredentials,backend:options.legacyStore.backend,warnings:["credential_secure_store_unavailable"]};try{options.backendPreference.clear()}catch{}}let secureFailure;if(options.secureStore)try{let secureCredentials=options.secureStore.read();if(secureCredentials)return{credentials:secureCredentials,backend:options.secureStore.backend,warnings:[]}}catch(error){secureFailure=error}try{let legacyCredentials=options.legacyStore.read();if(legacyCredentials)return{credentials:legacyCredentials,backend:options.legacyStore.backend,warnings:options.secureStore?deduplicateWarnings([secureFailure?classifySecureStoreFailureWithLegacyFallback(secureFailure):"credential_migration_pending"]):requiresFileCredentialProjection(legacyCredentials)?["credential_migration_pending"]:[]}}catch(error){throw error instanceof CredentialStoreCorruptedError||error instanceof CredentialStoreUnavailableError?error:new CredentialStoreUnavailableError("file","operation_failed")}if(secureFailure)throw secureFailure instanceof CredentialStoreCorruptedError||secureFailure instanceof CredentialStoreUnavailableError?secureFailure:new CredentialStoreUnavailableError(options.secureStore?.backend??"file","operation_failed");return{credentials:null,backend:"none",warnings:[]}}function writeCredentialsWithFallback(value,options){if(options.secureStore)try{options.secureStore.write(value);let verified=options.secureStore.read();if(!verified||!credentialsEqual(value,verified))throw new CredentialStoreCorruptedError(options.secureStore.backend);try{options.legacyStore.delete();try{options.backendPreference?.clear()}catch{}return{backend:options.secureStore.backend,warnings:[],legacyDeleted:!0}}catch{return{backend:options.secureStore.backend,warnings:["credential_migration_failed"],legacyDeleted:!1}}}catch{options.legacyStore.write(toFileFallbackCredentials(value));let secureDeleted=!1;try{options.secureStore.delete(),secureDeleted=!0}catch{secureDeleted=!1}if(secureDeleted)try{options.backendPreference?.clear()}catch{}else{if(!options.backendPreference)throw new CredentialStoreUnavailableError(options.secureStore.backend,"operation_failed");options.backendPreference.preferFile()}return{backend:options.legacyStore.backend,warnings:["credential_secure_store_unavailable"],legacyDeleted:!1}}return options.legacyStore.write(toFileFallbackCredentials(value)),{backend:options.legacyStore.backend,warnings:[],legacyDeleted:!1}}function migrateLegacyCredentials(options){let legacyCredentials;try{legacyCredentials=options.legacyStore.read()}catch{return{status:"failed",backend:"file",warnings:["credential_migration_failed"],legacyDeleted:!1}}if(!legacyCredentials){if(!options.secureStore)return{status:"not_needed",backend:"none",warnings:[],legacyDeleted:!1};try{return{status:"not_needed",backend:options.secureStore.read()?options.secureStore.backend:"none",warnings:[],legacyDeleted:!1}}catch(error){return{status:"failed",backend:options.secureStore.backend,warnings:[classifySecureStoreFailure(error)],legacyDeleted:!1}}}if(!options.secureStore){if(requiresFileCredentialProjection(legacyCredentials)){let projectedCredentials=toFileFallbackCredentials(legacyCredentials);try{options.legacyStore.write(projectedCredentials);let verified=options.legacyStore.read();if(!verified||!credentialsEqual(projectedCredentials,verified))throw new CredentialStoreCorruptedError("file");return{status:"migrated",backend:"file",warnings:[],legacyDeleted:!1}}catch{try{options.legacyStore.write(legacyCredentials)}catch{}return{status:"failed",backend:"file",warnings:["credential_migration_failed"],legacyDeleted:!1}}}return{status:"not_needed",backend:"file",warnings:[],legacyDeleted:!1}}if(!options.backendPreference?.isFilePreferred())try{if(options.secureStore.read())try{options.legacyStore.delete();try{options.backendPreference?.clear()}catch{}return{status:"not_needed",backend:options.secureStore.backend,warnings:[],legacyDeleted:!0}}catch{return{status:"failed",backend:options.secureStore.backend,warnings:["credential_migration_failed"],legacyDeleted:!1}}}catch(error){if(!(error instanceof CredentialStoreCorruptedError))return{status:"failed",backend:options.secureStore.backend,warnings:["credential_secure_store_unavailable"],legacyDeleted:!1}}try{options.secureStore.write(legacyCredentials);let verified=options.secureStore.read();if(!verified||!credentialsEqual(legacyCredentials,verified))throw new CredentialStoreCorruptedError(options.secureStore.backend);options.legacyStore.delete();try{options.backendPreference?.clear()}catch{}return{status:"migrated",backend:options.secureStore.backend,warnings:[],legacyDeleted:!0}}catch{try{options.secureStore.delete()}catch{}return{status:"failed",backend:options.secureStore.backend,warnings:["credential_migration_failed"],legacyDeleted:!1}}}function toFileFallbackCredentials(value){let{exchange_subject_token:_subjectToken,exchange_subject_token_type:_subjectTokenType,mode_expires_at:_modeExpiresAt,...safeValue}=value;return safeValue.credential_mode==="pat_exchange"&&(safeValue.credential_mode="seeded_token"),safeValue}function requiresFileCredentialProjection(value){return!!(value.exchange_subject_token||value.exchange_subject_token_type||value.mode_expires_at||value.credential_mode==="pat_exchange")}function credentialsEqual(left,right){return JSON.stringify(left)===JSON.stringify(right)}function classifySecureStoreFailure(error){return error instanceof CredentialStoreCorruptedError?"credential_store_corrupted":"credential_secure_store_unavailable"}function classifySecureStoreFailureWithLegacyFallback(error){return error instanceof CredentialStoreCorruptedError?"credential_migration_failed":"credential_secure_store_unavailable"}function deduplicateWarnings(warnings){return[...new Set(warnings)]}var WINDOWS_HARDEN_ACL_SCRIPT=String.raw`
|
|
2300
2298
|
$ErrorActionPreference = 'Stop'
|
|
2301
2299
|
$credentialPath = $env:VOOBASE_CREDENTIAL_PATH
|
|
2302
2300
|
if ([string]::IsNullOrWhiteSpace($credentialPath)) { throw 'credential path missing' }
|
|
@@ -2317,9 +2315,9 @@ foreach ($sidValue in @($currentSid.Value, 'S-1-5-18', 'S-1-5-32-544')) {
|
|
|
2317
2315
|
[void]$acl.AddAccessRule($rule)
|
|
2318
2316
|
}
|
|
2319
2317
|
Set-Acl -LiteralPath $credentialPath -AclObject $acl
|
|
2320
|
-
`;function hardenWindowsCredentialFileAcl(filePath){let result=
|
|
2318
|
+
`;function hardenWindowsCredentialFileAcl(filePath){let result=spawnSync3(resolveWindowsPowerShellExecutable(),["-NoLogo","-NoProfile","-NonInteractive","-Command",WINDOWS_HARDEN_ACL_SCRIPT],{encoding:"utf8",env:{...process.env,VOOBASE_CREDENTIAL_PATH:filePath},shell:!1,timeout:8e3,windowsHide:!0,maxBuffer:2097152});return!result.error&&result.status===0}function defaultFileStoreSecurityWarning(code2){process.stderr.write(`[${code2}] Windows \u51ED\u636E\u6587\u4EF6\u5DF2\u5199\u5165\uFF0C\u4F46\u672A\u80FD\u786E\u8BA4\u5F53\u524D\u7528\u6237\u4E13\u5C5E ACL\uFF1B\u672C\u6B21\u767B\u5F55\u5C06\u7EE7\u7EED\u3002
|
|
2321
2319
|
\u5EFA\u8BAE\uFF1A\u8FD0\u884C \`platform diagnostics credentials\` \u67E5\u770B\u6743\u9650\u72B6\u6001\u3002
|
|
2322
|
-
`)}function createCredentialStore(options){let platform=options.platform??process.platform
|
|
2320
|
+
`)}function createCredentialStore(options){let platform=options.platform??process.platform;return platform==="win32"?new WindowsDpapiCredentialStore({blobPath:join5(options.stateDir,"credentials.dpapi"),service:resolveCredentialStoreService(options.profileName,options.stateDir)}):new FileCredentialStore(join5(options.stateDir,"credentials.json"),{platform})}function resolveCredentialStoreService(profileName,stateDir){let stateIdentity=createHash4("sha256").update(resolve6(stateDir)).digest("hex").slice(0,16);return`cn.voobase.platform-cli.${sanitizeProfileName(profileName)}.${stateIdentity}`}function parseStoredCredentials(serialized,backend){try{let value=JSON.parse(serialized);if(!value||typeof value!="object"||typeof value.access_token!="string"||typeof value.issued_at!="string")throw new Error("invalid credential shape");return value}catch{throw new CredentialStoreCorruptedError(backend)}}function sanitizeProfileName(profileName){return profileName.trim().toLowerCase().replace(/[^a-z0-9._-]+/gu,"-")||"default"}function tryDeleteFile(filePath){try{unlinkSync3(filePath)}catch(error){if(error.code!=="ENOENT")throw new CredentialStoreUnavailableError("file","operation_failed")}}var DEFAULT_CONTROL_API_BASE_URL="http://localhost:7001",DEFAULT_RUNTIME_ENDPOINT_CAPABILITIES="end_user_auth,cms",runtimeEndpointCapabilities=["end_user_auth","workflow","end_user_notification"],publicEndpointCapabilities=["cms","asset_library"];function getControlApiBaseUrl(env=process.env){let configured=env.CONTROL_API_BASE_URL?.trim();if(configured&&configured.length>0)return configured;let profileDefault=getDistributionProfile().defaults?.CONTROL_API_BASE_URL?.trim();return profileDefault&&profileDefault.length>0?profileDefault:DEFAULT_CONTROL_API_BASE_URL}function resolveControlApiEndpoint(args={}){let env=args.env??process.env,controlApiBaseUrl=getControlApiBaseUrl(env),allowlist=readRuntimeEndpointCapabilityAllowlist(env);return(args.requestClass==="runtime"&&isRuntimeEndpointCapabilityEnabled(args.capability,allowlist)?readOptionalBaseUrl(env.RUNTIME_API_BASE_URL)??readOptionalBaseUrl(env.PUBLIC_API_BASE_URL)??controlApiBaseUrl:args.requestClass==="public"&&isRuntimeEndpointCapabilityEnabled(args.capability,allowlist)?readOptionalBaseUrl(env.PUBLIC_API_BASE_URL)??readOptionalBaseUrl(env.RUNTIME_API_BASE_URL)??controlApiBaseUrl:void 0)??controlApiBaseUrl}function listResolvedControlApiEndpoints(env=process.env){let controlApiBaseUrl=getControlApiBaseUrl(env),runtimeBaseUrl=readOptionalBaseUrl(env.RUNTIME_API_BASE_URL)??readOptionalBaseUrl(env.PUBLIC_API_BASE_URL)??controlApiBaseUrl,publicBaseUrl=readOptionalBaseUrl(env.PUBLIC_API_BASE_URL)??readOptionalBaseUrl(env.RUNTIME_API_BASE_URL)??controlApiBaseUrl,allowlist=parseRuntimeEndpointCapabilityAllowlist(readRuntimeEndpointCapabilityAllowlist(env)),runtimeCapabilities=filterAllowedEndpointCapabilities(runtimeEndpointCapabilities,allowlist),publicCapabilities=filterAllowedEndpointCapabilities(publicEndpointCapabilities,allowlist);return[{role:"control",baseUrl:controlApiBaseUrl,enabled:!0,capabilities:[],requestClass:"control"},{role:"runtime",baseUrl:runtimeBaseUrl,enabled:runtimeBaseUrl!=null&&runtimeCapabilities.length>0,capabilities:runtimeCapabilities,requestClass:"runtime",...runtimeBaseUrl==null?{reason:"not_configured"}:runtimeCapabilities.length===0?{reason:"disabled_by_allowlist"}:{}},{role:"public",baseUrl:publicBaseUrl,enabled:publicBaseUrl!=null&&publicCapabilities.length>0,capabilities:publicCapabilities,requestClass:"public",...publicBaseUrl==null?{reason:"not_configured"}:publicCapabilities.length===0?{reason:"disabled_by_allowlist"}:{}}]}function createControlApiSdk(args){return createPlatformSdk({baseUrl:args.baseUrl??resolveControlApiEndpoint({capability:args.capability,requestClass:args.requestClass}),getHeaders:()=>({Authorization:`Bearer ${args.accessToken}`,...args.tenantId?{"X-Tenant-Id":args.tenantId}:{},...Object.fromEntries(Object.entries(args.extraHeaders??{}).filter(([,value])=>value!=null))})})}function readOptionalBaseUrl(value){let trimmed=value?.trim();return trimmed&&trimmed.length>0?trimmed:void 0}function isRuntimeEndpointCapabilityEnabled(capability,rawAllowlist){if(!capability)return!1;let allowlist=parseRuntimeEndpointCapabilityAllowlist(rawAllowlist);return allowlist.has("*")||allowlist.has(capability)}function readRuntimeEndpointCapabilityAllowlist(env){return Object.prototype.hasOwnProperty.call(env,"CONTROL_API_RUNTIME_ENDPOINT_CAPABILITIES")?env.CONTROL_API_RUNTIME_ENDPOINT_CAPABILITIES:DEFAULT_RUNTIME_ENDPOINT_CAPABILITIES}function parseRuntimeEndpointCapabilityAllowlist(value){return new Set((value??"").split(/[,\s]+/u).map(item=>item.trim()).filter(item=>item.length>0))}function filterAllowedEndpointCapabilities(capabilities,allowlist){return allowlist.has("*")?[...capabilities]:capabilities.filter(capability=>allowlist.has(capability))}var TOKEN_REFRESH_SKEW_MS=6e4,PAT_LOGIN_VALIDITY_MS=10080*60*1e3,credentialOriginBackend=Symbol("credentialOriginBackend"),CliSessionExpiredError=class extends Error{detail;constructor(detail){super(detail&&detail.trim().length>0?`CLI \u4F1A\u8BDD\u5DF2\u5931\u6548\uFF08${detail.trim()}\uFF09\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C \`platform login\`\u3002`:"CLI \u4F1A\u8BDD\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u6267\u884C `platform login`\u3002"),this.detail=detail,this.name="CliSessionExpiredError"}};function sleep(ms){return new Promise(resolve20=>{setTimeout(resolve20,ms)})}function normalizeOidcGrantFailure(detail){let normalized=detail?.trim();return normalized&&(/(^|[\s:_-])(invalid_grant)([\s:_-]|$)/iu.test(normalized)||/grant request is invalid/iu.test(normalized))?normalized:null}function mapTokenFailureToAuthError(args){let detail=normalizeOidcGrantFailure(args.errorDescription)??normalizeOidcGrantFailure(args.error);return detail?new CliSessionExpiredError(detail):new Error(args.errorDescription??args.error??args.fallback)}function maybeWrapCredentialRefreshError(error){if(error instanceof CliSessionExpiredError)throw error;if(error instanceof Error){let detail=normalizeOidcGrantFailure(error.message);if(detail)throw new CliSessionExpiredError(detail)}throw error}function applyResource(params,audience){if(audience){if(/^[a-z][a-z0-9+.-]*:/iu.test(audience)){params.set("resource",audience);return}params.set("audience",audience)}}function normalizeAuthorizationPrompt(scopes,prompt){let normalized=(prompt??"").split(/\s+/u).map(item=>item.trim()).filter(Boolean);return scopes.includes("offline_access")&&!normalized.includes("consent")&&normalized.push("consent"),normalized.length>0?normalized.join(" "):void 0}function getLoginSuccessHtml(){return`<!DOCTYPE html>
|
|
2323
2321
|
<html lang="zh-CN">
|
|
2324
2322
|
<head>
|
|
2325
2323
|
<meta charset="utf-8" />
|
|
@@ -2453,7 +2451,7 @@ Set-Acl -LiteralPath $credentialPath -AclObject $acl
|
|
|
2453
2451
|
<p class="close-hint">\u8BF7\u91CD\u65B0\u5728\u7EC8\u7AEF\u6267\u884C platform login</p>
|
|
2454
2452
|
</div>
|
|
2455
2453
|
</body>
|
|
2456
|
-
</html>`}function escapeHtml(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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` \u8FC1\u79FB\u5230\u7CFB\u7EDF\u5B89\u5168\u5B58\u50A8\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){return looksLikeJwt(credentials.access_token)?credentials.access_token:looksLikeJwt(credentials.id_token)?credentials.id_token:credentials.access_token}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 isCredentialExpired(credentials,now=Date.now()){if(typeof credentials.expires_in=="number"&&Number.isFinite(credentials.expires_in)){let issuedAt=Date.parse(credentials.issued_at);if(Number.isFinite(issuedAt))return issuedAt+credentials.expires_in*1e3-TOKEN_REFRESH_SKEW_MS<=now}let jwtExpiry=readJwtExpiryMs(credentials.access_token)??readJwtExpiryMs(credentials.id_token);return typeof jwtExpiry=="number"?jwtExpiry-TOKEN_REFRESH_SKEW_MS<=now:!1}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),applyResource(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 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()),applyResource(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 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)}
|
|
2454
|
+
</html>`}function escapeHtml(s){return s.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}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){return looksLikeJwt(credentials.access_token)?credentials.access_token:looksLikeJwt(credentials.id_token)?credentials.id_token:credentials.access_token}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 isCredentialExpired(credentials,now=Date.now()){if(typeof credentials.expires_in=="number"&&Number.isFinite(credentials.expires_in)){let issuedAt=Date.parse(credentials.issued_at);if(Number.isFinite(issuedAt))return issuedAt+credentials.expires_in*1e3-TOKEN_REFRESH_SKEW_MS<=now}let jwtExpiry=readJwtExpiryMs(credentials.access_token)??readJwtExpiryMs(credentials.id_token);return typeof jwtExpiry=="number"?jwtExpiry-TOKEN_REFRESH_SKEW_MS<=now:!1}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),applyResource(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 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()),applyResource(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 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)}
|
|
2457
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(" ")),applyResource(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),applyResource(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),applyResource(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(" ")),applyResource(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)}
|
|
2458
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)}
|
|
2459
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(`
|
|
@@ -2468,7 +2466,7 @@ ${routeMarker}`)}return next}function buildAuthDebugPageSource(){return["export
|
|
|
2468
2466
|
`)}function buildDbDebugPageSource(){return["export function renderDbDebugPage() {"," return `<!doctype html>",'<html lang="zh-CN">'," <head>",' <meta charset="utf-8" />',' <meta name="viewport" content="width=device-width, initial-scale=1" />'," <title>DB Debug</title>"," <style>",' :root { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color-scheme: light; }'," body { margin: 0; background: #f8fafc; color: #0f172a; }"," main { width: min(1080px, calc(100vw - 32px)); margin: 40px auto; padding: 32px; border-radius: 24px; background: #fff; border: 1px solid #e2e8f0; box-shadow: 0 24px 80px rgba(15,23,42,.08); }"," h1 { margin: 0 0 12px; font-size: 32px; }"," p { margin: 0 0 12px; color: #475569; line-height: 1.7; }"," .status { margin-top: 16px; padding: 12px 14px; border-radius: 14px; border: 1px solid #e2e8f0; background: #f8fafc; color: #334155; }"," .status-neutral { background: #f8fafc; border-color: #e2e8f0; color: #334155; }"," .status-success { background: #ecfdf5; border-color: #86efac; color: #166534; }"," .status-warning { background: #fffbeb; border-color: #fcd34d; color: #92400e; }"," .status-error { background: #fff1f2; border-color: #fecdd3; color: #be123c; }"," .grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 16px; margin-top: 20px; }"," .card { border: 1px solid #e2e8f0; border-radius: 16px; padding: 16px; }"," .label { font-size: 12px; color: #64748b; }"," .value { margin-top: 8px; font-weight: 600; word-break: break-word; }"," .mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }"," .actions { display: flex; gap: 12px; margin-top: 20px; flex-wrap: wrap; }"," button, a { border: 0; border-radius: 12px; padding: 12px 16px; font: inherit; font-weight: 600; cursor: pointer; background: #0f172a; color: #fff; text-decoration: none; display: inline-flex; align-items: center; }"," button.secondary, a.secondary { background: #fff; color: #0f172a; border: 1px solid #cbd5e1; }"," ul { margin: 0; padding-left: 20px; color: #334155; }"," li { margin: 8px 0; }"," pre { margin: 0; white-space: pre-wrap; word-break: break-word; }"," @media (max-width: 720px) { .grid { grid-template-columns: 1fr; } }"," </style>"," </head>"," <body>"," <main>"," <h1>DB \u6700\u5C0F\u8054\u8C03\u9875</h1>"," <p>\u8FD9\u4E2A\u9875\u9762\u53EA\u7528\u4E8E\u672C\u5730\u6216 preview \u8054\u8C03\u5E73\u53F0 DB \u7ED1\u5B9A\uFF0C\u4E0D\u5C5E\u4E8E\u6B63\u5F0F\u4E1A\u52A1\u9875\u9762\u3002\u5B83\u4F1A\u8BFB\u53D6\u5F53\u524D\u5E94\u7528\u7684 DB \u7ED1\u5B9A\u4E0A\u4E0B\u6587\uFF0C\u5E76\u63D0\u793A\u4F60\u7EE7\u7EED\u4F7F\u7528 `platform db` \u548C `platform dev --remote-bindings` \u9A8C\u8BC1\u771F\u5B9E\u8868\u7ED3\u6784\u4E0E\u67E5\u8BE2\u3002</p>",' <div class="status status-neutral" id="status">\u6B63\u5728\u8BFB\u53D6 DB \u7ED1\u5B9A\u4E0A\u4E0B\u6587...</div>',' <div class="grid">',' <div class="card"><div class="label">\u5F53\u524D\u79DF\u6237 / \u5E94\u7528 / \u73AF\u5883</div><div class="value mono" id="identity">-</div></div>',' <div class="card"><div class="label">DATABASE_URL \u6CE8\u5165\u72B6\u6001</div><div class="value mono" id="db-ready">-</div></div>',' <div class="card"><div class="label">DATABASE_SCHEMA</div><div class="value mono" id="db-schema">-</div></div>',' <div class="card"><div class="label">Capability Version</div><div class="value mono" id="db-capability">-</div></div>'," </div>",' <div class="card" style="margin-top:16px"><div class="label">\u540E\u7AEF\u8FD4\u56DE\u7684 DB \u4E0A\u4E0B\u6587</div><div class="value"><pre id="db-context">-</pre></div></div>',' <div class="card" style="margin-top:16px"><div class="label">\u4E0B\u4E00\u6B65\u5EFA\u8BAE</div><div class="value"><ul><li>\u5148\u8DD1 <code>platform db status</code> \u770B binding / schema / migration\u3002</li><li>\u518D\u8DD1 <code>platform db tables</code> \u6216 <code>platform db query --sql "SELECT ..."</code> \u786E\u8BA4\u771F\u5B9E\u8868\u7ED3\u6784\u3002</li><li>\u5982\u679C\u4F60\u8981\u9A8C\u8BC1\u5E94\u7528\u4EE3\u7801\u76F4\u8FDE DB\uFF0C\u4F7F\u7528 <code>platform dev --remote-bindings</code>\uFF0C\u4E0D\u8981\u53EA\u8DD1\u666E\u901A <code>platform dev</code>\u3002</li></ul></div></div>',' <div class="actions">',' <button id="refresh" type="button">\u5237\u65B0\u72B6\u6001</button>',' <a class="secondary" href="/app">\u8FD4\u56DE\u4E1A\u52A1\u9875</a>'," </div>"," </main>",' <script type="module">'," import { getRuntimeStatusFromError, applyRuntimeStatus } from '/assets/platform-runtime.js';"," const statusEl = document.getElementById('status');"," const identityEl = document.getElementById('identity');"," const dbReadyEl = document.getElementById('db-ready');"," const dbSchemaEl = document.getElementById('db-schema');"," const dbCapabilityEl = document.getElementById('db-capability');"," const dbContextEl = document.getElementById('db-context');"," const refreshEl = document.getElementById('refresh');"," async function refreshDbDebug() {"," applyRuntimeStatus(statusEl, { tone: 'neutral', message: '\u6B63\u5728\u8BFB\u53D6 DB \u8C03\u8BD5\u72B6\u6001...' });"," try {"," const [context, dbContext] = await Promise.all(["," fetch('/api/me').then((item) => item.json()).catch(() => null),"," fetch('/api/debug/db-context').then((item) => item.json()).catch(() => null)"," ]);"," identityEl.textContent = [dbContext?.tenant_id || context?.tenant_id || '-', dbContext?.app_id || context?.app_id || '-', dbContext?.env || context?.env || '-'].join(' / ');"," dbReadyEl.textContent = dbContext?.database_ready ? 'ready' : 'not_injected';"," dbSchemaEl.textContent = dbContext?.database_schema || '-';"," dbCapabilityEl.textContent = dbContext?.database_capability_version || '-';"," dbContextEl.textContent = dbContext ? JSON.stringify(dbContext, null, 2) : '-';"," applyRuntimeStatus(statusEl, dbContext?.database_ready"," ? { tone: 'success', message: '\u5DF2\u68C0\u6D4B\u5230 DATABASE_URL\u3002\u4E0B\u4E00\u6B65\u8BF7\u7528 platform db tables/query \u9A8C\u8BC1\u771F\u5B9E\u8868\u7ED3\u6784\u3002' }"," : { tone: 'warning', message: '\u5F53\u524D\u8FD8\u6CA1\u68C0\u6D4B\u5230 DATABASE_URL\u3002\u82E5\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u8BF7\u6539\u7528 platform dev --remote-bindings\u3002' });"," } catch (error) {"," applyRuntimeStatus(statusEl, getRuntimeStatusFromError(error, 'DB \u8C03\u8BD5\u9875\u521D\u59CB\u5316\u5931\u8D25\u3002'));"," }"," }"," refreshEl.addEventListener('click', () => { void refreshDbDebug(); });"," void refreshDbDebug();"," </script>"," </body>","</html>`;","}",""].join(`
|
|
2469
2467
|
`)}function resolveWorkspaceDevTarget(target){if(!target)return null;let workspaceRoot=findWorkspaceRoot();return{command:`corepack pnpm --filter ${target.startsWith("@platform/")?target:`@platform/${target}`} dev`,cwd:workspaceRoot}}function buildDevEnvironment(binding,runtimeBindings={}){return{...process.env,PLATFORM_ACTIVE_TENANT_ID:binding?.tenant_id??"",PLATFORM_ACTIVE_APP_ID:binding?.app_id??"",PLATFORM_ACTIVE_ENV:binding?.env??"",PLATFORM_ACTIVE_APP_NAME:binding?.app_name??"",APP_ID:process.env.APP_ID??binding?.app_id??"",APP_ENV:process.env.APP_ENV??binding?.env??"preview",TENANT_ID:process.env.TENANT_ID??runtimeBindings.TENANT_ID??binding?.tenant_id??"",PUBLIC_APP_BASE_URL:process.env.PUBLIC_APP_BASE_URL??runtimeBindings.PUBLIC_APP_BASE_URL??"",CONTROL_API_BASE_URL:process.env.CONTROL_API_BASE_URL??runtimeBindings.CONTROL_API_BASE_URL??DEFAULT_CONTROL_API_BASE_URL,DATABASE_URL:process.env.DATABASE_URL??runtimeBindings.DATABASE_URL??"",DATABASE_SCHEMA:process.env.DATABASE_SCHEMA??runtimeBindings.DATABASE_SCHEMA??"",DATABASE_MIGRATOR_ROLE:process.env.DATABASE_MIGRATOR_ROLE??runtimeBindings.DATABASE_MIGRATOR_ROLE??"",DATABASE_RUNTIME_ROLE:process.env.DATABASE_RUNTIME_ROLE??runtimeBindings.DATABASE_RUNTIME_ROLE??"",DATABASE_CAPABILITY_VERSION:process.env.DATABASE_CAPABILITY_VERSION??runtimeBindings.DATABASE_CAPABILITY_VERSION??""}}function detectLocalDependencyInstallPlan(appDir){let packageJsonPath=join7(appDir,"package.json"),nodeModulesPath=join7(appDir,"node_modules");if(!existsSync11(packageJsonPath))return null;let packageJson=JSON.parse(readFileSync10(packageJsonPath,"utf8")),declaredPackageManager=typeof packageJson.packageManager=="string"?packageJson.packageManager.trim():"",declaredPackageManagerName=declaredPackageManager.includes("@")?declaredPackageManager.slice(0,declaredPackageManager.lastIndexOf("@")):declaredPackageManager,lockfiles=["package-lock.json","pnpm-lock.yaml","yarn.lock"].filter(fileName=>existsSync11(join7(appDir,fileName)));if(lockfiles.length>1)throw new Error(`[conflicting_lockfiles] \u68C0\u6D4B\u5230\u591A\u4E2A\u5305\u7BA1\u7406\u5668 lockfile\uFF1A${lockfiles.join(", ")}\u3002\u8BF7\u53EA\u4FDD\u7559\u9879\u76EE\u58F0\u660E\u7684\u5305\u7BA1\u7406\u5668 lockfile \u540E\u91CD\u8BD5\u3002`);let lockfilePackageManagers={"package-lock.json":"npm","pnpm-lock.yaml":"pnpm","yarn.lock":"yarn"},lockfile=lockfiles[0];if(declaredPackageManagerName&&lockfile&&lockfilePackageManagers[lockfile]!==declaredPackageManagerName)throw new Error(`[package_manager_lock_mismatch] packageManager ${declaredPackageManager} \u4E0E ${lockfile} \u4E0D\u5339\u914D\u3002\u8BF7\u4FDD\u7559\u4E0E packageManager \u4E00\u81F4\u7684 lockfile \u540E\u91CD\u8BD5\u3002`);return existsSync11(nodeModulesPath)?null:lockfile==="package-lock.json"?declaredPackageManagerName==="npm"&&declaredPackageManager?{command:"npx",args:["--yes",declaredPackageManager,"ci","--no-audit","--no-fund"],lockfile:"package-lock.json"}:{command:"npm",args:["ci","--no-audit","--no-fund"],lockfile:"package-lock.json"}:lockfile==="pnpm-lock.yaml"?{command:"corepack",args:["pnpm","install","--frozen-lockfile"],lockfile:"pnpm-lock.yaml"}:lockfile==="yarn.lock"?{command:"yarn",args:["install","--frozen-lockfile"],lockfile:"yarn.lock"}:null}function detectRequestedRemoteBindings(startDir=process.cwd()){let capabilities=new Set;try{let appRoot=findAppRoot(startDir);workspaceHasEffectiveDbMigration(appRoot)&&capabilities.add("db")}catch{return[]}return[...capabilities]}function templatePrefersPlatformCapabilityBindings(templateKey){return templateKey==="frontend-app-vite"||templateKey==="backend-app-node"}function recommendDevCommandForTemplate(templateKey,options={}){return(options.requestedRemoteBindings??[]).includes("db")?"platform dev --remote-bindings=db":templatePrefersPlatformCapabilityBindings(templateKey)?"platform dev --remote-bindings":null}function workspaceHasEffectiveDbMigration(appRoot){let migrationsDir=join7(appRoot,"resources","db","migrations");if(!existsSync11(migrationsDir)||!statSync2(migrationsDir).isDirectory())return!1;for(let entry of readdirSync3(migrationsDir,{withFileTypes:!0})){if(!entry.isFile())continue;if(readFileSync10(join7(migrationsDir,entry.name),"utf8").split(`
|
|
2470
2468
|
`).map(line=>line.replace(/--.*$/,"").trim()).filter(Boolean).join(`
|
|
2471
|
-
`).trim().length>0)return!0}return!1}async function resolveAvailableLocalDevPort(preferredPort,options={}){let host=options.host;return await canBindPort(preferredPort,host)?{port:preferredPort,reusedPreferred:!0}:{port:await allocateEphemeralPort(host),reusedPreferred:!1}}async function canBindPort(port,host){return new Promise(resolve20=>{let server=createNetServer(),finish=available=>{server.removeAllListeners(),resolve20(available)};server.once("error",()=>{finish(!1)});let onListening=()=>{server.close(()=>finish(!0))};if(host){server.listen(port,host,onListening);return}server.listen(port,onListening)})}async function allocateEphemeralPort(host){return new Promise((resolve20,reject)=>{let server=createNetServer();server.once("error",error=>{reject(error instanceof Error?error:new Error(String(error)))});let onListening=()=>{let address=server.address();if(!address||typeof address=="string"){server.close(()=>reject(new Error("\u65E0\u6CD5\u4E3A\u672C\u5730 dev \u5206\u914D\u56DE\u9000\u7AEF\u53E3\u3002")));return}let{port}=address;server.close(error=>{if(error){reject(error);return}resolve20(port)})};if(host){server.listen(0,host,onListening);return}server.listen(0,onListening)})}function collectDevPreflight(startDir=process.cwd(),target,runtimeBindings={}){let{manifest,directory}=readAppManifest(startDir),linked=readBinding(startDir);if(!linked?.binding.tenant_id||!linked.binding.app_id){let sourceContextPath=join7(directory,SOURCE_CONTEXT_FILE);throw new Error(existsSync11(sourceContextPath)?"\u5F53\u524D\u9879\u76EE\u672A\u7ED1\u5B9A tenant/app/env\u3002\u4F18\u5148\u5EFA\u8BAE\u6267\u884C `platform app create ...` \u6216 `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u53D6\u4E00\u4E2A\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u82E5\u4F60\u8981\u4FEE\u590D\u5F53\u524D\u76EE\u5F55\uFF0C\u518D\u624B\u52A8\u6267\u884C `platform link --tenant <tenant-id> --app <app-id> --env preview`\u3002":"\u5F53\u524D\u76EE\u5F55\u5DF2\u68C0\u6D4B\u5230 `app.yaml`\uFF0C\u4F46\u7F3A\u5C11 `.platform/source-context.json`\uFF0C\u770B\u8D77\u6765\u50CF\u4E00\u4E2A\u5DF2\u8FC1\u79FB\u6216\u672A\u91CD\u65B0\u7ED1\u5B9A\u7684\u5E94\u7528\u5DE5\u7A0B\u3002\u8BF7\u6267\u884C `platform link --tenant <tenant-id> --app <app-id> --env preview` \u91CD\u65B0\u7ED1\u5B9A\u5F53\u524D\u76EE\u5F55\u3002")}let sourceContext=readSourceContext(startDir)?.sourceContext,workspaceTarget=resolveWorkspaceDevTarget(target),command=workspaceTarget?.command??manifest.entry.command,cwd=workspaceTarget?.cwd??directory,env=buildDevEnvironment(linked.binding,runtimeBindings),port=Number(env.PORT||manifest.entry.port||3e3);env.PUBLIC_APP_BASE_URL||(env.PUBLIC_APP_BASE_URL=`http://127.0.0.1:${port}`);let healthPath=manifest.entry.health_check||"/healthz",resolvedTemplateKey=typeof sourceContext?.template_key=="string"&&sourceContext.template_key.trim().length>0?sourceContext.template_key.trim():manifest.template_key,devCommandAnalysis=analyzeDevCommand(command,cwd),previewAddressMayChange=!manifest.dev.auto_restart&&devCommandAnalysis.portMayChange,warnings=["\u5F53\u524D\u9ED8\u8BA4\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1A\u672C\u5730\u5F00\u53D1\u4E0D\u8981\u6C42 registry\u3001kind\u3001ingress-nginx \u6216 build-runner\u3002",`\u5F53\u524D\u542F\u52A8\u547D\u4EE4\u6765\u81EA app.yaml \u7684 entry.command\uFF1A${command}`];return manifest.dev.auto_restart?warnings.push("\u5F53\u524D app.yaml \u5DF2\u914D\u7F6E `dev.auto_restart: true`\uFF1BCLI \u4F1A\u5728\u68C0\u6D4B\u5230\u6E90\u7801\u53D8\u66F4\u540E\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B\u3002"):devCommandAnalysis.managedByCommand?warnings.push(devCommandAnalysis.message):warnings.push("\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"),env.DATABASE_URL||warnings.push("\u672A\u68C0\u6D4B\u5230 DATABASE_URL\uFF1B\u672C\u5730\u6A21\u677F\u63A5\u53E3\u548C\u9875\u9762\u5F00\u53D1\u4ECD\u53EF\u7EE7\u7EED\u3002\u82E5\u4F60\u9700\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u518D\u6267\u884C `platform dev --remote-bindings` \u6216\u624B\u52A8\u8BBE\u7F6E\u672C\u5730\u73AF\u5883\u53D8\u91CF\u3002"),templatePrefersPlatformCapabilityBindings(resolvedTemplateKey)&&warnings.push("\u5F53\u524D\u5B98\u65B9\u6A21\u677F\u9ED8\u8BA4\u5E26 Auth / CMS / Data Form \u793A\u4F8B\u9875\u3002\u82E5\u4F60\u8981\u8054\u8C03\u8FD9\u4E9B\u771F\u5B9E\u5E73\u53F0\u80FD\u529B\uFF0C\u5EFA\u8BAE\u76F4\u63A5\u6267\u884C `platform dev --remote-bindings`\u3002"),!process.env.PUBLIC_APP_BASE_URL&&!runtimeBindings.PUBLIC_APP_BASE_URL&&warnings.push(`\u672A\u663E\u5F0F\u914D\u7F6E PUBLIC_APP_BASE_URL\uFF1B\u672C\u5730 dev \u5DF2\u4E34\u65F6\u56DE\u9000\u4E3A ${env.PUBLIC_APP_BASE_URL}\u3002`),resolvedTemplateKey&&resolvedTemplateKey!=="frontend-app-vite"&&resolvedTemplateKey!=="backend-app-node"&&warnings.push(`\u5F53\u524D\u6A21\u677F\u4E3A ${resolvedTemplateKey}\uFF0C\u8BF7\u786E\u8BA4\u5165\u53E3\u547D\u4EE4\u4E0E\u5065\u5EB7\u68C0\u67E5\u8DEF\u5F84\u5DF2\u7ECF\u548C app.yaml \u5BF9\u9F50\u3002`),{binding:linked.binding,manifest,templateKey:resolvedTemplateKey,directory,command,cwd,env,healthcheckUrl:`http://localhost:${port}${healthPath}`,previewAddressMayChange,warnings}}function analyzeDevCommand(command,cwd){if(/(--watch|\bwatch\b|nodemon|vite|next dev|webpack serve|tsx watch)/iu.test(command))return{managedByCommand:!0,portMayChange:/\bvite\b/iu.test(command),message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u5DF2\u5305\u542B watch / \u70ED\u66F4\u65B0\u80FD\u529B\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002"};let npmScriptMatch=command.trim().match(/^(?:npm|pnpm|yarn)\s+run\s+([a-zA-Z0-9:_-]+)|^corepack\s+pnpm\s+run\s+([a-zA-Z0-9:_-]+)/u),scriptName=npmScriptMatch?.[1]??npmScriptMatch?.[2];if(!scriptName)return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"};let packageJsonPath=join7(cwd,"package.json");if(!existsSync11(packageJsonPath))return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"};try{let scriptCommand=JSON.parse(readFileSync10(packageJsonPath,"utf8")).scripts?.[scriptName];if(typeof scriptCommand=="string"&&/(--watch|\bwatch\b|nodemon|vite|next dev|webpack serve|tsx watch|scripts\/dev\.mjs|scripts\\dev\.mjs)/iu.test(scriptCommand))return{managedByCommand:!0,portMayChange:/\bvite\b|scripts\/dev\.mjs|scripts\\dev\.mjs/iu.test(scriptCommand),message:scriptCommand.includes("scripts/dev.mjs")?"\u5F53\u524D\u547D\u4EE4\u901A\u8FC7\u6A21\u677F\u81EA\u5E26\u7684\u672C\u5730 dev \u7F16\u6392\u811A\u672C\u542F\u52A8\uFF1B\u524D\u7AEF\u70ED\u66F4\u65B0\u4E0E\u670D\u52A1\u7AEF\u81EA\u52A8\u91CD\u542F\u7531\u6A21\u677F\u81EA\u5DF1\u7BA1\u7406\uFF0CCLI \u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002":"\u5F53\u524D\u547D\u4EE4\u901A\u8FC7 package.json script \u81EA\u5E26 watch / \u70ED\u66F4\u65B0\u80FD\u529B\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002"}}catch{return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"}}return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"}}async function runAppLibraryCommand(args,deps={}){let subcommand=args.rest[0];if(hasHelpFlag2(args)||args.rest.length===0||subcommand==="help"){printAppLibraryHelp();return}let sdk=deps.sdk,tenantId=deps.tenantId;if(!sdk||!tenantId){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");if(tenantId=deps.tenantId??resolveTenantId(args),!tenantId)throw new Error("`platform app-library` \u9700\u8981 tenant \u4E0A\u4E0B\u6587\u3002\u8BF7\u5148\u5728\u5F53\u524D\u9879\u76EE\u7ED1\u5B9A tenant/app\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant`\u3002");sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"dashboard",requestClass:"control"})}switch(subcommand){case"list":await runList(args,sdk);return;case"search":await runSearch(args,sdk);return;case"inspect":await runInspect(args,sdk);return;case"source":await runSource(args,sdk);return;case"config":await runConfig(args);return;case"open":await runOpen(args,deps);return;case"checkout":await runCheckout(args,sdk);return;case"create":await runCreate(args,sdk);return;case"update":await runUpdate(args,sdk);return;case"submit":await runSubmit(args,sdk,deps);return;case"publish":await runStateAction(args,sdk,"publish");return;case"unpublish":await runStateAction(args,sdk,"unpublish");return;case"archive":await runStateAction(args,sdk,"archive");return;case"delete":await runDelete(args,sdk);return;default:throw new Error("`platform app-library` \u4EC5\u652F\u6301 `list`\u3001`search`\u3001`inspect`\u3001`source`\u3001`config`\u3001`open`\u3001`checkout`\u3001`create`\u3001`update`\u3001`submit`\u3001`publish`\u3001`unpublish`\u3001`archive`\u3001`delete`\u3002")}}function printAppLibraryHelp(){process.stdout.write(["platform app-library <command>","","Commands:"," platform app-library list [--query <keyword>] [--status draft|published|unpublished|archived] [--tag <tag>] [--template-key <key>] [--visibility private|public] [--full] [--json]"," platform app-library search <keyword> [--status draft|published|unpublished|archived] [--full] [--json]"," platform app-library inspect <entry-id> [--json]"," platform app-library source tree <entry-id> [--json]"," platform app-library source read <entry-id> <path> [--json]"," platform app-library source search <entry-id> <query> [--json]"," platform app-library config init [--file app-library.yaml] [--force]"," platform app-library config validate [--file app-library.yaml] [--json]"," platform app-library open <entry-id> [--no-browser]"," platform app-library checkout <entry-id> [--dir <target-dir>] [--write-config] [--no-config] [--json]"," platform app-library create [--file app-library.yaml] [--name <name>] [--summary <text>] [--tags a,b] [--template-key <key>] [--write-config] [--json]"," platform app-library update <entry-id> [--file app-library.yaml] [--name <name>] [--summary <text>] [--tags a,b] [--template-key <key>] [--write-config] [--json]"," platform app-library submit <entry-id> [--file app-library.yaml] [--json]"," platform app-library publish <entry-id> [--json]"," platform app-library unpublish <entry-id> [--json]"," platform app-library archive <entry-id> [--json]"," platform app-library delete <entry-id> [--json]","","Notes:"," - \u521D\u671F\u4EC5\u652F\u6301 `example-app` \u6761\u76EE"," - `list` / `search` \u9ED8\u8BA4\u8FD4\u56DE\u8F7B\u6458\u8981\uFF1B\u5982\u9700\u5B8C\u6574\u5B57\u6BB5\u8BF7\u663E\u5F0F\u4F20 `--full`\uFF0C\u6216\u8FDB\u4E00\u6B65\u6267\u884C `inspect`"," - `list` / `search` \u9ED8\u8BA4\u4F1A\u67E5\u8BE2\u672C\u79DF\u6237 + \u8DE8\u79DF\u6237\u5DF2\u53D1\u5E03\u6761\u76EE\uFF1B\u5982\u663E\u5F0F\u4F20 `--status draft|unpublished|archived`\uFF0C\u5219\u4EC5\u67E5\u8BE2\u672C\u79DF\u6237\u6761\u76EE"," - `submit` \u9700\u8981\u5728\u672C\u5730\u8F7B\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u4F1A\u8BFB\u53D6\u5F53\u524D\u6E90\u7801\u5DE5\u4F5C\u533A\u5E76\u4E0A\u4F20\u4E3A\u5F53\u524D\u5FEB\u7167"," - \u5143\u6570\u636E\u9ED8\u8BA4\u8BFB\u53D6\u5F53\u524D\u5E94\u7528\u6839\u76EE\u5F55\u4E0B\u7684 `app-library.yaml`\uFF0CCLI flags \u53EF\u8986\u76D6\u540C\u540D\u5B57\u6BB5"," - `create` / `update` \u5728\u68C0\u6D4B\u5230\u73B0\u6709\u914D\u7F6E\u6587\u4EF6\u6216\u663E\u5F0F\u4F20\u5165 `--write-config` \u65F6\uFF0C\u4F1A\u628A\u6700\u65B0\u5143\u6570\u636E\u56DE\u5199\u5230 `app-library.yaml`"," - `checkout` \u9ED8\u8BA4\u5728\u76EE\u6807\u6E90\u7801\u4E0D\u5305\u542B `app-library.yaml` \u65F6\u81EA\u52A8\u751F\u6210\u4E00\u4EFD\uFF1B\u53EF\u7528 `--write-config` \u5F3A\u5236\u8986\u76D6\uFF0C`--no-config` \u8DF3\u8FC7"," - `open` \u9ED8\u8BA4\u6253\u5F00\u672C\u5730 tenant-workbench \u7684 `#app-library/<entry-id>` \u8DEF\u7531"," - `source tree/read/search` \u7528\u4E8E\u4E0D checkout \u7684\u4E91\u7AEF\u6E90\u7801\u7406\u89E3",""].join(`
|
|
2469
|
+
`).trim().length>0)return!0}return!1}async function resolveAvailableLocalDevPort(preferredPort,options={}){let host=options.host;return await canBindPort(preferredPort,host)?{port:preferredPort,reusedPreferred:!0}:{port:await allocateEphemeralPort(host),reusedPreferred:!1}}async function canBindPort(port,host){return new Promise(resolve20=>{let server=createNetServer(),finish=available=>{server.removeAllListeners(),resolve20(available)};server.once("error",()=>{finish(!1)});let onListening=()=>{server.close(()=>finish(!0))};if(host){server.listen(port,host,onListening);return}server.listen(port,onListening)})}async function allocateEphemeralPort(host){return new Promise((resolve20,reject)=>{let server=createNetServer();server.once("error",error=>{reject(error instanceof Error?error:new Error(String(error)))});let onListening=()=>{let address=server.address();if(!address||typeof address=="string"){server.close(()=>reject(new Error("\u65E0\u6CD5\u4E3A\u672C\u5730 dev \u5206\u914D\u56DE\u9000\u7AEF\u53E3\u3002")));return}let{port}=address;server.close(error=>{if(error){reject(error);return}resolve20(port)})};if(host){server.listen(0,host,onListening);return}server.listen(0,onListening)})}function collectDevPreflight(startDir=process.cwd(),target,runtimeBindings={}){let{manifest,directory}=readAppManifest(startDir),linked=readBinding(startDir);if(!linked?.binding.tenant_id||!linked.binding.app_id){let sourceContextPath=join7(directory,SOURCE_CONTEXT_FILE);throw new Error(existsSync11(sourceContextPath)?"\u5F53\u524D\u9879\u76EE\u672A\u7ED1\u5B9A tenant/app/env\u3002\u4F18\u5148\u5EFA\u8BAE\u6267\u884C `platform app create ...` \u6216 `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u53D6\u4E00\u4E2A\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u82E5\u4F60\u8981\u4FEE\u590D\u5F53\u524D\u76EE\u5F55\uFF0C\u518D\u624B\u52A8\u6267\u884C `platform link --tenant <tenant-id> --app <app-id> --env preview`\u3002":"\u5F53\u524D\u76EE\u5F55\u5DF2\u68C0\u6D4B\u5230 `app.yaml`\uFF0C\u4F46\u7F3A\u5C11 `.platform/source-context.json`\uFF0C\u770B\u8D77\u6765\u50CF\u4E00\u4E2A\u5DF2\u8FC1\u79FB\u6216\u672A\u91CD\u65B0\u7ED1\u5B9A\u7684\u5E94\u7528\u5DE5\u7A0B\u3002\u8BF7\u6267\u884C `platform link --tenant <tenant-id> --app <app-id> --env preview` \u91CD\u65B0\u7ED1\u5B9A\u5F53\u524D\u76EE\u5F55\u3002")}let sourceContext=readSourceContext(startDir)?.sourceContext,workspaceTarget=resolveWorkspaceDevTarget(target),command=workspaceTarget?.command??manifest.entry.command,cwd=workspaceTarget?.cwd??directory,env=buildDevEnvironment(linked.binding,runtimeBindings),port=Number(env.PORT||manifest.entry.port||3e3);env.PUBLIC_APP_BASE_URL||(env.PUBLIC_APP_BASE_URL=`http://127.0.0.1:${port}`);let healthPath=manifest.entry.health_check||"/healthz",resolvedTemplateKey=typeof sourceContext?.template_key=="string"&&sourceContext.template_key.trim().length>0?sourceContext.template_key.trim():manifest.template_key,devCommandAnalysis=analyzeDevCommand(command,cwd),previewAddressMayChange=!manifest.dev.auto_restart&&devCommandAnalysis.portMayChange,warnings=["\u5F53\u524D\u9ED8\u8BA4\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1A\u672C\u5730\u5F00\u53D1\u4E0D\u8981\u6C42 registry\u3001kind\u3001ingress-nginx \u6216 build-runner\u3002",`\u5F53\u524D\u542F\u52A8\u547D\u4EE4\u6765\u81EA app.yaml \u7684 entry.command\uFF1A${command}`];return manifest.dev.auto_restart?warnings.push("\u5F53\u524D app.yaml \u5DF2\u914D\u7F6E `dev.auto_restart: true`\uFF1BCLI \u4F1A\u5728\u68C0\u6D4B\u5230\u6E90\u7801\u53D8\u66F4\u540E\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B\u3002"):devCommandAnalysis.managedByCommand?warnings.push(devCommandAnalysis.message):warnings.push("\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"),env.DATABASE_URL||warnings.push("\u672A\u68C0\u6D4B\u5230 DATABASE_URL\uFF1B\u672C\u5730\u6A21\u677F\u63A5\u53E3\u548C\u9875\u9762\u5F00\u53D1\u4ECD\u53EF\u7EE7\u7EED\u3002\u82E5\u4F60\u9700\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u518D\u6267\u884C `platform dev --remote-bindings` \u6216\u624B\u52A8\u8BBE\u7F6E\u672C\u5730\u73AF\u5883\u53D8\u91CF\u3002"),templatePrefersPlatformCapabilityBindings(resolvedTemplateKey)&&warnings.push("\u5F53\u524D\u5B98\u65B9\u6A21\u677F\u9ED8\u8BA4\u5E26 Auth / CMS / Data Form \u793A\u4F8B\u9875\u3002\u82E5\u4F60\u8981\u8054\u8C03\u8FD9\u4E9B\u771F\u5B9E\u5E73\u53F0\u80FD\u529B\uFF0C\u5EFA\u8BAE\u76F4\u63A5\u6267\u884C `platform dev --remote-bindings`\u3002"),!process.env.PUBLIC_APP_BASE_URL&&!runtimeBindings.PUBLIC_APP_BASE_URL&&warnings.push(`\u672A\u663E\u5F0F\u914D\u7F6E PUBLIC_APP_BASE_URL\uFF1B\u672C\u5730 dev \u5DF2\u4E34\u65F6\u56DE\u9000\u4E3A ${env.PUBLIC_APP_BASE_URL}\u3002`),resolvedTemplateKey&&resolvedTemplateKey!=="frontend-app-vite"&&resolvedTemplateKey!=="backend-app-node"&&warnings.push(`\u5F53\u524D\u6A21\u677F\u4E3A ${resolvedTemplateKey}\uFF0C\u8BF7\u786E\u8BA4\u5165\u53E3\u547D\u4EE4\u4E0E\u5065\u5EB7\u68C0\u67E5\u8DEF\u5F84\u5DF2\u7ECF\u548C app.yaml \u5BF9\u9F50\u3002`),{binding:linked.binding,manifest,templateKey:resolvedTemplateKey,directory,command,cwd,env,healthcheckUrl:`http://localhost:${port}${healthPath}`,previewAddressMayChange,warnings}}function analyzeDevCommand(command,cwd){if(/(--watch|\bwatch\b|nodemon|vite|next dev|webpack serve|tsx watch)/iu.test(command))return{managedByCommand:!0,portMayChange:/\bvite\b/iu.test(command),message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u5DF2\u5305\u542B watch / \u70ED\u66F4\u65B0\u80FD\u529B\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002"};let npmScriptMatch=command.trim().match(/^(?:npm|pnpm|yarn)\s+run\s+([a-zA-Z0-9:_-]+)|^corepack\s+pnpm\s+run\s+([a-zA-Z0-9:_-]+)/u),scriptName=npmScriptMatch?.[1]??npmScriptMatch?.[2];if(!scriptName)return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"};let packageJsonPath=join7(cwd,"package.json");if(!existsSync11(packageJsonPath))return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"};try{let scriptCommand=JSON.parse(readFileSync10(packageJsonPath,"utf8")).scripts?.[scriptName];if(typeof scriptCommand=="string"&&/(--watch|\bwatch\b|nodemon|vite|next dev|webpack serve|tsx watch|scripts\/dev\.mjs|scripts\\dev\.mjs)/iu.test(scriptCommand))return{managedByCommand:!0,portMayChange:/\bvite\b|scripts\/dev\.mjs|scripts\\dev\.mjs/iu.test(scriptCommand),message:scriptCommand.includes("scripts/dev.mjs")?"\u5F53\u524D\u547D\u4EE4\u901A\u8FC7\u6A21\u677F\u81EA\u5E26\u7684\u672C\u5730 dev \u7F16\u6392\u811A\u672C\u542F\u52A8\uFF1B\u524D\u7AEF\u70ED\u66F4\u65B0\u4E0E\u670D\u52A1\u7AEF\u81EA\u52A8\u91CD\u542F\u7531\u6A21\u677F\u81EA\u5DF1\u7BA1\u7406\uFF0CCLI \u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002":"\u5F53\u524D\u547D\u4EE4\u901A\u8FC7 package.json script \u81EA\u5E26 watch / \u70ED\u66F4\u65B0\u80FD\u529B\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u989D\u5916\u63A5\u7BA1\u81EA\u52A8\u91CD\u542F\u3002"}}catch{return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"}}return{managedByCommand:!1,portMayChange:!1,message:"\u5F53\u524D\u547D\u4EE4\u81EA\u8EAB\u4E0D\u5E26\u70ED\u66F4\u65B0\uFF1BCLI \u9ED8\u8BA4\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F\u3002\u82E5\u4F60\u9700\u8981\u81EA\u52A8\u91CD\u542F\uFF0C\u8BF7\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\u3002"}}async function runAppLibraryCommand(args,deps={}){let subcommand=args.rest[0];if(hasHelpFlag2(args)||args.rest.length===0||subcommand==="help"){printAppLibraryHelp();return}if(subcommand==="config"){await runConfig(args);return}let sdk=deps.sdk,tenantId=deps.tenantId;if(!sdk||!tenantId){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");if(tenantId=deps.tenantId??resolveTenantId(args),!tenantId)throw new Error("`platform app-library` \u9700\u8981 tenant \u4E0A\u4E0B\u6587\u3002\u8BF7\u5148\u5728\u5F53\u524D\u9879\u76EE\u7ED1\u5B9A tenant/app\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant`\u3002");sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"dashboard",requestClass:"control"})}switch(subcommand){case"list":await runList(args,sdk);return;case"search":await runSearch(args,sdk);return;case"inspect":await runInspect(args,sdk);return;case"source":await runSource(args,sdk);return;case"open":await runOpen(args,deps);return;case"checkout":await runCheckout(args,sdk);return;case"create":await runCreate(args,sdk);return;case"update":await runUpdate(args,sdk);return;case"submit":await runSubmit(args,sdk,deps);return;case"publish":await runStateAction(args,sdk,"publish");return;case"unpublish":await runStateAction(args,sdk,"unpublish");return;case"archive":await runStateAction(args,sdk,"archive");return;case"delete":await runDelete(args,sdk);return;default:throw new Error("`platform app-library` \u4EC5\u652F\u6301 `list`\u3001`search`\u3001`inspect`\u3001`source`\u3001`config`\u3001`open`\u3001`checkout`\u3001`create`\u3001`update`\u3001`submit`\u3001`publish`\u3001`unpublish`\u3001`archive`\u3001`delete`\u3002")}}function printAppLibraryHelp(){process.stdout.write(["platform app-library <command>","","Commands:"," platform app-library list [--query <keyword>] [--status draft|published|unpublished|archived] [--tag <tag>] [--template-key <key>] [--visibility private|public] [--full] [--json]"," platform app-library search <keyword> [--status draft|published|unpublished|archived] [--full] [--json]"," platform app-library inspect <entry-id> [--json]"," platform app-library source tree <entry-id> [--json]"," platform app-library source read <entry-id> <path> [--json]"," platform app-library source search <entry-id> <query> [--json]"," platform app-library config init [--file app-library.yaml] [--force]"," platform app-library config validate [--file app-library.yaml] [--json]"," platform app-library open <entry-id> [--no-browser]"," platform app-library checkout <entry-id> [--dir <target-dir>] [--write-config] [--no-config] [--json]"," platform app-library create [--file app-library.yaml] [--name <name>] [--summary <text>] [--tags a,b] [--template-key <key>] [--write-config] [--json]"," platform app-library update <entry-id> [--file app-library.yaml] [--name <name>] [--summary <text>] [--tags a,b] [--template-key <key>] [--write-config] [--json]"," platform app-library submit <entry-id> [--file app-library.yaml] [--json]"," platform app-library publish <entry-id> [--json]"," platform app-library unpublish <entry-id> [--json]"," platform app-library archive <entry-id> [--json]"," platform app-library delete <entry-id> [--json]","","Notes:"," - \u521D\u671F\u4EC5\u652F\u6301 `example-app` \u6761\u76EE"," - `list` / `search` \u9ED8\u8BA4\u8FD4\u56DE\u8F7B\u6458\u8981\uFF1B\u5982\u9700\u5B8C\u6574\u5B57\u6BB5\u8BF7\u663E\u5F0F\u4F20 `--full`\uFF0C\u6216\u8FDB\u4E00\u6B65\u6267\u884C `inspect`"," - `list` / `search` \u9ED8\u8BA4\u4F1A\u67E5\u8BE2\u672C\u79DF\u6237 + \u8DE8\u79DF\u6237\u5DF2\u53D1\u5E03\u6761\u76EE\uFF1B\u5982\u663E\u5F0F\u4F20 `--status draft|unpublished|archived`\uFF0C\u5219\u4EC5\u67E5\u8BE2\u672C\u79DF\u6237\u6761\u76EE"," - `submit` \u9700\u8981\u5728\u672C\u5730\u8F7B\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u4F1A\u8BFB\u53D6\u5F53\u524D\u6E90\u7801\u5DE5\u4F5C\u533A\u5E76\u4E0A\u4F20\u4E3A\u5F53\u524D\u5FEB\u7167"," - \u5143\u6570\u636E\u9ED8\u8BA4\u8BFB\u53D6\u5F53\u524D\u5E94\u7528\u6839\u76EE\u5F55\u4E0B\u7684 `app-library.yaml`\uFF0CCLI flags \u53EF\u8986\u76D6\u540C\u540D\u5B57\u6BB5"," - `create` / `update` \u5728\u68C0\u6D4B\u5230\u73B0\u6709\u914D\u7F6E\u6587\u4EF6\u6216\u663E\u5F0F\u4F20\u5165 `--write-config` \u65F6\uFF0C\u4F1A\u628A\u6700\u65B0\u5143\u6570\u636E\u56DE\u5199\u5230 `app-library.yaml`"," - `checkout` \u9ED8\u8BA4\u5728\u76EE\u6807\u6E90\u7801\u4E0D\u5305\u542B `app-library.yaml` \u65F6\u81EA\u52A8\u751F\u6210\u4E00\u4EFD\uFF1B\u53EF\u7528 `--write-config` \u5F3A\u5236\u8986\u76D6\uFF0C`--no-config` \u8DF3\u8FC7"," - `open` \u9ED8\u8BA4\u6253\u5F00\u672C\u5730 tenant-workbench \u7684 `#app-library/<entry-id>` \u8DEF\u7531"," - `source tree/read/search` \u7528\u4E8E\u4E0D checkout \u7684\u4E91\u7AEF\u6E90\u7801\u7406\u89E3",""].join(`
|
|
2472
2470
|
`))}async function runList(args,sdk){let status=readStatusOption(args,"status")??"published",includePublic=status==="published",response=await sdk.listLightAppLibraryEntries({query:readStringOption2(args,"query"),status,template_key:readStringOption2(args,"template-key"),tag:readStringOption2(args,"tag"),visibility:readVisibilityOption(args,"visibility"),include_public:includePublic}).catch(error=>{throw formatAppLibraryError(error,"list")}),full=args.options.full===!0;writeJsonOrText(args.options.json===!0,full?response:toEntryListBriefPayload(response),[`items: ${response.items.length}`,...response.items.flatMap((item,index)=>formatEntrySummary(item,index+1,full))])}async function runSearch(args,sdk){let query=args.rest[1]?.trim();if(!query)throw new Error("`platform app-library search` \u9700\u8981 <keyword>\u3002");let status=readStatusOption(args,"status")??"published",includePublic=status==="published",response=await sdk.listLightAppLibraryEntries({query,status,include_public:includePublic}).catch(error=>{throw formatAppLibraryError(error,"search")}),full=args.options.full===!0;writeJsonOrText(args.options.json===!0,full?response:toEntryListBriefPayload(response),[`query: ${query}`,`items: ${response.items.length}`,...response.items.flatMap((item,index)=>formatEntrySummary(item,index+1,full))])}async function runInspect(args,sdk){let config2=loadAppLibraryConfigOptional(),entryId=resolveEntryId(args,config2);if(!entryId)throw new Error("`platform app-library inspect` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let[entry,source]=await Promise.all([sdk.getLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"inspect")}),sdk.getLightAppLibraryEntrySource(entryId).catch(error=>{throw formatAppLibraryError(error,"inspect(source)")})]);writeJsonOrText(args.options.json===!0,{entry,source},[`entry_id: ${entry.entry_id}`,`name: ${entry.name}`,`type: ${entry.type==="example_app"?"example-app":entry.type}`,`status: ${entry.status}`,`library: ${entry.library.name} (${entry.library.visibility})`,`summary: ${entry.summary?.trim()||"-"}`,`tags: ${entry.tags.length?entry.tags.join(", "):"-"}`,`template_key: ${entry.template_key??"-"}`,`capabilities: ${entry.capability_dependencies.length?entry.capability_dependencies.map(item=>item.minVersion?`${item.capability}@${item.minVersion}`:item.capability).join(", "):"-"}`,`current_snapshot_id: ${entry.current_snapshot_id??"-"}`,`source_files: ${source.files.length}`,`key_files: ${source.files.filter(file=>file.is_key_file).slice(0,8).map(file=>file.path).join(", ")||"-"}`,`next.inspect: platform app-library inspect ${entry.entry_id} --json`,`next.checkout: platform app-library checkout ${entry.entry_id} --dir ./${sanitizeDirectoryName(entry.name||entry.entry_id)}`])}async function runSource(args,sdk){let action=args.rest[1];if(action==="tree"){await runSourceTree(args,sdk);return}if(action==="read"){await runSourceRead(args,sdk);return}if(action==="search"){await runSourceSearch(args,sdk);return}throw new Error("`platform app-library source` \u4EC5\u652F\u6301 `tree`\u3001`read`\u3001`search`\u3002")}async function runConfig(args){let action=args.rest[1];if(action==="init"){runConfigInit(args);return}if(action==="validate"){runConfigValidate(args);return}throw new Error("`platform app-library config` \u4EC5\u652F\u6301 `init`\u3001`validate`\u3002")}async function runSourceTree(args,sdk){let entryId=resolvePositionalOrConfigEntryId(args,2);if(!entryId)throw new Error("`platform app-library source tree` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let source=await sdk.getLightAppLibraryEntrySource(entryId).catch(error=>{throw formatAppLibraryError(error,"source(tree)")});writeJsonOrText(args.options.json===!0,source,[`entry_id: ${entryId}`,`snapshot_id: ${source.snapshot_id}`,`files: ${source.files.length}`,...source.files.map(file=>{let markers=[file.is_key_file?"key":null,file.is_text?"text":"binary",file.ext||"-"].filter(Boolean).join(", ");return`- ${file.path} [${markers}]`})])}async function runSourceRead(args,sdk){let entryId=resolvePositionalOrConfigEntryId(args,2);if(!entryId)throw new Error("`platform app-library source read` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let path3=args.rest[3]?.trim()||readStringOption2(args,"path");if(!path3)throw new Error("`platform app-library source read` \u9700\u8981 <path>\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--path`\u3002");let response=await sdk.readLightAppLibraryEntrySourceFile(entryId,path3).catch(error=>{throw formatAppLibraryError(error,"source(read)")});if(args.options.json===!0){writeJsonOrText(!0,response,[]);return}process.stdout.write(`# ${response.file.path}
|
|
2473
2471
|
|
|
2474
2472
|
`),process.stdout.write(`${response.file.content}${response.file.content.endsWith(`
|
|
@@ -2739,13 +2737,13 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
|
|
|
2739
2737
|
`):process.stderr.write(`worker \u672A\u5B9E\u73B0: ${worker}
|
|
2740
2738
|
\u5F53\u524D\u5DF2\u5B9E\u73B0: ${[...implementedWorkers].join(", ")}
|
|
2741
2739
|
`),process.exitCode=1;return}await spawnControlApiWorker([worker,...serializeOptions(args.options)])}function printWorkerHelp(){process.stdout.write(["platform worker","","\u7528\u6CD5\uFF1A"," platform worker preview-retention [--once] [--dry-run] [--tenant <tenant-id>] [--app <app-id>] [--ttl-hours <n>] [--limit <n>] [--json]","","\u8BF4\u660E\uFF1A"," worker \u547D\u4EE4\u662F\u672C\u5730\u5F00\u53D1/\u8FD0\u7EF4\u5165\u53E3\uFF0C\u4F1A\u8F6C\u4EA4\u7ED9 @platform/control-api \u7684 worker \u5B9E\u73B0\u3002"," preview-retention \u9ED8\u8BA4\u4EE5\u524D\u53F0\u5E38\u9A7B worker \u8FD0\u884C\uFF1B\u52A0 --once \u65F6\u53EA\u6267\u884C\u4E00\u6B21\u3002",""].join(`
|
|
2742
|
-
`))}function serializeOptions(options){let result=[];for(let[key,value]of Object.entries(options))key==="help"||key==="h"||(result.push(`--${key}`),typeof value=="string"&&result.push(value));return result}async function spawnControlApiWorker(args){await new Promise((resolve20,reject)=>{let child=spawn4("corepack",["pnpm","--silent","--filter","@platform/control-api","worker",...args],{stdio:"inherit"});child.on("error",reject),child.on("exit",(code2,signal)=>{if(signal){reject(new Error(`control-api worker exited by signal ${signal}`));return}code2&&code2!==0&&(process.exitCode=code2),resolve20()})})}applyStoredEnvironmentProfile();applyDistributionProfileDefaults();loadDotenvFiles();var distributionProfile=getDistributionProfile(),cliPackageVersion=getCliPackageVersion();function persistActiveTenantSelection(tenant){let currentContext=loadStoredCliContext();persistCliContext({active_tenant_id:tenant.tenant_id,active_tenant_name:tenant.name,selected_app_tenant_id:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_tenant_id,selected_app_id:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_id,selected_app_env:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_env,selected_app_name:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_name,selected_app_display_name:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_display_name})}function currentInvocationDir(){return getInvocationCwd()}function parseArgs5(argv){let[command="help",...rest]=argv,options={},positionals=[];for(let index=0;index<rest.length;index+=1){let current=rest[index];if(current==="--help"){options.help=!0;continue}if(current==="-h"){options.h=!0;continue}if(!current.startsWith("--")){positionals.push(current);continue}let[key,inlineValue]=current.slice(2).split("=",2);if(inlineValue!==void 0){options[key]=inlineValue;continue}let next=rest[index+1];if(next&&!next.startsWith("--")){options[key]=next,index+=1;continue}options[key]=!0}return{command,rest:positionals,options}}function printHelp(){let envCommandLines=distributionProfile.name!=="developer"?[]:[" env use <profile> \u5207\u6362 CLI \u73AF\u5883 profile\uFF08\u5982 local / test\uFF09"," env current \u67E5\u770B\u5F53\u524D CLI \u73AF\u5883 profile"," env list \u67E5\u770B\u53EF\u7528 CLI \u73AF\u5883 profile"];process7.stdout.write(["platform <command>","","Commands:"," login \u5168\u5C40\u767B\u5F55\u5E76\u4FDD\u5B58\u51ED\u636E"," logout \u6E05\u7406\u672C\u5730\u767B\u5F55\u51ED\u636E\u4E0E\u8D26\u53F7\u4E0A\u4E0B\u6587"," credentials migrate \u5C06\u65E7\u660E\u6587\u51ED\u636E\u8FC1\u79FB\u5230\u7CFB\u7EDF\u5B89\u5168\u5B58\u50A8"," version \u8F93\u51FA\u5F53\u524D CLI \u7248\u672C\u53F7"," app create \u5728\u4E91\u7AEF\u521B\u5EFA\u5E94\u7528\uFF0C\u5E76 checkout \u5230\u672C\u5730\u65B0\u76EE\u5F55"," app checkout \u4ECE\u4E91\u7AEF checkout \u5E94\u7528\u6E90\u7801\u526F\u672C\u5230\u672C\u5730\u65B0\u76EE\u5F55"," app submit \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u63D0\u4EA4\u4E3A\u65B0\u7684\u4E91\u7AEF\u6E90\u7801\u7248\u672C"," app version create \u5728\u5F53\u524D app \u4E0B\u57FA\u4E8E\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u65B0\u7684\u6E90\u7801\u7248\u672C\u9AA8\u67B6"," app version list \u67E5\u770B\u5E94\u7528\u7684\u6E90\u7801\u7248\u672C\u5217\u8868"," app versions \u67E5\u770B\u5E94\u7528\u7684\u6E90\u7801\u7248\u672C\u5217\u8868"," app status \u67E5\u770B\u5E94\u7528\u63A7\u5236\u9762\u603B\u89C8\uFF08\u542B Auth / DB / \u7248\u672C\u6982\u51B5\uFF09"," app diagnose \u67E5\u770B\u5E94\u7528\u662F\u5426\u5DF2 ready for runtime validation"," app preflight \u4E00\u6B21\u6027\u6267\u884C whoami / app current / app diagnose \u98CE\u683C\u68C0\u67E5"," app sync-platform-blocks \u540C\u6B65\u53CC\u6A21\u677F\u5E73\u53F0\u7EF4\u62A4\u533A\uFF08dry-run / adopt / apply / rollback --last\uFF09"," app import preprocess \u9884\u5904\u7406\u7B2C\u4E09\u65B9\u8BBE\u8BA1\u6E90\u7801\u5305\uFF0C\u751F\u6210 clean-source \u4E0E\u62A5\u544A"," app import stage \u628A clean-source \u4E0E\u62A5\u544A stage \u5230\u6A21\u677F\u5DE5\u4F5C\u533A"," app import merge \u628A\u4E0A\u6E38 src \u5B89\u5168\u5E76\u5165 src/imported-upstream/"," app scaffold \u6309\u9700\u6CE8\u5165\u672C\u5730 debug scaffold\uFF08auth/workflow/cms/db\uFF09"," app-library \u7BA1\u7406\u8F7B\u5E94\u7528\u8D44\u6E90\u5E93 example-app \u6761\u76EE"," app use \u517C\u5BB9\u8DEF\u5F84\uFF1A\u4E3A init/link/dev \u9009\u62E9\u76EE\u6807\u5E94\u7528"," app current \u67E5\u770B\u5F53\u524D\u5DF2\u9009\u5E94\u7528\u4E0A\u4E0B\u6587"," tenant use <id> \u8BBE\u7F6E\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587"," tenant current \u67E5\u770B\u5F53\u524D\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587",...envCommandLines," whoami \u8C03\u7528 Control API \u8F93\u51FA\u5F53\u524D\u4E3B\u4F53"," preview \u9ED8\u8BA4\u6253\u5F00\u5F53\u524D\u53EF\u7528 Preview\uFF1B\u751F\u6210\u8BF7\u7528 `platform preview generate`"," init [name] \u751F\u6210\u9879\u76EE\u9AA8\u67B6\uFF0C\u5E76\u81EA\u52A8\u5199\u5165\u5DF2\u9009\u5E94\u7528\u7ED1\u5B9A"," link \u7ED1\u5B9A tenant/app/env \u5230\u5F53\u524D\u5E94\u7528\u76EE\u5F55"," dev \u9ED8\u8BA4\u8F7B\u91CF\u5F00\u53D1\u5165\u53E3\uFF1A\u6CE8\u5165\u7ED1\u5B9A\u540E\u542F\u52A8\u672C\u5730\u5F00\u53D1\u6001"," dev push \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u8986\u76D6\u63A8\u9001\u5230\u4E91\u7AEF Dev Workspace"," dev preview generate \u57FA\u4E8E\u4E91\u7AEF Dev Workspace \u751F\u6210\u5DE5\u4F5C\u533A Preview"," auth \u7BA1\u7406 Auth \u57FA\u5EA7\u80FD\u529B\uFF08discover / configure / bind / inspect\uFF09"," cms \u7BA1\u7406 CMS \u57FA\u5EA7\u80FD\u529B\uFF08discover / configure / apply / inspect\uFF09"," asset \u7BA1\u7406\u79DF\u6237\u5171\u4EAB\u7D20\u6750\uFF08upload / list / folder / get / update / analyze / move / open / tag\uFF09"," blob \u7BA1\u7406 Object Storage Blob\uFF08upload / list / get / url\uFF09"," db \u67E5\u770B DB \u72B6\u6001\u3001\u8868\u7ED3\u6784\u4E0E\u53EA\u8BFB\u67E5\u8BE2"," data-form \u6821\u9A8C/\u7F16\u8BD1/apply/query Data Form schema \u4E0E\u8BB0\u5F55"," workflow \u7BA1\u7406 Workflow \u57FA\u5EA7\u80FD\u529B\uFF08template / definition / binding / runtime\uFF09"," notification \u7BA1\u7406 Notification \u57FA\u5EA7\u80FD\u529B\uFF08inbox / announce / delivery\uFF09"," publish \u7BA1\u7406\u5E94\u7528\u6B63\u5F0F\u53D1\u5E03\u72B6\u6001\u4E0E\u5F53\u524D\u90E8\u7F72\u7248\u672C"," resources \u6267\u884C\u8D44\u6E90 diff/apply/rollback"," logs \u67E5\u8BE2\u8FD0\u884C\u65F6\u65E5\u5FD7\uFF0C\u652F\u6301 --follow"," diagnostics \u5E73\u53F0\u672C\u5730\u8BCA\u65AD\uFF08control-api / credentials\uFF09"," worker \u542F\u52A8\u5E73\u53F0\u540E\u53F0 worker\uFF08preview-retention\uFF09","","Advanced commands:"," build \u9AD8\u7EA7\u8BCA\u65AD\u5165\u53E3\uFF1A\u53D1\u8D77\u548C\u67E5\u8BE2 build"," deploy \u8FC7\u6E21\u5165\u53E3\uFF1A\u9AD8\u7EA7\u53D1\u5E03\uFF08artifact / promote\uFF09"," rollback \u8FC7\u6E21\u5165\u53E3\uFF1A\u56DE\u6EDA\u5230\u76EE\u6807 release \u6216\u7248\u672C","","App commands:"," platform app create --tenant <tenant-id> --name <display-name> --dir <project-name> [--template frontend-app-vite|backend-app-node]"," platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," platform app checkout --tenant <tenant-id> --app <app-id> --source-version <srcver>",' platform app submit --message "local iteration"',' platform app version create --message "switch template" --template backend-app-node'," platform app versions --tenant <tenant-id> --app <app-id>"," platform app status [--tenant <tenant-id>] [--app <app-id>] [--env preview|prod]"," platform app sync-platform-blocks [--dry-run|--adopt|--apply|--rollback --last]"," platform app diagnose [--tenant <tenant-id>] [--app <app-id>] [--env preview|prod]"," platform app import preprocess [--dir <third-party-source-dir>] [--dry-run]"," platform app import stage --preprocess <source-dir|.design-preprocess|reports|import-manifest.json>"," platform app import merge [--workspace-dir <template-workspace-dir>]"," platform app scaffold <auth-debug|workflow-debug|cms-debug|db-debug>"," platform app-library list"," platform app-library config init"," platform app-library inspect entry-demo"," platform app-library checkout entry-demo --dir ./example-app-demo",' platform app-library create --name "Data Form Verify" --summary "\u672C\u5730\u9A8C\u8BC1\u540E\u7684\u793A\u4F8B\u5E94\u7528"'," platform app-library submit entry-demo"," platform app use --tenant <tenant-id> --app <app-id> --env preview"," platform app current","","DB commands:"," platform db status"," platform db history --limit 10"," platform db migrate [--dry-run]"," platform db tables",' platform db query --sql "SELECT ... LIMIT 5"'," platform db open","","Auth commands:"," platform auth discover [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth configure [--tenant <tenant-id>] [--app <app-id>] --enable [--template <template>] [--user-store-id <id>] [--enable-admin-password|--disable-admin-password] [--enable-phone-sms-otp|--disable-phone-sms-otp] [--json]"," platform auth bind [--tenant <tenant-id>] [--app <app-id>] [--action bind|rebind|disable] [--user-store-id <id>] [--json]"," platform auth inspect [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth role list [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth role create [--tenant <tenant-id>] [--app <app-id>] --key <role-key> --name <display-name> [--description <text>] [--status active|disabled] [--json]"," platform auth role inspect [--tenant <tenant-id>] [--app <app-id>] --role <role-key> [--json]"," platform auth role update [--tenant <tenant-id>] [--app <app-id>] --role <role-key> [--name <display-name>] [--description <text> | --clear-description] [--status active|disabled] [--json]"," platform auth user-role list [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> [--json]"," platform auth user-role assign [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --roles role-a,role-b [--json]"," platform auth user-role replace [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --roles role-a,role-b [--json]"," platform auth user-role remove [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --role <role-key> [--json]","","CMS commands:"," platform cms discover [--collection <name>] [--json]"," platform cms configure collection --file <spec.json> [--json]"," platform cms configure item --file <item.json> [--item-id <item-id>] [--json]"," platform cms configure category --collection <name> --name <name> --slug <slug> [--parent-id <id>] [--order <n>] [--json]"," platform cms import markdown <file> [--collection <name>] [--item-id <item-id> | --item-id-prefix <prefix>] [--tags <label,label>] [--category-path <segment/segment>] [--cover-asset-id <asset-id>] [--publish | --publish-status draft|published|archived] [--skip-existing] [--dry-run] [--json]"," platform cms import url <url> [--collection <name>] [--item-id <item-id>] [--tags <label,label>] [--category-path <segment/segment>] [--publish | --publish-status draft|published|archived] [--skip-existing] [--no-assetize-images] [--dry-run] [--json]"," platform cms attach asset --collection <name> --item-id <id> --field <field-name> --asset-id <id[,id]> [--replace] [--json]"," platform cms ensure category --collection <name> --path <segment/segment> [--json]"," platform cms list items --collection <name> [--page <n>] [--page-size <n>] [--status draft|published|archived] [--category-id <id>] [--q <keyword>] [--json]"," platform cms batch update --collection <name> --item-id <id[,id]> [--category-id <id> | --clear-category] [--add-tags <label,label>] [--status draft|published|archived] [--json]"," platform cms apply schema --collection <name> --version <n> [--json]"," platform cms apply publish --collection <name> --item-id <id> --status draft|published|archived [--json]"," platform cms inspect schema --collection <name> [--json]"," platform cms inspect item --collection <name> --id <id> [--json]"," platform cms inspect delivery list --collection <name> [--page <n>] [--page-size <n>] [--tag <tag>] [--category-id <id>] [--json]"," platform cms inspect delivery get --collection <name> (--slug <slug> | --id <id>) [--json]"," platform cms inspect delivery categories --collection <name> [--json]","","Asset commands:"," platform asset upload <file-path> [--title <title>] [--folder-id <folder-id>]"," platform asset list [--q <keyword>] [--media-type image|video] [--folder-id <folder-id>] [--page <n>] [--limit <n>]"," platform asset folder list"," platform asset folder create <name> [--parent-folder-id <folder-id>]"," platform asset folder rename <folder-id> --name <name> [--parent-folder-id <folder-id> | --root]"," platform asset get <asset-id>"," platform asset move <asset-id> [--folder-id <folder-id> | --root]"," platform asset update <asset-id> [--title <title>] [--folder-id <folder-id> | --root] [--tags <label,label>]"," platform asset analyze <asset-id> [--json]"," platform asset open <asset-id> [--output <path>]"," platform asset download <asset-id> --variant thumbnail|sm|md|lg|cover [--output <path>]"," platform asset tag list [--asset <asset-id>]"," platform asset tag add <asset-id> <label>"," platform asset tag remove <asset-id> <label>","","Preview commands:"," platform preview"," platform preview open [--source-version <srcver>]"," platform preview generate [--source-version <srcver>]"," platform preview generate --from-build <build-id>","","Publish commands:"," platform publish"," platform publish status"," platform publish set [--source-version <srcver>] [--status published|unpublished]"," platform publish rollback <srcver>","","Workflow commands:"," platform workflow template list"," platform workflow template inspect --template <key>"," platform workflow definition list [--status draft|active|inactive]"," platform workflow definition inspect --definition <key>"," platform workflow definition create --definition <key> --app <app-id> [--template <template-key> | --object-type <type> --schema <json>]"," platform workflow binding list [--app <app-id>] [--definition <key>]"," platform workflow binding inspect --definition <key> [--target-id <id>]"," platform workflow binding update --definition <key> [--target-id <id>] --file <override.json>"," platform workflow role bind --definition <key> --app <app-id> --file <bindings.json> # \u4F4E\u5C42\u9AD8\u7EA7\u5165\u53E3"," platform workflow diagnose [--app <app-id>]"," platform workflow start --definition <key> --object-type <type> --object-id <id>"," platform workflow action --instance <instance-id> --action <action-key>"," platform workflow tasks [--status pending]"," platform workflow instance <instance-id>","","Notification commands:"," platform notification inbox list [--app <app-id>] [--type task_projection|announcement|notification|alert] [--status unread|read|dismissed|archived] [--limit <n>]"," platform notification inbox update <item-id> --status unread|read|dismissed|archived"," platform notification announce platform --tenant <tenant-id> --title <text> [--body <text>] [--level info|success|warning|error]"," platform notification announce app --tenant <tenant-id> --app <app-id> --title <text> [--body <text>] [--level info|success|warning|error]"," platform notification delivery [--app <app-id>] [--status pending|running|succeeded|failed|dead]"," platform notification end-user users --app <app-id>"," platform notification end-user inbox --app <app-id> --end-user <app-user-id> [--type task_projection|announcement|notification|alert] [--status unread|read|dismissed|archived] [--limit <n>]"," platform notification end-user unread --app <app-id> --end-user <app-user-id>"," platform notification end-user publish --app <app-id> --end-user <app-user-id> --title <text> [--body <text>] [--kind notification|alert|announcement]"," platform notification end-user announcement --app <app-id> --end-user <app-user-id> --title <text> --body <text>"," platform notification end-user reminder --app <app-id> --end-user <app-user-id> --title <text> --remind-at <ISO datetime> [--body <text>]","","Advanced release commands:"," platform deploy [--source-version <srcver>] [--prod]"," platform rollback <release-id|version>","","Advanced build commands:"," platform build run --source-version <srcver>"," platform build get <build-id>"," platform build events <build-id>"," platform build validate --app <app-id> --source-version <srcver>"," platform logs --follow"," platform diagnostics control-api [--json]"," platform diagnostics credentials [--json] [--strict]"," platform worker preview-retention [--once] [--dry-run] [--json]","","Resource commands:"," platform resources diff --base-snapshot <rsnap-id>"," platform resources apply --base-snapshot <rsnap-id>"," platform resources rollback <rsnap-id> --approve-id <approve-id>","","Examples:"," platform login"," platform login --pat <personal-access-token>"," platform env use local"," platform env use test"," platform env current",' platform app create --tenant t-default --name "\u6D3B\u52A8\u9080\u8BF7\u51FD" --dir invite-frontend',' platform app create --tenant t-default --name "\u62A5\u540D\u52A9\u624B" --dir signup-runtime --template backend-app-node',' platform app create --tenant t-default --name "\u8425\u9500\u9875" --dir landing-page --template frontend-app-vite',' platform app create --tenant t-default --name "\u4E1A\u52A1\u540E\u53F0" --dir ops-console --template backend-app-node'," platform app checkout --tenant t-default --app app-demo --dir app-demo"," platform app checkout --tenant t-default --app app-demo --source-version srcver-123",' platform app submit --message "local iteration"'," platform dev push"," platform dev preview generate"," platform dev preview open",' platform asset upload ./logo.png --title "\u54C1\u724C Logo"'," platform asset folder create \u54C1\u724C\u7D20\u6750"," platform asset folder rename asset-folder-123 --name \u54C1\u724C\u89C6\u89C9 --root"," platform asset folder list"," platform asset list --q logo --tag-ids tag-1,tag-2 --page 2"," platform asset get asset-123"," platform asset move asset-123 --folder-id asset-folder-123",' platform asset update asset-123 --title "\u9996\u9875 Hero \u56FE" --scene outdoor --tags hero,homepage'," platform asset analyze asset-123"," platform asset open asset-123"," platform asset download asset-123 --variant md"," platform asset tag list --asset asset-123"," platform asset tag add asset-123 logo"," platform asset tag remove asset-123 logo"," platform app versions --tenant t-default --app app-demo"," platform whoami --tenant t-default"," platform build get build-123"," platform build events build-123"," platform build run --source-version srcver-123"," platform build validate --app app-demo --source-version srcver-123"," platform preview"," platform preview open --source-version srcver-123"," platform preview generate"," platform preview generate --source-version srcver-123"," platform publish"," platform publish status"," platform publish set --status unpublished"," platform publish set --source-version srcver-123 --status published"," platform publish rollback srcver-122"," cd signup-lite && platform dev"," cd signup-lite && platform dev push"," cd signup-lite && platform dev preview generate"," cd signup-lite && platform dev preview open"," platform deploy --source-version srcver-123"," platform deploy --prod"," platform rollback v0.2.0","","Other examples:"," platform app current"," platform tenant use t-default"," platform tenant current"," platform db status"," platform db history --limit 10"," platform db tables",' platform db query --sql "SELECT * FROM example_items LIMIT 5"'," platform auth discover --app app-demo"," platform auth configure --app app-demo --enable --template email_magic_link_only"," platform auth configure --app app-demo --enable --template phone_sms_otp_only"," platform auth configure --app app-demo --enable --template email_magic_link_and_phone_sms_otp"," platform auth configure --app app-demo --enable --enable-phone-sms-otp"," platform auth bind --app app-checkin --action bind --user-store-id us_xxx"," platform auth inspect --app app-demo --json"," platform cms discover"," platform cms discover --collection article"," platform cms configure collection --file ./cms/article.collection.json"," platform cms configure item --file ./cms/article.item.json"," platform cms import markdown ./docs/post.md --collection article --tags cms,agent --category-path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03 --cover-asset-id asset-123 --publish"," platform cms import url https://zhuanlan.zhihu.com/p/488185988 --collection article --tags cms,url --dry-run"," platform cms import url https://example.com/post --collection article --no-assetize-images"," platform cms import markdown ./docs/articles --collection article --recursive --item-id-prefix article-doc --skip-existing"," platform cms import markdown ./docs/post.md --collection article --category-path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03 --dry-run --json"," platform cms import markdown ./docs/post.md --collection article --skip-existing --publish"," platform cms attach asset --collection article --item-id cms-item-123 --field cover --asset-id asset-123"," platform cms ensure category --collection article --path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03"," platform cms list items --collection article --status draft"," platform cms batch update --collection article --item-id item-a,item-b --category-id cms-category-123 --add-tags cms,cli --status published"," platform cms apply schema --collection article --version 1"," platform cms inspect schema --collection article --json"," platform cms inspect item --collection article --id cms-item-123"," platform cms inspect delivery list --collection article --tag cms"," platform cms inspect delivery get --collection article --slug introducing-cms-base"," platform resources diff --base-snapshot rsnap-123"," platform resources apply --base-snapshot rsnap-123"," platform resources rollback rsnap-122 --approve-id approve-123"," platform logs --follow","","Compatible path examples:"," platform app use --tenant t-default --app app-demo --env preview"," platform init demo-app"," platform link --tenant t-default --app app-demo --env preview"," platform dev --target tenant-workbench"," platform dev --remote-bindings"," platform dev --remote-bindings=db",""].join(`
|
|
2740
|
+
`))}function serializeOptions(options){let result=[];for(let[key,value]of Object.entries(options))key==="help"||key==="h"||(result.push(`--${key}`),typeof value=="string"&&result.push(value));return result}async function spawnControlApiWorker(args){await new Promise((resolve20,reject)=>{let child=spawn4("corepack",["pnpm","--silent","--filter","@platform/control-api","worker",...args],{stdio:"inherit"});child.on("error",reject),child.on("exit",(code2,signal)=>{if(signal){reject(new Error(`control-api worker exited by signal ${signal}`));return}code2&&code2!==0&&(process.exitCode=code2),resolve20()})})}applyStoredEnvironmentProfile();applyDistributionProfileDefaults();loadDotenvFiles();var distributionProfile=getDistributionProfile(),cliPackageVersion=getCliPackageVersion();function persistActiveTenantSelection(tenant){let currentContext=loadStoredCliContext();persistCliContext({active_tenant_id:tenant.tenant_id,active_tenant_name:tenant.name,selected_app_tenant_id:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_tenant_id,selected_app_id:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_id,selected_app_env:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_env,selected_app_name:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_name,selected_app_display_name:contextBelongsToDifferentTenant(currentContext,tenant.tenant_id)?void 0:currentContext?.selected_app_display_name})}function currentInvocationDir(){return getInvocationCwd()}function parseArgs5(argv){let[command="help",...rest]=argv,options={},positionals=[];for(let index=0;index<rest.length;index+=1){let current=rest[index];if(current==="--help"){options.help=!0;continue}if(current==="-h"){options.h=!0;continue}if(!current.startsWith("--")){positionals.push(current);continue}let[key,inlineValue]=current.slice(2).split("=",2);if(inlineValue!==void 0){options[key]=inlineValue;continue}let next=rest[index+1];if(next&&!next.startsWith("--")){options[key]=next,index+=1;continue}options[key]=!0}return{command,rest:positionals,options}}function printHelp(){let envCommandLines=distributionProfile.name!=="developer"?[]:[" env use <profile> \u5207\u6362 CLI \u73AF\u5883 profile\uFF08\u5982 local / test\uFF09"," env current \u67E5\u770B\u5F53\u524D CLI \u73AF\u5883 profile"," env list \u67E5\u770B\u53EF\u7528 CLI \u73AF\u5883 profile"];process7.stdout.write(["platform <command>","","Commands:"," login \u5168\u5C40\u767B\u5F55\u5E76\u4FDD\u5B58\u51ED\u636E"," logout \u6E05\u7406\u672C\u5730\u767B\u5F55\u51ED\u636E\u4E0E\u8D26\u53F7\u4E0A\u4E0B\u6587"," credentials migrate \u8FC1\u79FB\u6216\u51C0\u5316\u65E7\u7248\u51ED\u636E"," version \u8F93\u51FA\u5F53\u524D CLI \u7248\u672C\u53F7"," app create \u5728\u4E91\u7AEF\u521B\u5EFA\u5E94\u7528\uFF0C\u5E76 checkout \u5230\u672C\u5730\u65B0\u76EE\u5F55"," app checkout \u4ECE\u4E91\u7AEF checkout \u5E94\u7528\u6E90\u7801\u526F\u672C\u5230\u672C\u5730\u65B0\u76EE\u5F55"," app submit \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u63D0\u4EA4\u4E3A\u65B0\u7684\u4E91\u7AEF\u6E90\u7801\u7248\u672C"," app version create \u5728\u5F53\u524D app \u4E0B\u57FA\u4E8E\u6307\u5B9A\u6A21\u677F\u521B\u5EFA\u65B0\u7684\u6E90\u7801\u7248\u672C\u9AA8\u67B6"," app version list \u67E5\u770B\u5E94\u7528\u7684\u6E90\u7801\u7248\u672C\u5217\u8868"," app versions \u67E5\u770B\u5E94\u7528\u7684\u6E90\u7801\u7248\u672C\u5217\u8868"," app status \u67E5\u770B\u5E94\u7528\u63A7\u5236\u9762\u603B\u89C8\uFF08\u542B Auth / DB / \u7248\u672C\u6982\u51B5\uFF09"," app diagnose \u67E5\u770B\u5E94\u7528\u662F\u5426\u5DF2 ready for runtime validation"," app preflight \u4E00\u6B21\u6027\u6267\u884C whoami / app current / app diagnose \u98CE\u683C\u68C0\u67E5"," app sync-platform-blocks \u540C\u6B65\u53CC\u6A21\u677F\u5E73\u53F0\u7EF4\u62A4\u533A\uFF08dry-run / adopt / apply / rollback --last\uFF09"," app import preprocess \u9884\u5904\u7406\u7B2C\u4E09\u65B9\u8BBE\u8BA1\u6E90\u7801\u5305\uFF0C\u751F\u6210 clean-source \u4E0E\u62A5\u544A"," app import stage \u628A clean-source \u4E0E\u62A5\u544A stage \u5230\u6A21\u677F\u5DE5\u4F5C\u533A"," app import merge \u628A\u4E0A\u6E38 src \u5B89\u5168\u5E76\u5165 src/imported-upstream/"," app scaffold \u6309\u9700\u6CE8\u5165\u672C\u5730 debug scaffold\uFF08auth/workflow/cms/db\uFF09"," app-library \u7BA1\u7406\u8F7B\u5E94\u7528\u8D44\u6E90\u5E93 example-app \u6761\u76EE"," app use \u517C\u5BB9\u8DEF\u5F84\uFF1A\u4E3A init/link/dev \u9009\u62E9\u76EE\u6807\u5E94\u7528"," app current \u67E5\u770B\u5F53\u524D\u5DF2\u9009\u5E94\u7528\u4E0A\u4E0B\u6587"," tenant use <id> \u8BBE\u7F6E\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587"," tenant current \u67E5\u770B\u5F53\u524D\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587",...envCommandLines," whoami \u8C03\u7528 Control API \u8F93\u51FA\u5F53\u524D\u4E3B\u4F53"," preview \u9ED8\u8BA4\u6253\u5F00\u5F53\u524D\u53EF\u7528 Preview\uFF1B\u751F\u6210\u8BF7\u7528 `platform preview generate`"," init [name] \u751F\u6210\u9879\u76EE\u9AA8\u67B6\uFF0C\u5E76\u81EA\u52A8\u5199\u5165\u5DF2\u9009\u5E94\u7528\u7ED1\u5B9A"," link \u7ED1\u5B9A tenant/app/env \u5230\u5F53\u524D\u5E94\u7528\u76EE\u5F55"," dev \u9ED8\u8BA4\u8F7B\u91CF\u5F00\u53D1\u5165\u53E3\uFF1A\u6CE8\u5165\u7ED1\u5B9A\u540E\u542F\u52A8\u672C\u5730\u5F00\u53D1\u6001"," dev push \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u8986\u76D6\u63A8\u9001\u5230\u4E91\u7AEF Dev Workspace"," dev preview generate \u57FA\u4E8E\u4E91\u7AEF Dev Workspace \u751F\u6210\u5DE5\u4F5C\u533A Preview"," auth \u7BA1\u7406 Auth \u57FA\u5EA7\u80FD\u529B\uFF08discover / configure / bind / inspect\uFF09"," cms \u7BA1\u7406 CMS \u57FA\u5EA7\u80FD\u529B\uFF08discover / configure / apply / inspect\uFF09"," asset \u7BA1\u7406\u79DF\u6237\u5171\u4EAB\u7D20\u6750\uFF08upload / list / folder / get / update / analyze / move / open / tag\uFF09"," blob \u7BA1\u7406 Object Storage Blob\uFF08upload / list / get / url\uFF09"," db \u67E5\u770B DB \u72B6\u6001\u3001\u8868\u7ED3\u6784\u4E0E\u53EA\u8BFB\u67E5\u8BE2"," data-form \u6821\u9A8C/\u7F16\u8BD1/apply/query Data Form schema \u4E0E\u8BB0\u5F55"," workflow \u7BA1\u7406 Workflow \u57FA\u5EA7\u80FD\u529B\uFF08template / definition / binding / runtime\uFF09"," notification \u7BA1\u7406 Notification \u57FA\u5EA7\u80FD\u529B\uFF08inbox / announce / delivery\uFF09"," publish \u7BA1\u7406\u5E94\u7528\u6B63\u5F0F\u53D1\u5E03\u72B6\u6001\u4E0E\u5F53\u524D\u90E8\u7F72\u7248\u672C"," resources \u6267\u884C\u8D44\u6E90 diff/apply/rollback"," logs \u67E5\u8BE2\u8FD0\u884C\u65F6\u65E5\u5FD7\uFF0C\u652F\u6301 --follow"," diagnostics \u5E73\u53F0\u672C\u5730\u8BCA\u65AD\uFF08control-api / credentials\uFF09"," worker \u542F\u52A8\u5E73\u53F0\u540E\u53F0 worker\uFF08preview-retention\uFF09","","Advanced commands:"," build \u9AD8\u7EA7\u8BCA\u65AD\u5165\u53E3\uFF1A\u53D1\u8D77\u548C\u67E5\u8BE2 build"," deploy \u8FC7\u6E21\u5165\u53E3\uFF1A\u9AD8\u7EA7\u53D1\u5E03\uFF08artifact / promote\uFF09"," rollback \u8FC7\u6E21\u5165\u53E3\uFF1A\u56DE\u6EDA\u5230\u76EE\u6807 release \u6216\u7248\u672C","","App commands:"," platform app create --tenant <tenant-id> --name <display-name> --dir <project-name> [--template frontend-app-vite|backend-app-node]"," platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," platform app checkout --tenant <tenant-id> --app <app-id> --source-version <srcver>",' platform app submit --message "local iteration"',' platform app version create --message "switch template" --template backend-app-node'," platform app versions --tenant <tenant-id> --app <app-id>"," platform app status [--tenant <tenant-id>] [--app <app-id>] [--env preview|prod]"," platform app sync-platform-blocks [--dry-run|--adopt|--apply|--rollback --last]"," platform app diagnose [--tenant <tenant-id>] [--app <app-id>] [--env preview|prod]"," platform app import preprocess [--dir <third-party-source-dir>] [--dry-run]"," platform app import stage --preprocess <source-dir|.design-preprocess|reports|import-manifest.json>"," platform app import merge [--workspace-dir <template-workspace-dir>]"," platform app scaffold <auth-debug|workflow-debug|cms-debug|db-debug>"," platform app-library list"," platform app-library config init"," platform app-library inspect entry-demo"," platform app-library checkout entry-demo --dir ./example-app-demo",' platform app-library create --name "Data Form Verify" --summary "\u672C\u5730\u9A8C\u8BC1\u540E\u7684\u793A\u4F8B\u5E94\u7528"'," platform app-library submit entry-demo"," platform app use --tenant <tenant-id> --app <app-id> --env preview"," platform app current","","DB commands:"," platform db status"," platform db history --limit 10"," platform db migrate [--dry-run]"," platform db tables",' platform db query --sql "SELECT ... LIMIT 5"'," platform db open","","Auth commands:"," platform auth discover [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth configure [--tenant <tenant-id>] [--app <app-id>] --enable [--template <template>] [--user-store-id <id>] [--enable-admin-password|--disable-admin-password] [--enable-phone-sms-otp|--disable-phone-sms-otp] [--json]"," platform auth bind [--tenant <tenant-id>] [--app <app-id>] [--action bind|rebind|disable] [--user-store-id <id>] [--json]"," platform auth inspect [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth role list [--tenant <tenant-id>] [--app <app-id>] [--json]"," platform auth role create [--tenant <tenant-id>] [--app <app-id>] --key <role-key> --name <display-name> [--description <text>] [--status active|disabled] [--json]"," platform auth role inspect [--tenant <tenant-id>] [--app <app-id>] --role <role-key> [--json]"," platform auth role update [--tenant <tenant-id>] [--app <app-id>] --role <role-key> [--name <display-name>] [--description <text> | --clear-description] [--status active|disabled] [--json]"," platform auth user-role list [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> [--json]"," platform auth user-role assign [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --roles role-a,role-b [--json]"," platform auth user-role replace [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --roles role-a,role-b [--json]"," platform auth user-role remove [--tenant <tenant-id>] [--app <app-id>] --user <app-user-id> --role <role-key> [--json]","","CMS commands:"," platform cms discover [--collection <name>] [--json]"," platform cms configure collection --file <spec.json> [--json]"," platform cms configure item --file <item.json> [--item-id <item-id>] [--json]"," platform cms configure category --collection <name> --name <name> --slug <slug> [--parent-id <id>] [--order <n>] [--json]"," platform cms import markdown <file> [--collection <name>] [--item-id <item-id> | --item-id-prefix <prefix>] [--tags <label,label>] [--category-path <segment/segment>] [--cover-asset-id <asset-id>] [--publish | --publish-status draft|published|archived] [--skip-existing] [--dry-run] [--json]"," platform cms import url <url> [--collection <name>] [--item-id <item-id>] [--tags <label,label>] [--category-path <segment/segment>] [--publish | --publish-status draft|published|archived] [--skip-existing] [--no-assetize-images] [--dry-run] [--json]"," platform cms attach asset --collection <name> --item-id <id> --field <field-name> --asset-id <id[,id]> [--replace] [--json]"," platform cms ensure category --collection <name> --path <segment/segment> [--json]"," platform cms list items --collection <name> [--page <n>] [--page-size <n>] [--status draft|published|archived] [--category-id <id>] [--q <keyword>] [--json]"," platform cms batch update --collection <name> --item-id <id[,id]> [--category-id <id> | --clear-category] [--add-tags <label,label>] [--status draft|published|archived] [--json]"," platform cms apply schema --collection <name> --version <n> [--json]"," platform cms apply publish --collection <name> --item-id <id> --status draft|published|archived [--json]"," platform cms inspect schema --collection <name> [--json]"," platform cms inspect item --collection <name> --id <id> [--json]"," platform cms inspect delivery list --collection <name> [--page <n>] [--page-size <n>] [--tag <tag>] [--category-id <id>] [--json]"," platform cms inspect delivery get --collection <name> (--slug <slug> | --id <id>) [--json]"," platform cms inspect delivery categories --collection <name> [--json]","","Asset commands:"," platform asset upload <file-path> [--title <title>] [--folder-id <folder-id>]"," platform asset list [--q <keyword>] [--media-type image|video] [--folder-id <folder-id>] [--page <n>] [--limit <n>]"," platform asset folder list"," platform asset folder create <name> [--parent-folder-id <folder-id>]"," platform asset folder rename <folder-id> --name <name> [--parent-folder-id <folder-id> | --root]"," platform asset get <asset-id>"," platform asset move <asset-id> [--folder-id <folder-id> | --root]"," platform asset update <asset-id> [--title <title>] [--folder-id <folder-id> | --root] [--tags <label,label>]"," platform asset analyze <asset-id> [--json]"," platform asset open <asset-id> [--output <path>]"," platform asset download <asset-id> --variant thumbnail|sm|md|lg|cover [--output <path>]"," platform asset tag list [--asset <asset-id>]"," platform asset tag add <asset-id> <label>"," platform asset tag remove <asset-id> <label>","","Preview commands:"," platform preview"," platform preview open [--source-version <srcver>]"," platform preview generate [--source-version <srcver>]"," platform preview generate --from-build <build-id>","","Publish commands:"," platform publish"," platform publish status"," platform publish set [--source-version <srcver>] [--status published|unpublished]"," platform publish rollback <srcver>","","Workflow commands:"," platform workflow template list"," platform workflow template inspect --template <key>"," platform workflow definition list [--status draft|active|inactive]"," platform workflow definition inspect --definition <key>"," platform workflow definition create --definition <key> --app <app-id> [--template <template-key> | --object-type <type> --schema <json>]"," platform workflow binding list [--app <app-id>] [--definition <key>]"," platform workflow binding inspect --definition <key> [--target-id <id>]"," platform workflow binding update --definition <key> [--target-id <id>] --file <override.json>"," platform workflow role bind --definition <key> --app <app-id> --file <bindings.json> # \u4F4E\u5C42\u9AD8\u7EA7\u5165\u53E3"," platform workflow diagnose [--app <app-id>]"," platform workflow start --definition <key> --object-type <type> --object-id <id>"," platform workflow action --instance <instance-id> --action <action-key>"," platform workflow tasks [--status pending]"," platform workflow instance <instance-id>","","Notification commands:"," platform notification inbox list [--app <app-id>] [--type task_projection|announcement|notification|alert] [--status unread|read|dismissed|archived] [--limit <n>]"," platform notification inbox update <item-id> --status unread|read|dismissed|archived"," platform notification announce platform --tenant <tenant-id> --title <text> [--body <text>] [--level info|success|warning|error]"," platform notification announce app --tenant <tenant-id> --app <app-id> --title <text> [--body <text>] [--level info|success|warning|error]"," platform notification delivery [--app <app-id>] [--status pending|running|succeeded|failed|dead]"," platform notification end-user users --app <app-id>"," platform notification end-user inbox --app <app-id> --end-user <app-user-id> [--type task_projection|announcement|notification|alert] [--status unread|read|dismissed|archived] [--limit <n>]"," platform notification end-user unread --app <app-id> --end-user <app-user-id>"," platform notification end-user publish --app <app-id> --end-user <app-user-id> --title <text> [--body <text>] [--kind notification|alert|announcement]"," platform notification end-user announcement --app <app-id> --end-user <app-user-id> --title <text> --body <text>"," platform notification end-user reminder --app <app-id> --end-user <app-user-id> --title <text> --remind-at <ISO datetime> [--body <text>]","","Advanced release commands:"," platform deploy [--source-version <srcver>] [--prod]"," platform rollback <release-id|version>","","Advanced build commands:"," platform build run --source-version <srcver>"," platform build get <build-id>"," platform build events <build-id>"," platform build validate --app <app-id> --source-version <srcver>"," platform logs --follow"," platform diagnostics control-api [--json]"," platform diagnostics credentials [--json] [--strict]"," platform worker preview-retention [--once] [--dry-run] [--json]","","Resource commands:"," platform resources diff --base-snapshot <rsnap-id>"," platform resources apply --base-snapshot <rsnap-id>"," platform resources rollback <rsnap-id> --approve-id <approve-id>","","Examples:"," platform login"," platform login --pat <personal-access-token>"," platform env use local"," platform env use test"," platform env current",' platform app create --tenant t-default --name "\u6D3B\u52A8\u9080\u8BF7\u51FD" --dir invite-frontend',' platform app create --tenant t-default --name "\u62A5\u540D\u52A9\u624B" --dir signup-runtime --template backend-app-node',' platform app create --tenant t-default --name "\u8425\u9500\u9875" --dir landing-page --template frontend-app-vite',' platform app create --tenant t-default --name "\u4E1A\u52A1\u540E\u53F0" --dir ops-console --template backend-app-node'," platform app checkout --tenant t-default --app app-demo --dir app-demo"," platform app checkout --tenant t-default --app app-demo --source-version srcver-123",' platform app submit --message "local iteration"'," platform dev push"," platform dev preview generate"," platform dev preview open",' platform asset upload ./logo.png --title "\u54C1\u724C Logo"'," platform asset folder create \u54C1\u724C\u7D20\u6750"," platform asset folder rename asset-folder-123 --name \u54C1\u724C\u89C6\u89C9 --root"," platform asset folder list"," platform asset list --q logo --tag-ids tag-1,tag-2 --page 2"," platform asset get asset-123"," platform asset move asset-123 --folder-id asset-folder-123",' platform asset update asset-123 --title "\u9996\u9875 Hero \u56FE" --scene outdoor --tags hero,homepage'," platform asset analyze asset-123"," platform asset open asset-123"," platform asset download asset-123 --variant md"," platform asset tag list --asset asset-123"," platform asset tag add asset-123 logo"," platform asset tag remove asset-123 logo"," platform app versions --tenant t-default --app app-demo"," platform whoami --tenant t-default"," platform build get build-123"," platform build events build-123"," platform build run --source-version srcver-123"," platform build validate --app app-demo --source-version srcver-123"," platform preview"," platform preview open --source-version srcver-123"," platform preview generate"," platform preview generate --source-version srcver-123"," platform publish"," platform publish status"," platform publish set --status unpublished"," platform publish set --source-version srcver-123 --status published"," platform publish rollback srcver-122"," cd signup-lite && platform dev"," cd signup-lite && platform dev push"," cd signup-lite && platform dev preview generate"," cd signup-lite && platform dev preview open"," platform deploy --source-version srcver-123"," platform deploy --prod"," platform rollback v0.2.0","","Other examples:"," platform app current"," platform tenant use t-default"," platform tenant current"," platform db status"," platform db history --limit 10"," platform db tables",' platform db query --sql "SELECT * FROM example_items LIMIT 5"'," platform auth discover --app app-demo"," platform auth configure --app app-demo --enable --template email_magic_link_only"," platform auth configure --app app-demo --enable --template phone_sms_otp_only"," platform auth configure --app app-demo --enable --template email_magic_link_and_phone_sms_otp"," platform auth configure --app app-demo --enable --enable-phone-sms-otp"," platform auth bind --app app-checkin --action bind --user-store-id us_xxx"," platform auth inspect --app app-demo --json"," platform cms discover"," platform cms discover --collection article"," platform cms configure collection --file ./cms/article.collection.json"," platform cms configure item --file ./cms/article.item.json"," platform cms import markdown ./docs/post.md --collection article --tags cms,agent --category-path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03 --cover-asset-id asset-123 --publish"," platform cms import url https://zhuanlan.zhihu.com/p/488185988 --collection article --tags cms,url --dry-run"," platform cms import url https://example.com/post --collection article --no-assetize-images"," platform cms import markdown ./docs/articles --collection article --recursive --item-id-prefix article-doc --skip-existing"," platform cms import markdown ./docs/post.md --collection article --category-path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03 --dry-run --json"," platform cms import markdown ./docs/post.md --collection article --skip-existing --publish"," platform cms attach asset --collection article --item-id cms-item-123 --field cover --asset-id asset-123"," platform cms ensure category --collection article --path \u4EA7\u54C1\u66F4\u65B0/\u7248\u672C\u53D1\u5E03"," platform cms list items --collection article --status draft"," platform cms batch update --collection article --item-id item-a,item-b --category-id cms-category-123 --add-tags cms,cli --status published"," platform cms apply schema --collection article --version 1"," platform cms inspect schema --collection article --json"," platform cms inspect item --collection article --id cms-item-123"," platform cms inspect delivery list --collection article --tag cms"," platform cms inspect delivery get --collection article --slug introducing-cms-base"," platform resources diff --base-snapshot rsnap-123"," platform resources apply --base-snapshot rsnap-123"," platform resources rollback rsnap-122 --approve-id approve-123"," platform logs --follow","","Compatible path examples:"," platform app use --tenant t-default --app app-demo --env preview"," platform init demo-app"," platform link --tenant t-default --app app-demo --env preview"," platform dev --target tenant-workbench"," platform dev --remote-bindings"," platform dev --remote-bindings=db",""].join(`
|
|
2743
2741
|
`))}function printVersion(){process7.stdout.write(`v${cliPackageVersion}
|
|
2744
2742
|
`)}function normalizeAppTemplateOption(value){return normalizeAppTemplateKey(value)}function readRequiredEnv(key){let value=process7.env[key];if(!value||value.trim().length===0)throw new Error(`\u7F3A\u5C11\u73AF\u5883\u53D8\u91CF: ${key}`);return value.trim()}function resolveBrowserLoginConfig(){let cliClientId=readAuthConfigValue(AUTH_CLI_CLIENT_ID_KEYS),cliRedirectUri=readAuthConfigValue(AUTH_CLI_REDIRECT_URI_KEYS);if(cliClientId&&cliRedirectUri)return{clientId:cliClientId,redirectUri:cliRedirectUri,source:"cli-app"};let fallbackClientId=readAuthConfigValue(AUTH_TENANT_CLIENT_ID_KEYS),fallbackRedirectUri=readAuthConfigValue(AUTH_TENANT_REDIRECT_URI_KEYS);return!fallbackClientId||!fallbackRedirectUri?null:{clientId:fallbackClientId,redirectUri:fallbackRedirectUri,source:"workbench-fallback"}}function shouldFallbackToBrowserLogin(error){if(!(error instanceof Error))return!1;let message=error.message;return message.includes("OIDC discovery \u7F3A\u5C11 Device Flow \u7AEF\u70B9")||message.includes("device_code is not allowed for this client")||message.includes("grant-type:device_code is not allowed for this client")}function readOption2(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function hasFlag2(args,key){return args.options[key]===!0}function printDiagnosticsHelp(){process7.stdout.write(["platform diagnostics","","\u7528\u6CD5\uFF1A"," platform diagnostics control-api [--json]"," platform diagnostics credentials [--json] [--strict]","","\u8BF4\u660E\uFF1A"," \u8F93\u51FA control/runtime/public endpoint \u5206\u533A\u8BCA\u65AD\uFF0C\u4E0D\u6539\u53D8\u9ED8\u8BA4 URL\u3002"," runtime/public endpoint \u4EC5\u5728\u914D\u7F6E\u5B58\u5728\u4E14 capability allowlist \u547D\u4E2D\u65F6\u63A2\u6D4B\u3002"," credentials \u53EA\u8F93\u51FA\u5B58\u50A8\u540E\u7AEF\u3001state \u8DEF\u5F84\u548C\u6743\u9650\u5224\u65AD\uFF0C\u4E0D\u8BFB\u53D6\u6216\u8F93\u51FA token\u3002"," credentials warning \u9ED8\u8BA4\u9000\u51FA\u7801\u4E3A 0\uFF1B\u4EC5\u663E\u5F0F --strict \u8FD4\u56DE\u975E\u96F6\u3002","","\u73AF\u5883\u53D8\u91CF\uFF1A"," CONTROL_API_BASE_URL"," RUNTIME_API_BASE_URL"," PUBLIC_API_BASE_URL"," CONTROL_API_RUNTIME_ENDPOINT_CAPABILITIES",""].join(`
|
|
2745
2743
|
`))}async function runDiagnostics(args){let subcommand=args.rest[0]??"help";if(hasFlag2(args,"help")||hasFlag2(args,"h")||subcommand==="help"){printDiagnosticsHelp();return}if(subcommand==="credentials"){let diagnostics2=inspectStoredCredentialSecurity();args.options.json===!0?process7.stdout.write(`${JSON.stringify(diagnostics2,null,2)}
|
|
2746
2744
|
`):process7.stdout.write(formatCredentialSecurityReportText(diagnostics2)),hasFlag2(args,"strict")&&diagnostics2.status!=="ok"&&(process7.exitCode=2);return}if(subcommand!=="control-api")throw printDiagnosticsHelp(),new Error(`\u672A\u77E5 diagnostics \u5B50\u547D\u4EE4: ${subcommand}`);let diagnostics=await collectControlApiFailureDiagnostics();if(args.options.json===!0){process7.stdout.write(`${JSON.stringify(diagnostics,null,2)}
|
|
2747
2745
|
`);return}process7.stdout.write(formatControlApiDiagnosticsText(diagnostics))}function readIntegerOption(args,key){let raw=readOption2(args,key);if(raw===void 0)return;let value=Number(raw);if(!Number.isInteger(value))throw new Error(`\u65E0\u6548\u7684 \`--${key}\`\uFF0C\u5FC5\u987B\u662F\u6574\u6570\u3002`);return value}function readCsvOption3(args,key){let raw=readOption2(args,key);return raw?raw.split(",").map(item=>item.trim()).filter(Boolean):[]}function readJsonInput(args,key="file"){let filePath=readOption2(args,key);if(!filePath)throw new Error(`\u7F3A\u5C11 \`--${key} <path>\`\u3002`);let content=filePath==="-"?readFileSync29(0,"utf8"):readFileSync29(filePath,"utf8");try{return JSON.parse(content)}catch(error){throw new Error(`\u65E0\u6CD5\u89E3\u6790 JSON \u8F93\u5165: ${filePath==="-"?"stdin":filePath}\u3002${error instanceof Error?` ${error.message}`:""}`)}}async function findExistingTenantCmsItemForImport(args){let lookup=args.lookup;if(!lookup)return null;if(lookup.kind==="item_id")try{return{item:await args.sdk.getTenantCmsItem({collection:args.collection,id:lookup.value}),matchedBy:"item_id"}}catch(error){if(error instanceof PlatformApiError&&error.status===404)return null;throw error}let matched=(await args.sdk.listTenantCmsItems({collection:args.collection,page:1,pageSize:20,query:lookup.value})).items.find(item=>item.system.slug===lookup.value);return matched?{item:matched,matchedBy:"slug"}:null}function resolveTenantContext(args,startDir=currentInvocationDir()){let linked;try{linked=readBinding(startDir)}catch{linked=null}let storedContext=loadStoredCliContext();return readOption2(args,"tenant")??linked?.binding.tenant_id??storedContext?.selected_app_tenant_id??storedContext?.active_tenant_id}function tryReadCurrentBinding2(){try{return readBinding(currentInvocationDir())}catch{return null}}function syncSelectedAppContextFromBinding(binding){let existing=loadStoredCliContext();persistCliContext({active_tenant_id:binding.tenant_id,active_tenant_name:existing?.active_tenant_id===binding.tenant_id?existing.active_tenant_name:void 0,selected_app_tenant_id:binding.tenant_id,selected_app_id:binding.app_id,selected_app_env:binding.env,selected_app_name:binding.app_name??binding.app_id,selected_app_display_name:binding.app_display_name})}function tryReadCurrentSourceContext(){try{return readSourceContext(currentInvocationDir())}catch{return null}}function readStoredCredentialModeSafely(){try{return loadStoredCredentials()?.credential_mode}catch{return}}function readCredentialPathSafely(){try{return getCredentialPath()}catch{return}}function formatRuntimeTargetLabel(env){return env==="preview"?"\u4E91\u7AEF Preview":"\u4E91\u7AEF Prod"}function summarizePreflightAppContext(args){let binding=tryReadCurrentBinding2()?.binding??null,sourceContextResult=tryReadCurrentSourceContext(),sourceContext=sourceContextResult?.sourceContext??null,context=loadStoredCliContext(),tenantId=readOption2(args,"tenant")??sourceContext?.tenant_id??binding?.tenant_id??context?.selected_app_tenant_id??context?.active_tenant_id,appId=readOption2(args,"app")??sourceContext?.app_id??binding?.app_id??context?.selected_app_id??args.rest[1],env=readOption2(args,"env")??sourceContext?.env??binding?.env??context?.selected_app_env??"preview";return sourceContext?.tenant_id&&sourceContext.app_id&&binding?.tenant_id&&binding.app_id?{status:"ready",detail:`\u5F53\u524D\u76EE\u5F55\u5DF2\u7ED1\u5B9A ${sourceContext.tenant_id}/${sourceContext.app_id}/${sourceContext.env??env}`,tenantId,appId,env,bindingPath:`${currentInvocationDir()}/.platform/config.json`,sourceContextPath:sourceContextResult?.path??null}:sourceContext?.tenant_id&&sourceContext.app_id?{status:"warning",detail:`\u5F53\u524D\u76EE\u5F55\u4EC5\u68C0\u6D4B\u5230 source-context\uFF1A${sourceContext.tenant_id}/${sourceContext.app_id}/${sourceContext.env??env}`,tenantId,appId,env,bindingPath:binding?`${currentInvocationDir()}/.platform/config.json`:null,sourceContextPath:sourceContextResult?.path??null}:binding?.tenant_id&&binding.app_id?{status:"warning",detail:`\u5F53\u524D\u76EE\u5F55\u4EC5\u68C0\u6D4B\u5230\u76EE\u5F55\u7ED1\u5B9A\uFF1A${binding.tenant_id}/${binding.app_id}/${binding.env??env}`,tenantId,appId,env,bindingPath:`${currentInvocationDir()}/.platform/config.json`,sourceContextPath:sourceContextResult?.path??null}:context?.selected_app_tenant_id&&context.selected_app_id?{status:"warning",detail:`\u5F53\u524D\u4EC5\u547D\u4E2D\u5168\u5C40 CLI \u5E94\u7528\u4E0A\u4E0B\u6587\uFF1A${context.selected_app_tenant_id}/${context.selected_app_id}/${context.selected_app_env??env}`,tenantId,appId,env,bindingPath:null,sourceContextPath:sourceContextResult?.path??null}:{status:"blocked",detail:"\u5F53\u524D\u672A\u89E3\u6790\u51FA\u53EF\u7528\u7684 tenant/app \u4E0A\u4E0B\u6587",tenantId,appId,env,bindingPath:null,sourceContextPath:sourceContextResult?.path??null}}function mergePreflightRecommendations(items){let seen=new Set,merged=[];for(let item of items){let normalized=item.trim();!normalized||seen.has(normalized)||(seen.add(normalized),merged.push(normalized))}return merged}function summarizeCheckStatuses(checks){return checks.some(item=>item.status==="blocked")?"blocked":checks.some(item=>item.status!=="ready")?"warning":"ready"}function resolveAppIdFromContext(args,positionalIndex=1){let binding=tryReadCurrentBinding2()?.binding,context=loadStoredCliContext();return readOption2(args,"app")??binding?.app_id??context?.selected_app_id??args.rest[positionalIndex]}async function collectAppControlPlaneSnapshot(args){let[overview,sourceVersions,publishSettings,authConfig,authInspect,appUsers,dbInstance,deploymentTimeline,workflowDefinitions,workflowBindings]=await Promise.all([fetchTenantOverview({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(args.credentials),tenantId:args.tenantId}),args.sdk.listTenantAppSourceVersions(args.appId).catch(()=>({items:[]})),args.sdk.getTenantAppPublishSettings(args.appId).catch(()=>null),args.sdk.getTenantAppEndUserAuthDiscovery(args.appId).catch(()=>null),args.sdk.getTenantAppEndUserAuthInspect(args.appId).catch(()=>null),args.sdk.listTenantAppEndUsers(args.appId).catch(()=>({items:[]})),args.sdk.getTenantAppDbInstance(args.appId,args.env).catch(()=>null),args.sdk.listTenantAppDeploymentTimeline(args.appId,{limit:10}).catch(()=>({items:[]})),args.sdk.listWorkflowDefinitions({target_id:args.appId,status:"active"}).catch(()=>[]),args.sdk.listWorkflowBindings({target_id:args.appId}).catch(()=>[])]),app=overview.apps.find(item=>item.id===args.appId);if(!app)throw new Error(`\u5728\u79DF\u6237 ${args.tenantId} \u4E0B\u672A\u627E\u5230\u5E94\u7528 ${args.appId}\u3002`);return{overview,app,sourceVersions,publishSettings,authConfig,authInspect,appUsers,dbInstance,deploymentTimeline,workflowDefinitions,workflowBindings}}function buildAppStatusPayload(args){let{tenantId,appId,env,snapshot}=args,authEnabled=snapshot.authConfig?.auth_enabled===!0,appUserItems=snapshot.appUsers?.items??[],blockedCount=appUserItems.filter(item=>item.status==="blocked").length,envOverview=snapshot.overview.environments.filter(item=>item.app_id===appId),previewEnv=envOverview.find(item=>item.env==="preview"),prodEnv=envOverview.find(item=>item.env==="prod"),previewDeployment=snapshot.deploymentTimeline.items.find(item=>item.env==="preview"&&item.is_current_release),prodDeployment=snapshot.deploymentTimeline.items.find(item=>item.env==="prod"&&item.is_current_release),latestSourceVersion=snapshot.sourceVersions.items[0]??null;return{tenant_id:tenantId,app_id:appId,env,app:{display_name:snapshot.app.name,slug:snapshot.app.slug??null,template_key:snapshot.app.template_key??null,publish_status:snapshot.publishSettings?.publish_status??snapshot.app.publish_status,source_versions_count:snapshot.sourceVersions.items.length,latest_source_version_id:latestSourceVersion?.source_version_id??null,latest_source_version_message:latestSourceVersion?.message??null,latest_deployment_class_suggested:latestSourceVersion?.deployment_class_suggested??null,latest_deployment_class_post_build:latestSourceVersion?.deployment_class_post_build??null},publish:{deployment_class_confirmed:snapshot.publishSettings?.deployment_class_confirmed??null,current_deployment_class_used:snapshot.publishSettings?.current_deployment_class_used??null,current_artifact_kind:snapshot.publishSettings?.current_artifact_kind??null,current_execution_mode:snapshot.publishSettings?.current_execution_mode??null,current_object_prefix:snapshot.publishSettings?.current_object_prefix??null,public_prod_url:snapshot.publishSettings?.public_prod_url??null},auth:{enabled:authEnabled,capability_name:snapshot.authConfig?.capability_name??"auth",capability_version:snapshot.authConfig?.capability_version??null,contract_version:snapshot.authConfig?.contract_version??null,user_store_id:snapshot.authConfig?.user_store_id??null,binding_id:snapshot.authConfig?.binding_id??null,binding_mode:snapshot.authConfig?.binding_mode??null,binding_status:snapshot.authConfig?.binding_status??null,auth_template:snapshot.authConfig?.auth_template??null,ui_driver:snapshot.authConfig?.ui_driver??null,enabled_recipes:snapshot.authConfig?.enabled_recipes??[],sign_in_methods:snapshot.authConfig?.sign_in_methods?.map(item=>item.method)??[],registration_mode:snapshot.authConfig?.registration_mode??null,auto_provision_app_user:typeof snapshot.authConfig?.auto_provision_app_user=="boolean"?snapshot.authConfig.auto_provision_app_user:null,owner_service:snapshot.authConfig?.owner_service??null,last_runtime_status:snapshot.authConfig?.last_runtime_status??null,inspect_status:snapshot.authInspect?.inspect_status??null,inspect_issues:snapshot.authInspect?.issues??[],runtime_environments:snapshot.authInspect?.environments.map(item=>({env:item.env,status:item.status,missing_binding_keys:item.missing_binding_keys,issues:item.issues,updated_at:item.updated_at??null}))??[],app_user_count:appUserItems.length,blocked_app_user_count:blockedCount},runtime:{preview:{version:previewEnv?.version??null,health:previewEnv?.health??previewDeployment?.health??null,source_version_id:previewEnv?.source_version_id??previewDeployment?.source_version_id??null,preview_url:previewDeployment?.preview_url??null},prod:{version:prodEnv?.version??null,health:prodEnv?.health??prodDeployment?.health??null,source_version_id:prodEnv?.source_version_id??prodDeployment?.source_version_id??null}},db:{bound:snapshot.dbInstance?.bound??!1,status:snapshot.dbInstance?.status??null,schema_name:snapshot.dbInstance?.schema_name??null,database_name:snapshot.dbInstance?.database_name??null,tables_count:typeof snapshot.dbInstance?.tables_count=="number"?snapshot.dbInstance.tables_count:null,latest_migration:snapshot.dbInstance?.latest_migration?.migration_path??null},workflow:{active_definition_count:snapshot.workflowDefinitions.length,binding_count:snapshot.workflowBindings.length,definitions:snapshot.workflowDefinitions.map(item=>({definition_key:item.definition_key,status:item.status,object_type:item.object_type})),bindings:snapshot.workflowBindings.map(item=>({definition_key:item.definition_key,target_id:item.target_id,target_scope:item.target_scope,status:item.status}))}}}function buildAppDiagnosePayload(args){let authEnv=args.statusPayload.auth.runtime_environments.find(item=>item.env===args.env)??null,dbTablesCount=args.statusPayload.db.tables_count,databaseStatus=args.statusPayload.db.bound?typeof dbTablesCount=="number"&&dbTablesCount===0?"warning":"ready":"warning",databaseDetail=args.statusPayload.db.bound?typeof dbTablesCount=="number"&&dbTablesCount===0?`${args.statusPayload.db.database_name??"-"} / ${args.statusPayload.db.schema_name??"-"} (0 tables)`:`${args.statusPayload.db.database_name??"-"} / ${args.statusPayload.db.schema_name??"-"}`:"\u5F53\u524D\u73AF\u5883\u672A\u5B8C\u6210 DB \u7ED1\u5B9A",checks={app_context:{status:args.bindingPath?"ready":"warning",detail:args.bindingPath?`\u5DF2\u7ED1\u5B9A\u9879\u76EE\u76EE\u5F55 (${args.bindingPath})`:"\u5F53\u524D\u76EE\u5F55\u672A\u68C0\u6D4B\u5230 `.platform/config.json`"},auth_runtime:{status:args.statusPayload.auth.enabled&&authEnv?.status==="ready"?"ready":args.statusPayload.auth.enabled?"warning":"not_configured",detail:args.statusPayload.auth.enabled?authEnv?`${args.env}=${authEnv.status}`:`\u7F3A\u5C11 ${args.env} \u8FD0\u884C\u65F6\u68C0\u67E5\u7ED3\u679C`:"\u5F53\u524D app \u672A\u542F\u7528 Auth\uFF1B\u5982\u679C\u5F53\u524D\u6A21\u677F\u4E0D\u4F9D\u8D56\u767B\u5F55\uFF0C\u53EF\u5FFD\u7565"},database:{status:databaseStatus,detail:databaseDetail},workflow:{status:args.statusPayload.workflow.active_definition_count>0&&args.statusPayload.workflow.binding_count>0?"ready":args.statusPayload.workflow.active_definition_count>0?"warning":"not_configured",detail:args.statusPayload.workflow.active_definition_count>0?`definitions=${args.statusPayload.workflow.active_definition_count}, bindings=${args.statusPayload.workflow.binding_count}`:"\u5F53\u524D app \u672A\u914D\u7F6E Workflow\uFF1B\u5982\u679C\u5F53\u524D\u6A21\u677F\u4E0D\u4F9D\u8D56\u5BA1\u6279\u6D41\uFF0C\u53EF\u5FFD\u7565"},preview_runtime:{status:args.env==="preview"?args.statusPayload.runtime.preview.preview_url?"ready":"warning":args.statusPayload.runtime.prod.source_version_id?"ready":"warning",detail:args.env==="preview"?args.statusPayload.runtime.preview.preview_url??"\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u4E91\u7AEF Preview \u5730\u5740":args.statusPayload.runtime.prod.source_version_id??"\u5F53\u524D\u6CA1\u6709\u4E91\u7AEF Prod \u90E8\u7F72\u7248\u672C"},source_version:{status:args.statusPayload.app.latest_source_version_id?"ready":"warning",detail:args.statusPayload.app.latest_source_version_id??"\u5F53\u524D\u5E94\u7528\u8FD8\u6CA1\u6709\u63D0\u4EA4\u8FC7\u6E90\u7801\u7248\u672C"},source_context:{status:args.sourceContextPath?"ready":"warning",detail:args.sourceContextPath?`\u5DF2\u8BB0\u5F55\u6E90\u7801\u4E0A\u4E0B\u6587 (${args.sourceContextPath})`:"\u5F53\u524D\u76EE\u5F55\u672A\u68C0\u6D4B\u5230 `.platform/source-context.json`"}},recommendations=[];return args.bindingPath||recommendations.push("\u5148\u6267\u884C `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>`\uFF0C\u6216\u5728\u73B0\u6709\u76EE\u5F55\u6267\u884C `platform link --tenant <tenant-id> --app <app-id> --env preview`\u3002"),args.statusPayload.app.latest_source_version_id||recommendations.push('\u6267\u884C `platform app submit --message "initial iteration"` \u751F\u6210\u9996\u4E2A\u6E90\u7801\u7248\u672C\u3002'),args.statusPayload.auth.enabled&&authEnv?.status!=="ready"&&recommendations.push(`\u6267\u884C \`platform auth inspect\` \u786E\u8BA4 ${args.env} \u73AF\u5883\u7F3A\u5931\u7684\u8FD0\u884C\u65F6\u7ED1\u5B9A\uFF0C\u518D\u6839\u636E\u7ED3\u679C\u6267\u884C \`platform resources apply --env `+args.env+"`\u3002"),args.statusPayload.db.bound?typeof dbTablesCount=="number"&&dbTablesCount===0&&recommendations.push("\u5F53\u524D DB \u5DF2\u7ED1\u5B9A\uFF0C\u4F46 schema \u4ECD\u4E3A 0 \u8868\u3002\u82E5\u4F60\u8BA1\u5212\u63A5\u5165\u4E1A\u52A1 DB\uFF0C\u8BF7\u5148\u628A `resources/db/migrations/` \u91CC\u7684\u7A7A scaffold \u6539\u6210\u771F\u5B9E migration\uFF0C\u518D\u6267\u884C `platform db migrate`\u3001`platform db tables`\u3002"):recommendations.push("\u5982\u679C\u5F53\u524D app \u9700\u8981 DB\uFF0C\u518D\u6267\u884C `platform resources apply --env "+args.env+"`\uFF0C\u8BA9 DB \u7ED1\u5B9A\u548C\u8FC1\u79FB\u843D\u5230\u76EE\u6807\u73AF\u5883\u3002"),args.statusPayload.workflow.active_definition_count===0?recommendations.push("\u5982\u679C\u5F53\u524D app \u4F9D\u8D56\u5BA1\u6279\u6D41\uFF0C\u518D\u6267\u884C `platform workflow definition create ...` \u4E0E `platform workflow binding update ...`\u3002"):args.statusPayload.workflow.binding_count===0&&recommendations.push("Workflow definition \u5DF2\u5B58\u5728\uFF0C\u4F46\u7F3A\u5C11 app \u7EA7 binding\uFF1B\u8865\u6267\u884C `platform workflow binding update ...`\u3002"),args.env==="preview"&&!args.statusPayload.runtime.preview.preview_url&&recommendations.push("\u6267\u884C `platform preview generate` \u751F\u6210\u4E91\u7AEF Preview\uFF1B\u8FD9\u4E00\u6B65\u4E0D\u540C\u4E8E\u672C\u5730 `platform dev` \u9884\u89C8\u3002"),args.env==="prod"&&!args.statusPayload.runtime.prod.source_version_id&&recommendations.push("\u4E91\u7AEF Prod \u4E0D\u4F1A\u968F\u7740 Preview \u81EA\u52A8\u66F4\u65B0\uFF1B\u5982\u9700\u4E0A\u7EBF\u6B63\u5F0F\u73AF\u5883\uFF0C\u8BF7\u6267\u884C `platform publish set --source-version <srcver> --status published`\u3002"),recommendations.length===0&&recommendations.push(args.env==="prod"?"\u63A7\u5236\u9762\u89C6\u89D2\u4E0B\u5F53\u524D prod \u5DF2\u57FA\u672C ready\uFF1B\u540E\u7EED\u82E5\u8981\u5207\u6362\u6B63\u5F0F\u7248\u672C\uFF0C\u8BF7\u7EE7\u7EED\u4F7F\u7528 `platform publish`\u3002":"\u63A7\u5236\u9762\u89C6\u89D2\u4E0B\u5F53\u524D\u5E94\u7528\u5DF2\u57FA\u672C ready\uFF1B\u4E0B\u4E00\u6B65\u53EF\u76F4\u63A5\u505A\u9875\u9762\u8054\u8C03\u6216\u8FD0\u884C\u65F6\u9A8C\u8BC1\u3002"),{tenant_id:args.tenantId,app_id:args.appId,env:args.env,checks,recommendations}}function findDevPreviewTimelineItem(items,target){return items.find(item=>item.env==="preview"&&target.deploymentId&&item.deployment_id===target.deploymentId)??items.find(item=>item.env==="preview"&&target.releaseId&&item.release_id===target.releaseId)??items.find(item=>item.env==="preview"&&item.is_current_release)??null}function formatDevPreviewLines(args){let lines=[args.title,`tenant/app: ${args.tenantId}/${args.appId}`,`source version: ${args.sourceVersionId??"-"}`,`build: ${args.buildId??"-"}`,`release: ${args.releaseId??"-"}`,`deployment: ${args.deploymentId??"-"}`];return args.previewUrl&&lines.push(`preview url: ${args.previewUrl}`),args.health&&lines.push(`health: ${args.health}`),args.healthCheckUrl&&lines.push(`health_check_url: ${args.healthCheckUrl}`),args.message&&lines.push(`message: ${args.message}`),args.failureReason&&lines.push(`failure_reason: ${args.failureReason}`),args.diagnosticUrl&&lines.push(`diagnostic_url: ${args.diagnosticUrl}`),lines}function createTenantScopedSdk(credentials,tenantId,options={}){if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");return createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:options.capability,requestClass:options.requestClass??"control"})}async function loadRemoteDbRuntimeBindings(binding,requestedBindings){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)return{values:{},cleanup:null};let env=binding.env==="prod"?"prod":"preview",sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId:binding.tenant_id,capability:"db",requestClass:"control"}),result=await sdk.resolveDevRuntimeBindings({app_id:binding.app_id,env,requested_bindings:requestedBindings});if(result.mode==="unavailable")throw new Error([result.message??"\u5F53\u524D\u73AF\u5883\u5C1A\u672A\u63D0\u4F9B\u5F00\u53D1\u673A\u53EF\u8FBE\u7684 DB binding\u3002",result.remediation,result.request_id?`request_id: ${result.request_id}`:void 0].filter(item=>!!(item&&item.trim().length>0)).join(`
|
|
2748
|
-
`));return{values:result.values,cleanup:result.session_id?async()=>{try{await sdk.revokeDevRuntimeBindings({app_id:binding.app_id,env,session_id:result.session_id})}catch{}}:null}}function resolveRequestedRemoteBindings(args,startDir=process7.cwd()){let explicitValue=readOption2(args,"remote-bindings")?.trim().toLowerCase();if(!explicitValue||explicitValue==="auto")return{capabilities:detectRequestedRemoteBindings(startDir),mode:"auto"};if(explicitValue==="db")return{capabilities:["db"],mode:"db"};throw new Error("`platform dev --remote-bindings` \u76EE\u524D\u4EC5\u652F\u6301 `auto` \u6216 `db`\u3002")}function printCredentialsHelp(){process7.stdout.write(["platform credentials","","\u7528\u6CD5\uFF1A"," platform credentials migrate [--json]","","\u8BF4\u660E\uFF1A"," \u5C06\u65E7 credentials.json \u8FC1\u79FB\u5230
|
|
2746
|
+
`));return{values:result.values,cleanup:result.session_id?async()=>{try{await sdk.revokeDevRuntimeBindings({app_id:binding.app_id,env,session_id:result.session_id})}catch{}}:null}}function resolveRequestedRemoteBindings(args,startDir=process7.cwd()){let explicitValue=readOption2(args,"remote-bindings")?.trim().toLowerCase();if(!explicitValue||explicitValue==="auto")return{capabilities:detectRequestedRemoteBindings(startDir),mode:"auto"};if(explicitValue==="db")return{capabilities:["db"],mode:"db"};throw new Error("`platform dev --remote-bindings` \u76EE\u524D\u4EC5\u652F\u6301 `auto` \u6216 `db`\u3002")}function printCredentialsHelp(){process7.stdout.write(["platform credentials","","\u7528\u6CD5\uFF1A"," platform credentials migrate [--json]","","\u8BF4\u660E\uFF1A"," Windows \u5C06\u65E7 credentials.json \u8FC1\u79FB\u5230\u5F53\u524D\u7528\u6237 DPAPI\uFF1BmacOS \u53EF\u51C0\u5316\u65E7\u6587\u4EF6\u4E2D\u7684 PAT \u4EA4\u6362\u5B57\u6BB5\u3002"," \u53EA\u6709\u5B89\u5168\u5B58\u50A8\u5199\u5165\u5E76\u56DE\u8BFB\u6821\u9A8C\u6210\u529F\u540E\u624D\u5220\u9664\u65E7\u660E\u6587\u6587\u4EF6\u3002"," \u8FC1\u79FB\u5931\u8D25\u4F1A\u4FDD\u7559\u539F\u767B\u5F55\u6001\uFF0C\u5E76\u7ED9\u51FA\u660E\u786E\u63D0\u793A\u3002",""].join(`
|
|
2749
2747
|
`))}async function runCredentials(args){let subcommand=args.rest[0]??"help";if(hasFlag2(args,"help")||hasFlag2(args,"h")||subcommand==="help"){printCredentialsHelp();return}if(subcommand!=="migrate")throw printCredentialsHelp(),new Error(`\u672A\u77E5 credentials \u5B50\u547D\u4EE4: ${subcommand}`);let result=migrateStoredCredentials(),output={status:result.status,backend:result.backend,legacy_deleted:result.legacyDeleted,warnings:result.warnings};hasFlag2(args,"json")?process7.stdout.write(`${JSON.stringify(output,null,2)}
|
|
2750
2748
|
`):result.status==="migrated"?process7.stdout.write(`\u51ED\u636E\u8FC1\u79FB\u5B8C\u6210\u3002
|
|
2751
2749
|
\u5B58\u50A8\u540E\u7AEF: ${result.backend}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voobase/cli",
|
|
3
|
-
"version": "0.1.1-nonprod.
|
|
3
|
+
"version": "0.1.1-nonprod.2073",
|
|
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.
|
|
60
|
-
"sequence":
|
|
61
|
-
"gitSha": "
|
|
62
|
-
"fullGitSha": "
|
|
63
|
-
"buildId": "0.1.1-nonprod.
|
|
59
|
+
"version": "0.1.1-nonprod.2073",
|
|
60
|
+
"sequence": 2073,
|
|
61
|
+
"gitSha": "a773879",
|
|
62
|
+
"fullGitSha": "a773879666d11a1a36137354066b0cdb95419b79",
|
|
63
|
+
"buildId": "0.1.1-nonprod.2073+a773879"
|
|
64
64
|
}
|
|
65
65
|
}
|