@voobase/cli 0.1.0 → 0.1.1-nonprod.2019

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.
Files changed (2) hide show
  1. package/dist-bundle/index.mjs +72 -69
  2. package/package.json +20 -17
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __commonJS=(cb,mod)=>function(){return mod||(0,cb[__getOwnPropNames(cb)[0]])((mod={exports:{}}).exports,mod),mod.exports};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod));var require_punycode=__commonJS({"../../node_modules/.pnpm/punycode.js@2.3.1/node_modules/punycode.js/punycode.js"(exports,module){"use strict";var regexPunycode=/^xn--/,regexNonASCII=/[^\0-\x7F]/,regexSeparators=/[\x2E\u3002\uFF0E\uFF61]/g,errors={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},baseMinusTMin=35,floor=Math.floor,stringFromCharCode=String.fromCharCode;function error(type){throw new RangeError(errors[type])}function map(array,callback){let result=[],length=array.length;for(;length--;)result[length]=callback(array[length]);return result}function mapDomain(domain,callback){let parts=domain.split("@"),result="";parts.length>1&&(result=parts[0]+"@",domain=parts[1]),domain=domain.replace(regexSeparators,".");let labels=domain.split("."),encoded=map(labels,callback).join(".");return result+encoded}function ucs2decode(string){let output=[],counter=0,length=string.length;for(;counter<length;){let value=string.charCodeAt(counter++);if(value>=55296&&value<=56319&&counter<length){let extra=string.charCodeAt(counter++);(extra&64512)==56320?output.push(((value&1023)<<10)+(extra&1023)+65536):(output.push(value),counter--)}else output.push(value)}return output}var ucs2encode=codePoints=>String.fromCodePoint(...codePoints),basicToDigit=function(codePoint){return codePoint>=48&&codePoint<58?26+(codePoint-48):codePoint>=65&&codePoint<91?codePoint-65:codePoint>=97&&codePoint<123?codePoint-97:36},digitToBasic=function(digit,flag){return digit+22+75*(digit<26)-((flag!=0)<<5)},adapt=function(delta,numPoints,firstTime){let k=0;for(delta=firstTime?floor(delta/700):delta>>1,delta+=floor(delta/numPoints);delta>baseMinusTMin*26>>1;k+=36)delta=floor(delta/baseMinusTMin);return floor(k+(baseMinusTMin+1)*delta/(delta+38))},decode2=function(input){let output=[],inputLength=input.length,i=0,n=128,bias=72,basic=input.lastIndexOf("-");basic<0&&(basic=0);for(let j=0;j<basic;++j)input.charCodeAt(j)>=128&&error("not-basic"),output.push(input.charCodeAt(j));for(let index=basic>0?basic+1:0;index<inputLength;){let oldi=i;for(let w=1,k=36;;k+=36){index>=inputLength&&error("invalid-input");let digit=basicToDigit(input.charCodeAt(index++));digit>=36&&error("invalid-input"),digit>floor((2147483647-i)/w)&&error("overflow"),i+=digit*w;let t=k<=bias?1:k>=bias+26?26:k-bias;if(digit<t)break;let baseMinusT=36-t;w>floor(2147483647/baseMinusT)&&error("overflow"),w*=baseMinusT}let out=output.length+1;bias=adapt(i-oldi,out,oldi==0),floor(i/out)>2147483647-n&&error("overflow"),n+=floor(i/out),i%=out,output.splice(i++,0,n)}return String.fromCodePoint(...output)},encode2=function(input){let output=[];input=ucs2decode(input);let inputLength=input.length,n=128,delta=0,bias=72;for(let currentValue of input)currentValue<128&&output.push(stringFromCharCode(currentValue));let basicLength=output.length,handledCPCount=basicLength;for(basicLength&&output.push("-");handledCPCount<inputLength;){let m=2147483647;for(let currentValue of input)currentValue>=n&&currentValue<m&&(m=currentValue);let handledCPCountPlusOne=handledCPCount+1;m-n>floor((2147483647-delta)/handledCPCountPlusOne)&&error("overflow"),delta+=(m-n)*handledCPCountPlusOne,n=m;for(let currentValue of input)if(currentValue<n&&++delta>2147483647&&error("overflow"),currentValue===n){let q=delta;for(let k=36;;k+=36){let t=k<=bias?1:k>=bias+26?26:k-bias;if(q<t)break;let qMinusT=q-t,baseMinusT=36-t;output.push(stringFromCharCode(digitToBasic(t+qMinusT%baseMinusT,0))),q=floor(qMinusT/baseMinusT)}output.push(stringFromCharCode(digitToBasic(q,0))),bias=adapt(delta,handledCPCountPlusOne,handledCPCount===basicLength),delta=0,++handledCPCount}++delta,++n}return output.join("")},toUnicode=function(input){return mapDomain(input,function(string){return regexPunycode.test(string)?decode2(string.slice(4).toLowerCase()):string})},toASCII=function(input){return mapDomain(input,function(string){return regexNonASCII.test(string)?"xn--"+encode2(string):string})},punycode2={version:"2.3.1",ucs2:{decode:ucs2decode,encode:ucs2encode},decode:decode2,encode:encode2,toASCII,toUnicode};module.exports=punycode2}});import{spawn as spawn8}from"node:child_process";import{existsSync as existsSync24,readFileSync as readFileSync26}from"node:fs";import process7 from"node:process";async function batchUpdateTenantCmsItems(args){let collection=args.payload.collection.trim(),itemIds=Array.from(new Set(args.payload.item_ids.map(itemId=>itemId.trim()).filter(Boolean))),tagAdds=dedupeTags(args.payload.changes.tags.add),discover=await args.sdk.discoverTenantCmsCollection(collection),schemaSpec=discover.active_schema??discover.draft_schema;if(!schemaSpec)throw new Error(`Collection \`${collection}\` \u5F53\u524D\u6CA1\u6709\u53EF\u7528 schema\u3002`);let succeeded=[],failed=[];for(let itemId of itemIds){let title=itemId;try{let item=await args.sdk.getTenantCmsItem({collection,id:itemId});title=resolveCmsItemTitle(item);let currentStatus=item.system.publish_status??"draft",targetStatus=args.payload.changes.publish_status.mode==="set"?args.payload.changes.publish_status.value:void 0,hasCategoryChange=args.payload.changes.category.mode!=="keep",hasTagChange=tagAdds.length>0,hasMetadataChange=hasCategoryChange||hasTagChange,effectiveStatus=currentStatus;if(hasMetadataChange){currentStatus==="archived"&&targetStatus&&targetStatus!=="archived"&&(await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:targetStatus}),effectiveStatus=targetStatus);let payload=buildCmsItemWritePayloadFromDelivery({item,schemaSpec,publishStatus:targetStatus&&targetStatus!=="archived"?targetStatus:effectiveStatus,categoryChange:args.payload.changes.category,tagsToAdd:tagAdds});await args.sdk.configureTenantCmsItem({...payload,item_id:itemId}),targetStatus==="archived"&&effectiveStatus!=="archived"?await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:"archived"}):targetStatus&&targetStatus!=="archived"&&(effectiveStatus=targetStatus)}else targetStatus&&targetStatus!==effectiveStatus&&await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:targetStatus});succeeded.push({item_id:itemId,title})}catch(error){failed.push({item_id:itemId,title,message:error instanceof Error?error.message:"\u6279\u91CF\u66F4\u65B0\u5931\u8D25"})}}return{total:itemIds.length,succeeded,failed}}function buildCmsItemWritePayloadFromDelivery(args){let nextTags=dedupeTags([...args.item.system.tags??[],...args.tagsToAdd]);return{collection:args.item.collection,system:{publish_status:args.publishStatus,...args.item.system.slug?{slug:args.item.system.slug}:{},featured:args.item.system.featured??!1,tags:nextTags,category_id:resolveNextCategoryId(args.item,args.categoryChange),...args.item.system.content_format?{content_format:args.item.system.content_format}:{},...args.item.system.source?{source:{...args.item.system.source}}:{}},content:normalizeCmsContentForWrite(args.item.content,args.schemaSpec.fields)}}function resolveNextCategoryId(item,categoryChange){return categoryChange.mode==="clear"?null:categoryChange.mode==="set"?categoryChange.category_id?.trim()||null:item.system.category_id??null}function resolveCmsItemTitle(item){let title=item.content.title,name=item.content.name;return typeof title=="string"&&title.trim()?title.trim():typeof name=="string"&&name.trim()?name.trim():item.system.slug??item.system.id??"Untitled item"}function dedupeTags(values){let seen=new Set,next=[];for(let value of values){let normalized=value.trim();if(!normalized)continue;let lowered=normalized.toLowerCase();seen.has(lowered)||(seen.add(lowered),next.push(normalized))}return next}function normalizeCmsContentForWrite(content,fields){let normalized={};for(let field of fields)normalized[field.name]=normalizeFieldValueForPayload(field,content[field.name]);return normalized}function normalizeFieldValueForPayload(field,value){switch(field.type){case"date":if(typeof value=="string"){let normalized=value.trim();return normalized.length>0?normalized:null}return value??null;case"number":if(typeof value=="string"){let parsed=Number.parseFloat(value.trim());return Number.isFinite(parsed)?field.ui?.number_kind==="integer"?Math.trunc(parsed):parsed:0}return value;case"bool":return!!value;case"multi_select":return normalizeStringArrayValue(value);case"image":case"file":return normalizeAssetValue(value);case"images":case"files":return normalizeAssetArrayValue(value);case"relation":return normalizeRelationId(value);case"relations":return normalizeRelationArrayValue(value);default:return typeof value=="string"?value:value??""}}function normalizeRelationId(value){if(typeof value=="string"){let normalized=value.trim();return normalized.length>0?normalized:null}if(value&&typeof value=="object"&&!Array.isArray(value)&&"id"in value){let id=value.id;return typeof id=="string"&&id.trim().length>0?id.trim():null}return null}function normalizeAssetValue(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:null}function normalizeStringArrayValue(value){return Array.isArray(value)?value.map(item=>String(item)):typeof value=="string"?value.split(",").map(item=>item.trim()).filter(Boolean):[]}function normalizeAssetArrayValue(value){return Array.isArray(value)?value.filter(item=>!!item&&typeof item=="object"&&!Array.isArray(item)):[]}function normalizeRelationArrayValue(value){return Array.isArray(value)?value.map(item=>normalizeRelationId(item)).filter(item=>!!item):[]}import{createHash}from"node:crypto";import{URL as URL2}from"node:url";var IMAGE_URL_ATTRS=["src","data-src","data-original","data-original-src","data-lazy-src"],IMAGE_SRCSET_ATTRS=["srcset","data-srcset"];function trimToUndefined(value){let normalized=value?.trim();return normalized||void 0}function normalizeUrl(value,baseUrl){let trimmed=trimToUndefined(value);if(trimmed)try{return baseUrl?new URL2(trimmed,baseUrl).toString():new URL2(trimmed).toString()}catch{return}}function isPlatformHostedAssetUrl(value){try{let parsed=new URL2(value);return/^\/assets\/[^/]+\/(original|variants\/[^/]+)$/.test(parsed.pathname)||parsed.pathname.startsWith("/api/tenant/assets/")}catch{return!1}}function inferMimeTypeFromUrl(value){if(!value)return;let pathname=(()=>{try{return new URL2(value).pathname.toLowerCase()}catch{return value.toLowerCase()}})();if(pathname.endsWith(".png"))return"image/png";if(pathname.endsWith(".webp"))return"image/webp";if(pathname.endsWith(".gif"))return"image/gif";if(pathname.endsWith(".svg"))return"image/svg+xml";if(pathname.endsWith(".jpg")||pathname.endsWith(".jpeg"))return"image/jpeg";if(pathname.endsWith(".avif"))return"image/avif"}function computeChecksum(content){return`sha256:${createHash("sha256").update(content).digest("hex")}`}function inferRemoteImageFileName(url,mimeType){let lastSegment=(()=>{try{return new URL2(url).pathname}catch{return url}})().split("/").filter(Boolean).at(-1);return lastSegment&&/\.[a-z0-9]{2,6}$/i.test(lastSegment)?decodeURIComponent(lastSegment):`remote-image.${(()=>{switch(mimeType){case"image/png":return"png";case"image/webp":return"webp";case"image/gif":return"gif";case"image/svg+xml":return"svg";case"image/avif":return"avif";case"image/jpeg":default:return"jpg"}})()}`}function buildTenantAssetReference(asset){return{asset_id:asset.asset.asset_id,title:asset.asset.title,media_type:asset.asset.media_type,mime_type:asset.asset.mime_type,size_bytes:asset.original_file.size_bytes,folder_id:asset.asset.folder_id,original_url:asset.original_url,variant_urls:asset.variant_urls}}function replaceImageAttributeUrls(html,replacementsByUrl,attribute2){let pattern=new RegExp(`(<img\\b[^>]*?\\s${attribute2}\\s*=\\s*)(["'])(.*?)\\2`,"gi");return html.replace(pattern,(fullMatch,prefix,quote,rawUrl)=>{let replacement=replacementsByUrl.get(rawUrl);return!replacement||replacement.finalUrl===rawUrl?fullMatch:`${prefix}${quote}${replacement.finalUrl}${quote}`})}function stripImageAttributes(html,attributes){let nextHtml=html;for(let attribute2 of attributes){let pattern=new RegExp(`\\s${attribute2}\\s*=\\s*(["']).*?\\1`,"gi");nextHtml=nextHtml.replace(pattern,"")}return nextHtml}async function fetchRemoteImageBinary(args){let response=await(args.fetchImpl??fetch)(args.url,{headers:{accept:"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"}});if(!response.ok)throw new Error(`\u56FE\u7247\u62C9\u53D6\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`);let normalizedMimeType=String(response.headers.get("content-type")??"").split(";")[0]?.trim().toLowerCase()||inferMimeTypeFromUrl(args.url);if(!normalizedMimeType||!normalizedMimeType.startsWith("image/"))throw new Error("\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u53D7\u652F\u6301\u7684\u56FE\u7247\u7C7B\u578B");let content=new Uint8Array(await response.arrayBuffer()),maxBytes=args.maxBytes??20*1024*1024;if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");if(content.byteLength>maxBytes)throw new Error(`\u8FDC\u7A0B\u56FE\u7247\u8D85\u8FC7\u5927\u5C0F\u9650\u5236\uFF08${content.byteLength} bytes\uFF09`);return{content,mimeType:normalizedMimeType}}async function ingestRemoteImageCandidates(args){let uniqueCandidates=new Map;for(let candidate of args.candidates)uniqueCandidates.has(candidate.url)||uniqueCandidates.set(candidate.url,candidate);let resultsByUrl=new Map,resultsByChecksum=new Map,warnings=[];for(let candidate of uniqueCandidates.values())try{let{content,mimeType}=await fetchRemoteImageBinary({url:candidate.url,fetchImpl:args.fetchImpl,maxBytes:args.maxBytes}),checksum3=computeChecksum(content),existingByChecksum=resultsByChecksum.get(checksum3);if(existingByChecksum){let reused={...existingByChecksum,originalUrl:candidate.url,status:"reused"};resultsByUrl.set(candidate.url,reused);continue}let fileName=inferRemoteImageFileName(candidate.url,mimeType),uploadedAsset=await args.sdk.createTenantAssetBinary({fileName,mimeType,content,title:candidate.title,...args.folderId?{folderId:args.folderId}:{}}),uploaded={originalUrl:candidate.url,finalUrl:uploadedAsset.original_url,asset:uploadedAsset,assetReference:buildTenantAssetReference(uploadedAsset),mimeType,checksum:checksum3,status:"uploaded"};resultsByUrl.set(candidate.url,uploaded),resultsByChecksum.set(checksum3,uploaded)}catch(error){let message=error instanceof Error?error.message:"\u5916\u94FE\u56FE\u7247\u8D44\u4EA7\u5316\u5931\u8D25";warnings.push(`\u56FE\u7247 \`${candidate.url}\` \u8D44\u4EA7\u5316\u5931\u8D25\uFF0C\u5DF2\u56DE\u9000\u539F\u94FE\u63A5\uFF1A${message}`),resultsByUrl.set(candidate.url,{originalUrl:candidate.url,finalUrl:candidate.url,mimeType:inferMimeTypeFromUrl(candidate.url),status:"fallback",warning:message})}return{resultsByUrl,warnings}}function collectExternalImageCandidatesFromHtml(args){let candidates=new Map;return args.html.replace(/<img\b[^>]*>/gi,tag=>{for(let attribute2 of IMAGE_URL_ATTRS){let rawUrl=tag.match(new RegExp(`(?:^|\\s)${attribute2}\\s*=\\s*(["'])(.*?)\\1`,"i"))?.[2],normalizedUrl=normalizeUrl(rawUrl,args.baseUrl);!normalizedUrl||normalizedUrl.startsWith("data:")||isPlatformHostedAssetUrl(normalizedUrl)||candidates.has(normalizedUrl)||candidates.set(normalizedUrl,{url:normalizedUrl,title:args.title,source:"body"})}return""}),[...candidates.values()]}async function assetizeExternalImagesInHtml(args){let bodyCandidates=collectExternalImageCandidatesFromHtml({html:args.html,baseUrl:args.baseUrl,title:args.bodyTitle}),normalizedCoverUrl=normalizeUrl(args.coverUrl,args.baseUrl),coverCandidate=normalizedCoverUrl&&!normalizedCoverUrl.startsWith("data:")&&!isPlatformHostedAssetUrl(normalizedCoverUrl)?{url:normalizedCoverUrl,title:args.coverTitle??args.bodyTitle,source:"cover"}:null,candidates=coverCandidate?[coverCandidate,...bodyCandidates]:bodyCandidates,{resultsByUrl,warnings}=await ingestRemoteImageCandidates({sdk:args.sdk,candidates,folderId:args.folderId,fetchImpl:args.fetchImpl,maxBytes:args.maxBytes}),html=args.html;for(let attribute2 of IMAGE_URL_ATTRS)html=replaceImageAttributeUrls(html,resultsByUrl,attribute2);html=stripImageAttributes(html,IMAGE_SRCSET_ATTRS);let replacements=[...resultsByUrl.values()].map(result=>({originalUrl:result.originalUrl,finalUrl:result.finalUrl,...result.asset?.asset.asset_id?{assetId:result.asset.asset.asset_id}:{},status:result.status}));if(!normalizedCoverUrl)return{html,cover:{mode:"none"},replacements,warnings};let coverResult=resultsByUrl.get(normalizedCoverUrl);return coverResult?.assetReference?{html,cover:{mode:"asset",value:coverResult.assetReference},replacements,warnings}:{html,cover:{mode:"remote",value:{title:args.coverTitle??args.bodyTitle??"Remote cover",...coverResult?.mimeType||args.coverMimeType?{mime_type:coverResult?.mimeType??args.coverMimeType}:{},original_url:normalizedCoverUrl}},replacements,warnings}}var PlatformApiError=class extends Error{status;code;detail;requestId;capability;category;remediation;constructor(message,status,code2,detail,requestId,capability,category,remediation){super(message),this.status=status,this.code=code2,this.detail=detail,this.requestId=requestId,this.capability=capability,this.category=category,this.remediation=remediation,this.name="PlatformApiError"}},BasePlatformSdk=class{options;fetchImpl;constructor(options){this.options=options,this.fetchImpl=options.fetchImpl??fetch}async request(path,init={}){return this.requestUrl(new URL(path,this.options.baseUrl),init)}async requestBinary(path,init={}){return this.requestBinaryUrl(new URL(path,this.options.baseUrl),init)}async requestVoid(path,init={}){return this.requestVoidUrl(new URL(path,this.options.baseUrl),init)}async requestUrl(url,init={}){let response=await this.fetchResponse(url,init),payload=await parseJsonResponse(response);if(!response.ok){let errorPayload=payload,error=errorPayload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??errorPayload.detail,errorPayload.request_id,error?.capability,error?.category,error?.remediation)}return payload}async requestBinaryUrl(url,init={}){let response=await this.fetchResponse(url,init);if(!response.ok){let payload=await parseJsonResponse(response),error=payload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??payload.detail,payload.request_id,error?.capability,error?.category,error?.remediation)}return new Uint8Array(await response.arrayBuffer())}async requestVoidUrl(url,init={}){let response=await this.fetchResponse(url,init);if(!response.ok){let payload=await parseJsonResponse(response),error=payload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??payload.detail,payload.request_id,error?.capability,error?.category,error?.remediation)}}async fetchResponse(url,init={}){let headers=new Headers(init.headers);!headers.has("Content-Type")&&init.body&&headers.set("Content-Type","application/json");let extraHeaders=await this.options.getHeaders?.();return extraHeaders&&new Headers(extraHeaders).forEach((value,key)=>{headers.set(key,value)}),this.fetchImpl(url,{...init,headers})}};async function parseJsonResponse(response){let text2=await response.text();if(text2.trim().length===0)return{};try{return JSON.parse(text2)}catch{if(response.ok)return{};throw new PlatformApiError(`Request failed with non-JSON response: ${response.status}`,response.status,"non_json_response",{content_type:response.headers.get("content-type")??void 0,body_preview:text2.replace(/\s+/g," ").slice(0,240)})}}var PlatformSdk=class extends BasePlatformSdk{notification;constructor(options){super(options),this.notification=new NotificationSdkNamespace(this)}async listNotificationInbox(filters={}){let url=new URL("/api/tenant/notification/inbox",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"inbox_type",filters.inbox_type),setOptionalSearchParam(url,"status",filters.status),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async updateNotificationInboxItemStatus(itemId,payload){return(await this.request(`/api/tenant/notification/inbox/${encodeURIComponent(itemId)}`,{method:"PATCH",body:JSON.stringify(payload)})).item}async batchUpdateNotificationInboxItemsStatus(payload){return this.request("/api/tenant/notification/inbox:batch",{method:"PATCH",body:JSON.stringify(payload)})}async listNotificationDeliveries(filters={}){let url=new URL("/api/tenant/notification/deliveries",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async announcePlatformNotification(payload){return(await this.request("/api/admin/notification/announcements/platform",{method:"POST",body:JSON.stringify(payload)})).item}async announceAppNotification(appId,payload){return(await this.request(`/api/tenant/notification/apps/${encodeURIComponent(appId)}/announcements`,{method:"POST",body:JSON.stringify(payload)})).item}async getAppNotificationConfig(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/config`)}async listAppNotificationAnnouncements(appId,options={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements`,this.options.baseUrl);return typeof options.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async createAppNotificationAnnouncement(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements`,{method:"POST",body:JSON.stringify(payload)})}async archiveAppNotificationAnnouncement(appId,announcementId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements/${encodeURIComponent(announcementId)}:archive`,{method:"POST"})}async publishEndUserNotification(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/publish`,{method:"POST",body:JSON.stringify(payload)})}async createEndUserNotificationReminder(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/reminders`,{method:"POST",body:JSON.stringify(payload)})}async projectEndUserTaskNotification(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/task-projections`,{method:"POST",body:JSON.stringify(payload)})}async listEndUserNotificationInbox(appId,query){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/inbox`,this.options.baseUrl);return url.searchParams.set("end_user_id",query.end_user_id),setOptionalSearchParam(url,"status",query.status),setOptionalSearchParam(url,"inbox_type",query.inbox_type),typeof query.limit=="number"&&Number.isFinite(query.limit)&&url.searchParams.set("limit",String(query.limit)),this.request(`${url.pathname}${url.search}`)}async getEndUserNotificationUnreadCount(appId,endUserId){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/unread-count`,this.options.baseUrl);return url.searchParams.set("end_user_id",endUserId),this.request(`${url.pathname}${url.search}`)}async createWorkflowDefinition(payload){return(await this.request("/api/workflow/definitions",{method:"POST",body:JSON.stringify(payload)})).item}async listWorkflowTemplates(){return(await this.request("/api/workflow/templates")).items}async listWorkflowDefinitions(filters={}){let url=new URL("/api/workflow/definitions",this.options.baseUrl);return setOptionalSearchParam(url,"target_id",filters.target_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async listWorkflowBindings(filters={}){let url=new URL("/api/workflow/bindings",this.options.baseUrl);return setOptionalSearchParam(url,"target_id",filters.target_id),setOptionalSearchParam(url,"definition_key",filters.definition_key),(await this.request(`${url.pathname}${url.search}`)).items}async updateWorkflowDefinitionMetadata(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}`,{method:"PATCH",body:JSON.stringify(payload)})).item}async saveWorkflowRoleBindings(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}/role-bindings`,{method:"POST",body:JSON.stringify(payload)})).items}async getWorkflowBindingOverride(args){let url=new URL(`/api/workflow/definitions/${encodeURIComponent(args.definition_key)}/binding-override`,this.options.baseUrl);return setOptionalSearchParam(url,"target_scope",args.target_scope),setOptionalSearchParam(url,"target_id",args.target_id),(await this.request(`${url.pathname}${url.search}`)).item}async saveWorkflowBindingOverride(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}/binding-override`,{method:"POST",body:JSON.stringify(payload)})).item}async listWorkflowRoleBindings(args){let url=new URL(`/api/workflow/definitions/${encodeURIComponent(args.definition_key)}/role-bindings`,this.options.baseUrl);return setOptionalSearchParam(url,"target_scope",args.target_scope),setOptionalSearchParam(url,"target_id",args.target_id),(await this.request(`${url.pathname}${url.search}`)).items}async startWorkflow(payload){return(await this.request("/api/workflow/instances/start",{method:"POST",body:JSON.stringify(payload)})).item}async performWorkflowAction(instanceId,payload){return(await this.request(`/api/workflow/instances/${encodeURIComponent(instanceId)}/actions`,{method:"POST",body:JSON.stringify(payload)})).item}async getWorkflowInstance(instanceId){return(await this.request(`/api/workflow/instances/${encodeURIComponent(instanceId)}`)).item}async listWorkflowTasks(filters={}){let url=new URL("/api/workflow/tasks",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async getWhoAmI(){return this.request("/api/auth/whoami")}async getResolvedPermissions(){return this.request("/api/auth/permissions")}async switchTenantContext(payload){return this.request("/api/auth/context/switch-tenant",{method:"POST",body:JSON.stringify(payload)})}async listTenantWorkspaces(){return this.request("/api/auth/workspaces")}async ensurePersonalWorkspace(){return this.request("/api/auth/workspaces/ensure-personal",{method:"POST"})}async getAdminOverview(){return this.request("/api/admin/overview")}async listAdminWorkbenchEntries(){return this.request("/api/admin/workbench-entries")}async getAdminWorkbenchEntryDetail(entryKey){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}`)}async updateAdminWorkbenchEntryVisibility(entryKey,payload){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility`,{method:"PUT",body:JSON.stringify(payload)})}async resetAdminWorkbenchEntryVisibility(entryKey){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility`,{method:"DELETE"})}async previewAdminWorkbenchEntryVisibility(entryKey,payload){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility:preview`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAsset(payload){return this.request("/api/tenant/assets",{method:"POST",body:JSON.stringify(payload)})}async createTenantAssetBinary(args){let headers=new Headers({"Content-Type":args.mimeType,"X-Asset-File-Name":encodeURIComponent(args.fileName)});return args.title?.trim()&&headers.set("X-Asset-Title",encodeURIComponent(args.title.trim())),args.folderId?.trim()&&headers.set("X-Asset-Folder-Id",encodeURIComponent(args.folderId.trim())),this.request("/api/tenant/assets/upload",{method:"POST",headers,body:Buffer.from(args.content)})}async listTenantAssets(filters={}){let url=new URL("/api/tenant/assets",this.options.baseUrl);return setOptionalSearchParam(url,"q",filters.q),setOptionalSearchParam(url,"media_type",filters.media_type),setOptionalSearchParam(url,"mime_type",filters.mime_type),setOptionalSearchParam(url,"folder_id",filters.folder_id),setOptionalSearchParam(url,"tag_ids",filters.tag_ids?.join(",")),setOptionalSearchParam(url,"scene",filters.scene),setOptionalSearchParam(url,"objects",filters.objects?.join(",")),setOptionalSearchParam(url,"safety_flags",filters.safety_flags?.join(",")),setOptionalSearchParam(url,"orientation",filters.orientation),setOptionalBooleanSearchParam(url,"has_ocr",filters.has_ocr),setOptionalBooleanSearchParam(url,"has_person",filters.has_person),setOptionalBooleanSearchParam(url,"is_svg",filters.is_svg),typeof filters.page=="number"&&Number.isFinite(filters.page)&&url.searchParams.set("page",String(filters.page)),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantAsset(assetId){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}`)}async deleteTenantAsset(assetId){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}`,{method:"DELETE"})}async batchUpdateTenantAssets(payload){return this.request("/api/tenant/assets/batch",{method:"POST",body:JSON.stringify(payload)})}async listTenantAssetFolders(){return this.request("/api/tenant/assets/folders")}async createTenantAssetFolder(payload){return this.request("/api/tenant/assets/folders",{method:"POST",body:JSON.stringify(payload)})}async updateTenantAssetFolderMetadata(folderId,payload){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteTenantAssetFolder(folderId){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}`,{method:"DELETE"})}async moveTenantAssetFolder(folderId,direction){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}/move-${direction}`,{method:"POST"})}async updateTenantAssetFolder(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/folder`,{method:"PATCH",body:JSON.stringify(payload)})}async updateTenantAssetMetadata(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/metadata`,{method:"PATCH",body:JSON.stringify(payload)})}async listTenantAssetTags(options){let url=new URL("/api/tenant/assets/tags",this.options.baseUrl);return options?.assetId&&url.searchParams.set("asset_id",options.assetId),this.request(`${url.pathname}${url.search}`)}async addTenantAssetTag(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/tags`,{method:"POST",body:JSON.stringify(payload)})}async removeTenantAssetTag(assetId,label){let url=new URL(`/api/tenant/assets/${encodeURIComponent(assetId)}/tags`,this.options.baseUrl);return url.searchParams.set("label",label),this.request(`${url.pathname}${url.search}`,{method:"DELETE"})}async downloadTenantAssetOriginal(assetId){return this.requestBinary(`/api/tenant/assets/${encodeURIComponent(assetId)}/original`)}async downloadTenantAssetVariant(assetId,variantKind){return this.requestBinary(`/assets/${encodeURIComponent(assetId)}/variants/${encodeURIComponent(variantKind)}`)}async createTenantBlobUploadSession(payload){return this.request("/api/tenant/blobs/upload-sessions",{method:"POST",body:JSON.stringify(payload)})}async uploadTenantBlobBinary(uploadSessionId,payload){let url=resolveRelativeOrAbsoluteUrl(payload.upload_url??`/api/tenant/blobs/upload-sessions/${encodeURIComponent(uploadSessionId)}/content`,this.options.baseUrl),headers=new Headers(payload.headers);headers.set("Content-Type",payload.content_type?.trim()||"application/octet-stream"),await this.requestVoidUrl(url,{method:"PUT",headers,body:Buffer.from(payload.content)})}async completeTenantBlobUpload(uploadSessionId,payload={}){return this.request(`/api/tenant/blobs/upload-sessions/${encodeURIComponent(uploadSessionId)}/complete`,{method:"POST",body:JSON.stringify(payload)})}async createTenantBlobBinary(args){let contentType=args.contentType?.trim()||"application/octet-stream",session=await this.createTenantBlobUploadSession({original_filename:args.fileName,content_type:contentType,size_bytes:args.content.byteLength,...args.appId?.trim()?{app_id:args.appId.trim()}:{},...args.clientRequestId?.trim()?{client_request_id:args.clientRequestId.trim()}:{}});return await this.uploadTenantBlobBinary(session.upload_session_id,{content:args.content,content_type:contentType,upload_url:session.upload_url,headers:session.headers}),this.completeTenantBlobUpload(session.upload_session_id,{size_bytes:args.content.byteLength,...args.sha256?.trim()?{sha256:args.sha256.trim()}:{}})}async listTenantBlobs(filters={}){let url=new URL("/api/tenant/blobs",this.options.baseUrl);return setOptionalSearchParam(url,"cursor",filters.cursor),setOptionalSearchParam(url,"app_id",filters.app_id??void 0),setOptionalSearchParam(url,"q",filters.q??void 0),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantBlob(blobId){return this.request(`/api/tenant/blobs/${encodeURIComponent(blobId)}`)}async issueTenantBlobDownloadUrl(blobId,payload={}){return this.request(`/api/tenant/blobs/${encodeURIComponent(blobId)}/download-url`,{method:"POST",body:JSON.stringify(payload)})}async getTenantOverview(){return this.request("/api/tenant/overview")}async getTenantEffectiveState(){return this.request("/api/tenant/effective-state")}async getTenantWorkbenchNavigation(){return this.request("/api/tenant/workbench/navigation")}async createTenantApp(payload){return this.request("/api/tenant/apps",{method:"POST",body:JSON.stringify(payload)})}async updateTenantApp(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async listAppTemplates(){return this.request("/api/tenant/app-templates")}async createAppTemplate(payload){return this.request("/api/tenant/app-templates",{method:"POST",body:JSON.stringify(payload)})}async getAppTemplate(templateId){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`)}async openAppTemplatePreview(templateId){return this.requestVoid(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/preview`)}async updateAppTemplateSettings(templateId,payload){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteAppTemplate(templateId,payload={}){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`,{method:"DELETE",body:JSON.stringify(payload)})}async createAppTemplateInitializationTask(templateId,payload){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/initialization-tasks`,{method:"POST",body:JSON.stringify(payload)})}async getAppTemplateInitializationTask(taskId){return this.request(`/api/tenant/app-template-initialization-tasks/${encodeURIComponent(taskId)}`)}async createAppMarketSubmission(templateId,payload={}){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/market-submissions`,{method:"POST",body:JSON.stringify(payload)})}async cancelAppMarketSubmission(submissionId){return this.request(`/api/tenant/app-market/submissions/${encodeURIComponent(submissionId)}/cancel`,{method:"POST"})}async listTenantAppMarketSubmissions(options){let url=new URL("/api/tenant/app-market/submissions",this.options.baseUrl);return options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async listAppMarketListings(options){let url=new URL("/api/tenant/app-market/listings",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.tag&&url.searchParams.set("tag",options.tag),this.request(`${url.pathname}${url.search}`)}async listAdminAppMarketListings(options){let url=new URL("/api/admin/app-market/listings",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.tag&&url.searchParams.set("tag",options.tag),this.request(`${url.pathname}${url.search}`)}async getAppMarketListing(listingId){return this.request(`/api/tenant/app-market/listings/${encodeURIComponent(listingId)}`)}async openAppMarketSubmissionPreview(submissionId){return this.requestVoid(`/api/tenant/app-market/submissions/${encodeURIComponent(submissionId)}/preview`)}async createAppMarketInstall(listingId,payload){return this.request(`/api/tenant/app-market/listings/${encodeURIComponent(listingId)}/installs`,{method:"POST",body:JSON.stringify(payload)})}async listAdminAppMarketSubmissions(options){let url=new URL("/api/admin/app-market/submissions",this.options.baseUrl);return options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async approveAppMarketSubmission(submissionId){return this.request(`/api/admin/app-market/submissions/${encodeURIComponent(submissionId)}/approve`,{method:"POST"})}async rejectAppMarketSubmission(submissionId,payload={}){return this.request(`/api/admin/app-market/submissions/${encodeURIComponent(submissionId)}/reject`,{method:"POST",body:JSON.stringify(payload)})}async unlistAppMarketListing(listingId,payload={}){return this.request(`/api/admin/app-market/listings/${encodeURIComponent(listingId)}/unlist`,{method:"POST",body:JSON.stringify(payload)})}async publishAppMarketListing(listingId,payload={}){return this.request(`/api/admin/app-market/listings/${encodeURIComponent(listingId)}/publish`,{method:"POST",body:JSON.stringify(payload)})}async listAdminLightAppLibraries(options){let url=new URL("/api/admin/light-app-library/libraries",this.options.baseUrl);return options?.visibility&&url.searchParams.set("visibility",options.visibility),this.request(`${url.pathname}${url.search}`)}async setAdminLightAppLibraryVisibility(libraryId,payload){return this.request(`/api/admin/light-app-library/libraries/${encodeURIComponent(libraryId)}/visibility`,{method:"POST",body:JSON.stringify(payload)})}async listLightAppLibraryEntries(options){let url=new URL("/api/tenant/light-app-library/entries",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.status&&url.searchParams.set("status",options.status),options?.template_key&&url.searchParams.set("template_key",options.template_key),options?.tag&&url.searchParams.set("tag",options.tag),options?.visibility&&url.searchParams.set("visibility",options.visibility),typeof options?.include_public=="boolean"&&url.searchParams.set("include_public",String(options.include_public)),this.request(`${url.pathname}${url.search}`)}async searchLightAppLibraryEntries(query){let url=new URL("/api/tenant/light-app-library/entries/search",this.options.baseUrl);return url.searchParams.set("query",query),this.request(`${url.pathname}${url.search}`)}async getLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`)}async createLightAppLibraryEntry(payload){return this.request("/api/tenant/light-app-library/entries",{method:"POST",body:JSON.stringify(payload)})}async updateLightAppLibraryEntry(entryId,payload){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async submitLightAppLibraryEntrySnapshot(entryId,payload){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/snapshots`,{method:"POST",body:JSON.stringify(payload)})}async publishLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/publish`,{method:"POST"})}async unpublishLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/unpublish`,{method:"POST"})}async archiveLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/archive`,{method:"POST"})}async deleteLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`,{method:"DELETE"})}async getLightAppLibraryEntrySource(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source`)}async readLightAppLibraryEntrySourceFile(entryId,path){let url=new URL(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source/files`,this.options.baseUrl);return url.searchParams.set("path",path),this.request(`${url.pathname}${url.search}`)}async searchLightAppLibraryEntrySource(entryId,query){let url=new URL(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source/search`,this.options.baseUrl);return url.searchParams.set("query",query),this.request(`${url.pathname}${url.search}`)}async listLightAppPrototypeEntries(options){let url=new URL("/api/tenant/prototypes",this.options.baseUrl);return options?.q&&url.searchParams.set("q",options.q),options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async getLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`)}async createLightAppPrototypeEntry(payload){return this.request("/api/tenant/prototypes",{method:"POST",body:JSON.stringify(payload)})}async updateLightAppPrototypeEntry(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async copyLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/copy`,{method:"POST"})}async deleteLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`,{method:"DELETE"})}async saveLightAppPrototypeCurrentVersion(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/current-version`,{method:"PUT",body:JSON.stringify(payload)})}async submitLightAppPrototypeVersion(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/versions`,{method:"POST",body:JSON.stringify(payload)})}async getLightAppPrototypeVersion(entryId,versionId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/versions/${encodeURIComponent(versionId)}`)}async deleteTenantApp(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}`,{method:"DELETE"})}async getTenantAppDeletePreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/delete-preview`,{method:"POST"})}async getTenantAppDeleteJob(jobId){return this.request(`/api/tenant/app-delete-jobs/${encodeURIComponent(jobId)}`)}async getTenantAppUndeployPreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/undeploy-preview`,{method:"POST"})}async undeployTenantApp(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/undeploy`,{method:"POST"})}async getTenantAppUndeployJob(jobId){return this.request(`/api/tenant/app-undeploy-jobs/${encodeURIComponent(jobId)}`)}async createBuild(payload){return this.request("/api/builds",{method:"POST",body:JSON.stringify(payload)})}async listBuilds(appId,options){let url=new URL("/api/builds",this.options.baseUrl);return url.searchParams.set("app_id",appId),typeof options?.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async getBuildPrecheck(appId,args){let url=new URL("/api/builds/precheck",this.options.baseUrl);return url.searchParams.set("app_id",appId),url.searchParams.set("source_version_id",args.source_version_id),args.build_config?.dockerfile_path&&url.searchParams.set("dockerfile_path",args.build_config.dockerfile_path),args.build_config?.context_subdir&&url.searchParams.set("context_subdir",args.build_config.context_subdir),args.build_config?.target&&url.searchParams.set("target",args.build_config.target),this.request(`${url.pathname}${url.search}`)}async getBuild(buildId){return this.request(`/api/builds/${encodeURIComponent(buildId)}`)}async listBuildEvents(buildId){return this.request(`/api/builds/${encodeURIComponent(buildId)}/events`)}async createLocalBuildSession(payload){return this.request("/api/builds/local-sessions",{method:"POST",body:JSON.stringify(payload)})}async completeLocalBuildSession(buildId,payload){return this.request(`/api/builds/${encodeURIComponent(buildId)}/local-complete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppSourceWorkspace(appId,options){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/source-workspace`,this.options.baseUrl);return options?.sourceVersionId&&url.searchParams.set("source_version_id",options.sourceVersionId),this.request(`${url.pathname}${url.search}`)}async getTenantAppDevWorkspace(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace`)}async pushTenantAppDevWorkspace(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/push`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload)})}async createTenantAppDevWorkspacePreview(appId,payload={}){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/preview`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppDevWorkspacePreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/preview`)}async listTenantAppSourceVersions(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions`)}async updateTenantAppSourceVersion(appId,sourceVersionId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async getTenantAppEndUserAuthConfig(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/config`)}async getTenantAppEndUserAuthDiscovery(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/discovery`)}async getTenantAppEndUserAuthInspect(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/inspect`)}async configureTenantAppEndUserAuth(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/configure`,{method:"POST",body:JSON.stringify(payload)})}async bindTenantAppEndUserAuth(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/bind`,{method:"POST",body:JSON.stringify(payload)})}async listTenantAppEndUsers(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users`)}async listTenantAppEndUserRoles(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles`)}async createTenantAppEndUserRole(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppEndUserRole(appId,roleKey){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles/${encodeURIComponent(roleKey)}`)}async updateTenantAppEndUserRole(appId,roleKey,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles/${encodeURIComponent(roleKey)}`,{method:"PATCH",body:JSON.stringify(payload)})}async listTenantAppUserRoles(appId,appUserId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles`)}async assignTenantAppUserRoles(appId,appUserId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles:assign`,{method:"POST",body:JSON.stringify(payload)})}async replaceTenantAppUserRoles(appId,appUserId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles`,{method:"PUT",body:JSON.stringify(payload)})}async removeTenantAppUserRole(appId,appUserId,roleKey){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles/${encodeURIComponent(roleKey)}`,{method:"DELETE"})}async discoverTenantCmsCollection(collection){let url=new URL("/api/tenant/cms/discover",this.options.baseUrl);return url.searchParams.set("collection",collection),this.request(`${url.pathname}${url.search}`)}async listTenantCmsCollections(){return this.request("/api/tenant/cms/collections")}async inspectTenantCmsSchema(collection){let url=new URL("/api/tenant/cms/inspect/schema",this.options.baseUrl);return url.searchParams.set("collection",collection),this.request(`${url.pathname}${url.search}`)}async listTenantCmsItems(args){let url=new URL("/api/tenant/cms/items",this.options.baseUrl);return url.searchParams.set("collection",args.collection),typeof args.page=="number"&&Number.isFinite(args.page)&&url.searchParams.set("page",String(args.page)),typeof args.pageSize=="number"&&Number.isFinite(args.pageSize)&&url.searchParams.set("page_size",String(args.pageSize)),setOptionalSearchParam(url,"category_id",args.categoryId),setOptionalSearchParam(url,"status",args.status),setOptionalSearchParam(url,"q",args.query),this.request(`${url.pathname}${url.search}`)}async getTenantCmsItem(args){let url=new URL(`/api/tenant/cms/items/${encodeURIComponent(args.id)}`,this.options.baseUrl);return url.searchParams.set("collection",args.collection),this.request(`${url.pathname}${url.search}`)}async configureTenantCmsCollection(spec){return this.request("/api/tenant/cms/configure/collection",{method:"POST",body:JSON.stringify(spec)})}async configureTenantCmsItem(payload){return this.request("/api/tenant/cms/configure/item",{method:"POST",body:JSON.stringify(payload)})}async configureTenantCmsCategory(payload){return this.request("/api/tenant/cms/configure/category",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsSchema(payload){return this.request("/api/tenant/cms/apply/schema",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsCollectionStatus(payload){return this.request("/api/tenant/cms/apply/collection-status",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsPublish(payload){return this.request("/api/tenant/cms/apply/publish",{method:"POST",body:JSON.stringify(payload)})}async listPublicCmsItems(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items`,this.options.baseUrl);url.searchParams.set("tenant_id",args.tenantId),typeof args.page=="number"&&Number.isFinite(args.page)&&url.searchParams.set("page",String(args.page)),typeof args.pageSize=="number"&&Number.isFinite(args.pageSize)&&url.searchParams.set("page_size",String(args.pageSize)),setOptionalSearchParam(url,"category_id",args.categoryId),setOptionalSearchParam(url,"sort_field",args.sortField),setOptionalSearchParam(url,"sort_direction",args.sortDirection);for(let tag of args.tags??[])url.searchParams.append("tag",tag);return this.request(`${url.pathname}${url.search}`)}async getPublicCmsItemBySlug(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items/by-slug/${encodeURIComponent(args.slug)}`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async getPublicCmsItemById(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items/${encodeURIComponent(args.id)}`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async listPublicCmsCategories(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/categories`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async listTenantAppDeploymentTimeline(appId,options){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/deployments`,this.options.baseUrl);return typeof options?.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantAppPublishSettings(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings`)}async updateTenantAppPublishSettings(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings`,{method:"PATCH",body:JSON.stringify(payload)})}async setTenantAppCurrentPublishedVersion(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings/current-version`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppPreview(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/previews`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppSourceVersion(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppSourceVersionFromTemplate(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions:from-template`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppReleaseDeletePreview(appId,releaseId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/releases/${encodeURIComponent(releaseId)}/delete-preview`,{method:"POST"})}async deleteTenantAppRelease(appId,releaseId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/releases/${encodeURIComponent(releaseId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppSourceVersionDeletePreview(appId,sourceVersionId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}/delete-preview`,{method:"POST"})}async deleteTenantAppSourceVersion(appId,sourceVersionId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantVersionDeleteJob(jobId){return this.request(`/api/tenant/version-delete-jobs/${encodeURIComponent(jobId)}`)}async getTenantAppBuildDeletePreview(appId,buildId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/builds/${encodeURIComponent(buildId)}/delete-preview`,{method:"POST"})}async deleteTenantAppBuild(appId,buildId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/builds/${encodeURIComponent(buildId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppDbInstance(appId,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbRuntimeBindings(appId,env="preview",purpose){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/runtime-bindings`,this.options.baseUrl);return url.searchParams.set("env",env),purpose&&url.searchParams.set("purpose",purpose),this.requestUrl(url)}async resolveDevRuntimeBindings(payload){return this.request("/api/dev-runtime-bindings/resolve",{method:"POST",body:JSON.stringify(payload)})}async revokeDevRuntimeBindings(payload){return this.request("/api/dev-runtime-bindings/revoke",{method:"POST",body:JSON.stringify(payload)})}async listTenantAppDbTables(appId,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbTableSchema(appId,tableName,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/schema`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbTableRows(appId,tableName,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.page=="number"&&url.searchParams.set("page",String(args.page)),typeof args.page_size=="number"&&url.searchParams.set("page_size",String(args.page_size)),typeof args.sort_by=="string"&&args.sort_by.trim().length>0&&url.searchParams.set("sort_by",args.sort_by),args.sort_order==="desc"&&url.searchParams.set("sort_order","desc"),typeof args.filter_column=="string"&&args.filter_column.trim().length>0&&url.searchParams.set("filter_column",args.filter_column),typeof args.filter_value=="string"&&args.filter_value.length>0&&url.searchParams.set("filter_value",args.filter_value),typeof args.search_query=="string"&&args.search_query.trim().length>0&&url.searchParams.set("search_query",args.search_query),this.requestUrl(url)}async listTenantAppDbMigrationRuns(appId,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/migrations`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.limit=="number"&&url.searchParams.set("limit",String(args.limit)),this.requestUrl(url)}async listTenantAppDbChangeAudits(appId,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/audits`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.table_name=="string"&&args.table_name.trim().length>0&&url.searchParams.set("table_name",args.table_name),typeof args.limit=="number"&&url.searchParams.set("limit",String(args.limit)),this.requestUrl(url)}async insertTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"POST",body:JSON.stringify(payload)})}async updateTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"DELETE",body:JSON.stringify(payload)})}async queryTenantAppDb(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/query`,{method:"POST",body:JSON.stringify(payload)})}async createWorkspace(payload){return this.request("/api/admin/workspaces",{method:"POST",body:JSON.stringify(payload)})}async deleteWorkspace(workspaceId,payload){return this.request(`/api/admin/workspaces/${encodeURIComponent(workspaceId)}`,{method:"DELETE",...payload?{body:JSON.stringify(payload)}:{}})}async createApproval(payload){return this.request("/api/admin/resource-approvals",{method:"POST",body:JSON.stringify(payload)})}async listApprovals(filters){let url=new URL("/api/admin/resource-approvals",this.options.baseUrl);return filters?.tenant_id&&url.searchParams.set("tenant_id",filters.tenant_id),filters?.app_id&&url.searchParams.set("app_id",filters.app_id),filters?.status&&url.searchParams.set("status",filters.status),filters?.operation&&url.searchParams.set("operation",filters.operation),this.requestUrl(url)}async decideApproval(approvalId,payload){return this.request(`/api/admin/resource-approvals/${approvalId}/decision`,{method:"POST",body:JSON.stringify(payload)})}async listResourceLocks(filters){let url=new URL("/api/admin/resource-locks",this.options.baseUrl);return filters?.tenant_id&&url.searchParams.set("tenant_id",filters.tenant_id),filters?.app_id&&url.searchParams.set("app_id",filters.app_id),filters?.env&&url.searchParams.set("env",filters.env),this.requestUrl(url)}async diffResources(payload){return this.request("/api/resources/diff",{method:"POST",body:JSON.stringify(payload)})}async applyResources(payload){return this.request("/api/resources/apply",{method:"POST",body:JSON.stringify(payload)})}async rollbackResources(payload){return this.request("/api/resources/rollback",{method:"POST",body:JSON.stringify(payload)})}async deployRelease(payload){return this.request("/api/releases/deploy",{method:"POST",body:JSON.stringify(payload)})}async rollbackRelease(payload){return this.request("/api/releases/rollback",{method:"POST",body:JSON.stringify(payload)})}async queryLogs(payload){return this.request("/api/logs/query",{method:"POST",body:JSON.stringify(payload)})}};function setOptionalSearchParam(url,key,value){typeof value=="string"&&value.trim().length>0&&url.searchParams.set(key,value)}function setOptionalBooleanSearchParam(url,key,value){typeof value=="boolean"&&url.searchParams.set(key,value?"true":"false")}function resolveRelativeOrAbsoluteUrl(pathOrUrl,baseUrl){return new URL(pathOrUrl,baseUrl)}function createPlatformSdk(options){return new PlatformSdk(options)}var NotificationSdkNamespace=class{sdk;endUser;constructor(sdk){this.sdk=sdk,this.endUser=new EndUserNotificationNamespace(sdk)}},EndUserNotificationNamespace=class{sdk;constructor(sdk){this.sdk=sdk}forApp(appId){return new EndUserNotificationAppClient(this.sdk,appId)}},EndUserNotificationAppClient=class{sdk;appId;announcements;constructor(sdk,appId){this.sdk=sdk,this.appId=appId,this.announcements=new EndUserNotificationAppAnnouncementsClient(sdk,appId)}listUsers(){return this.sdk.listTenantAppEndUsers(this.appId)}forUser(endUserId){return new EndUserNotificationUserClient(this.sdk,this.appId,endUserId)}listInbox(endUserId,query={}){return this.sdk.listEndUserNotificationInbox(this.appId,{end_user_id:endUserId,...query})}getUnreadCount(endUserId){return this.sdk.getEndUserNotificationUnreadCount(this.appId,endUserId)}publish(input){return this.sdk.publishEndUserNotification(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),title:input.title,body:input.body??null,notification_type:input.notification_type??"notification",object_ref:input.object_ref,action_ref:input.action_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("publish",this.appId,input.end_user_id),deliver_to:input.deliver_to})}remind(input){return this.sdk.createEndUserNotificationReminder(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),remind_at:input.remind_at,title:input.title,body:input.body??null,object_ref:input.object_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("reminder",this.appId,input.end_user_id)})}projectTask(input){return this.sdk.projectEndUserTaskNotification(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),source_task_ref:input.source_task_ref,title:input.title,summary:input.summary??null,due_at:input.due_at??null,source_event_id:input.source_event_id??null,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("task-projection",this.appId,input.end_user_id)})}},EndUserNotificationAppAnnouncementsClient=class{sdk;appId;constructor(sdk,appId){this.sdk=sdk,this.appId=appId}getConfig(){return this.sdk.getAppNotificationConfig(this.appId)}list(limit){return this.sdk.listAppNotificationAnnouncements(this.appId,{limit})}create(input){return this.sdk.createAppNotificationAnnouncement(this.appId,input)}archive(announcementId){return this.sdk.archiveAppNotificationAnnouncement(this.appId,announcementId)}},EndUserNotificationUserClient=class{sdk;appId;endUserId;constructor(sdk,appId,endUserId){this.sdk=sdk,this.appId=appId,this.endUserId=endUserId}buildRecipientRef(){return buildDirectEndUserRecipientRef(this.appId,this.endUserId)}listInbox(query={}){return this.sdk.listEndUserNotificationInbox(this.appId,{end_user_id:this.endUserId,...query})}getUnreadCount(){return this.sdk.getEndUserNotificationUnreadCount(this.appId,this.endUserId)}publish(input){return this.sdk.publishEndUserNotification(this.appId,{recipient:this.buildRecipientRef(),title:input.title,body:input.body??null,notification_type:input.notification_type??"notification",object_ref:input.object_ref,action_ref:input.action_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("publish",this.appId,this.endUserId),deliver_to:input.deliver_to})}remind(input){return this.sdk.createEndUserNotificationReminder(this.appId,{recipient:this.buildRecipientRef(),remind_at:input.remind_at,title:input.title,body:input.body??null,object_ref:input.object_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("reminder",this.appId,this.endUserId)})}projectTask(input){return this.sdk.projectEndUserTaskNotification(this.appId,{recipient:this.buildRecipientRef(),source_task_ref:input.source_task_ref,title:input.title,summary:input.summary??null,due_at:input.due_at??null,source_event_id:input.source_event_id??null,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("task-projection",this.appId,this.endUserId)})}};function buildDirectEndUserRecipientRef(appId,endUserId){return{app_id:appId,end_user_id:endUserId,recipient_type:"direct_user"}}function buildNotificationIdempotencyKey(prefix,appId,endUserId){return`${prefix}:${appId}:${endUserId}:${Date.now()}`}var AUTH_PAGE_HTML=String.raw`<!doctype html>
2
+ var __create=Object.create;var __defProp=Object.defineProperty;var __getOwnPropDesc=Object.getOwnPropertyDescriptor;var __getOwnPropNames=Object.getOwnPropertyNames;var __getProtoOf=Object.getPrototypeOf,__hasOwnProp=Object.prototype.hasOwnProperty;var __commonJS=(cb,mod)=>function(){return mod||(0,cb[__getOwnPropNames(cb)[0]])((mod={exports:{}}).exports,mod),mod.exports};var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0})},__copyProps=(to,from,except,desc)=>{if(from&&typeof from=="object"||typeof from=="function")for(let key of __getOwnPropNames(from))!__hasOwnProp.call(to,key)&&key!==except&&__defProp(to,key,{get:()=>from[key],enumerable:!(desc=__getOwnPropDesc(from,key))||desc.enumerable});return to};var __toESM=(mod,isNodeMode,target)=>(target=mod!=null?__create(__getProtoOf(mod)):{},__copyProps(isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target,mod));var require_punycode=__commonJS({"../../node_modules/.pnpm/punycode.js@2.3.1/node_modules/punycode.js/punycode.js"(exports,module){"use strict";var regexPunycode=/^xn--/,regexNonASCII=/[^\0-\x7F]/,regexSeparators=/[\x2E\u3002\uFF0E\uFF61]/g,errors={overflow:"Overflow: input needs wider integers to process","not-basic":"Illegal input >= 0x80 (not a basic code point)","invalid-input":"Invalid input"},baseMinusTMin=35,floor=Math.floor,stringFromCharCode=String.fromCharCode;function error(type){throw new RangeError(errors[type])}function map(array,callback){let result=[],length=array.length;for(;length--;)result[length]=callback(array[length]);return result}function mapDomain(domain,callback){let parts=domain.split("@"),result="";parts.length>1&&(result=parts[0]+"@",domain=parts[1]),domain=domain.replace(regexSeparators,".");let labels=domain.split("."),encoded=map(labels,callback).join(".");return result+encoded}function ucs2decode(string){let output=[],counter=0,length=string.length;for(;counter<length;){let value=string.charCodeAt(counter++);if(value>=55296&&value<=56319&&counter<length){let extra=string.charCodeAt(counter++);(extra&64512)==56320?output.push(((value&1023)<<10)+(extra&1023)+65536):(output.push(value),counter--)}else output.push(value)}return output}var ucs2encode=codePoints=>String.fromCodePoint(...codePoints),basicToDigit=function(codePoint){return codePoint>=48&&codePoint<58?26+(codePoint-48):codePoint>=65&&codePoint<91?codePoint-65:codePoint>=97&&codePoint<123?codePoint-97:36},digitToBasic=function(digit,flag){return digit+22+75*(digit<26)-((flag!=0)<<5)},adapt=function(delta,numPoints,firstTime){let k=0;for(delta=firstTime?floor(delta/700):delta>>1,delta+=floor(delta/numPoints);delta>baseMinusTMin*26>>1;k+=36)delta=floor(delta/baseMinusTMin);return floor(k+(baseMinusTMin+1)*delta/(delta+38))},decode2=function(input){let output=[],inputLength=input.length,i=0,n=128,bias=72,basic=input.lastIndexOf("-");basic<0&&(basic=0);for(let j=0;j<basic;++j)input.charCodeAt(j)>=128&&error("not-basic"),output.push(input.charCodeAt(j));for(let index=basic>0?basic+1:0;index<inputLength;){let oldi=i;for(let w=1,k=36;;k+=36){index>=inputLength&&error("invalid-input");let digit=basicToDigit(input.charCodeAt(index++));digit>=36&&error("invalid-input"),digit>floor((2147483647-i)/w)&&error("overflow"),i+=digit*w;let t=k<=bias?1:k>=bias+26?26:k-bias;if(digit<t)break;let baseMinusT=36-t;w>floor(2147483647/baseMinusT)&&error("overflow"),w*=baseMinusT}let out=output.length+1;bias=adapt(i-oldi,out,oldi==0),floor(i/out)>2147483647-n&&error("overflow"),n+=floor(i/out),i%=out,output.splice(i++,0,n)}return String.fromCodePoint(...output)},encode2=function(input){let output=[];input=ucs2decode(input);let inputLength=input.length,n=128,delta=0,bias=72;for(let currentValue of input)currentValue<128&&output.push(stringFromCharCode(currentValue));let basicLength=output.length,handledCPCount=basicLength;for(basicLength&&output.push("-");handledCPCount<inputLength;){let m=2147483647;for(let currentValue of input)currentValue>=n&&currentValue<m&&(m=currentValue);let handledCPCountPlusOne=handledCPCount+1;m-n>floor((2147483647-delta)/handledCPCountPlusOne)&&error("overflow"),delta+=(m-n)*handledCPCountPlusOne,n=m;for(let currentValue of input)if(currentValue<n&&++delta>2147483647&&error("overflow"),currentValue===n){let q=delta;for(let k=36;;k+=36){let t=k<=bias?1:k>=bias+26?26:k-bias;if(q<t)break;let qMinusT=q-t,baseMinusT=36-t;output.push(stringFromCharCode(digitToBasic(t+qMinusT%baseMinusT,0))),q=floor(qMinusT/baseMinusT)}output.push(stringFromCharCode(digitToBasic(q,0))),bias=adapt(delta,handledCPCountPlusOne,handledCPCount===basicLength),delta=0,++handledCPCount}++delta,++n}return output.join("")},toUnicode=function(input){return mapDomain(input,function(string){return regexPunycode.test(string)?decode2(string.slice(4).toLowerCase()):string})},toASCII=function(input){return mapDomain(input,function(string){return regexNonASCII.test(string)?"xn--"+encode2(string):string})},punycode2={version:"2.3.1",ucs2:{decode:ucs2decode,encode:ucs2encode},decode:decode2,encode:encode2,toASCII,toUnicode};module.exports=punycode2}});import{spawn as spawn5}from"node:child_process";import{existsSync as existsSync24,readFileSync as readFileSync26}from"node:fs";import process7 from"node:process";async function batchUpdateTenantCmsItems(args){let collection=args.payload.collection.trim(),itemIds=Array.from(new Set(args.payload.item_ids.map(itemId=>itemId.trim()).filter(Boolean))),tagAdds=dedupeTags(args.payload.changes.tags.add),discover=await args.sdk.discoverTenantCmsCollection(collection),schemaSpec=discover.active_schema??discover.draft_schema;if(!schemaSpec)throw new Error(`Collection \`${collection}\` \u5F53\u524D\u6CA1\u6709\u53EF\u7528 schema\u3002`);let succeeded=[],failed=[];for(let itemId of itemIds){let title=itemId;try{let item=await args.sdk.getTenantCmsItem({collection,id:itemId});title=resolveCmsItemTitle(item);let currentStatus=item.system.publish_status??"draft",targetStatus=args.payload.changes.publish_status.mode==="set"?args.payload.changes.publish_status.value:void 0,hasCategoryChange=args.payload.changes.category.mode!=="keep",hasTagChange=tagAdds.length>0,hasMetadataChange=hasCategoryChange||hasTagChange,effectiveStatus=currentStatus;if(hasMetadataChange){currentStatus==="archived"&&targetStatus&&targetStatus!=="archived"&&(await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:targetStatus}),effectiveStatus=targetStatus);let payload=buildCmsItemWritePayloadFromDelivery({item,schemaSpec,publishStatus:targetStatus&&targetStatus!=="archived"?targetStatus:effectiveStatus,categoryChange:args.payload.changes.category,tagsToAdd:tagAdds});await args.sdk.configureTenantCmsItem({...payload,item_id:itemId}),targetStatus==="archived"&&effectiveStatus!=="archived"?await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:"archived"}):targetStatus&&targetStatus!=="archived"&&(effectiveStatus=targetStatus)}else targetStatus&&targetStatus!==effectiveStatus&&await args.sdk.applyTenantCmsPublish({collection,item_id:itemId,target_status:targetStatus});succeeded.push({item_id:itemId,title})}catch(error){failed.push({item_id:itemId,title,message:error instanceof Error?error.message:"\u6279\u91CF\u66F4\u65B0\u5931\u8D25"})}}return{total:itemIds.length,succeeded,failed}}function buildCmsItemWritePayloadFromDelivery(args){let nextTags=dedupeTags([...args.item.system.tags??[],...args.tagsToAdd]);return{collection:args.item.collection,system:{publish_status:args.publishStatus,...args.item.system.slug?{slug:args.item.system.slug}:{},featured:args.item.system.featured??!1,tags:nextTags,category_id:resolveNextCategoryId(args.item,args.categoryChange),...args.item.system.content_format?{content_format:args.item.system.content_format}:{},...args.item.system.source?{source:{...args.item.system.source}}:{}},content:normalizeCmsContentForWrite(args.item.content,args.schemaSpec.fields)}}function resolveNextCategoryId(item,categoryChange){return categoryChange.mode==="clear"?null:categoryChange.mode==="set"?categoryChange.category_id?.trim()||null:item.system.category_id??null}function resolveCmsItemTitle(item){let title=item.content.title,name=item.content.name;return typeof title=="string"&&title.trim()?title.trim():typeof name=="string"&&name.trim()?name.trim():item.system.slug??item.system.id??"Untitled item"}function dedupeTags(values){let seen=new Set,next=[];for(let value of values){let normalized=value.trim();if(!normalized)continue;let lowered=normalized.toLowerCase();seen.has(lowered)||(seen.add(lowered),next.push(normalized))}return next}function normalizeCmsContentForWrite(content,fields){let normalized={};for(let field of fields)normalized[field.name]=normalizeFieldValueForPayload(field,content[field.name]);return normalized}function normalizeFieldValueForPayload(field,value){switch(field.type){case"date":if(typeof value=="string"){let normalized=value.trim();return normalized.length>0?normalized:null}return value??null;case"number":if(typeof value=="string"){let parsed=Number.parseFloat(value.trim());return Number.isFinite(parsed)?field.ui?.number_kind==="integer"?Math.trunc(parsed):parsed:0}return value;case"bool":return!!value;case"multi_select":return normalizeStringArrayValue(value);case"image":case"file":return normalizeAssetValue(value);case"images":case"files":return normalizeAssetArrayValue(value);case"relation":return normalizeRelationId(value);case"relations":return normalizeRelationArrayValue(value);default:return typeof value=="string"?value:value??""}}function normalizeRelationId(value){if(typeof value=="string"){let normalized=value.trim();return normalized.length>0?normalized:null}if(value&&typeof value=="object"&&!Array.isArray(value)&&"id"in value){let id=value.id;return typeof id=="string"&&id.trim().length>0?id.trim():null}return null}function normalizeAssetValue(value){return value&&typeof value=="object"&&!Array.isArray(value)?value:null}function normalizeStringArrayValue(value){return Array.isArray(value)?value.map(item=>String(item)):typeof value=="string"?value.split(",").map(item=>item.trim()).filter(Boolean):[]}function normalizeAssetArrayValue(value){return Array.isArray(value)?value.filter(item=>!!item&&typeof item=="object"&&!Array.isArray(item)):[]}function normalizeRelationArrayValue(value){return Array.isArray(value)?value.map(item=>normalizeRelationId(item)).filter(item=>!!item):[]}import{createHash}from"node:crypto";import{URL as URL2}from"node:url";var IMAGE_URL_ATTRS=["src","data-src","data-original","data-original-src","data-lazy-src"],IMAGE_SRCSET_ATTRS=["srcset","data-srcset"];function trimToUndefined(value){let normalized=value?.trim();return normalized||void 0}function normalizeUrl(value,baseUrl){let trimmed=trimToUndefined(value);if(trimmed)try{return baseUrl?new URL2(trimmed,baseUrl).toString():new URL2(trimmed).toString()}catch{return}}function isPlatformHostedAssetUrl(value){try{let parsed=new URL2(value);return/^\/assets\/[^/]+\/(original|variants\/[^/]+)$/.test(parsed.pathname)||parsed.pathname.startsWith("/api/tenant/assets/")}catch{return!1}}function inferMimeTypeFromUrl(value){if(!value)return;let pathname=(()=>{try{return new URL2(value).pathname.toLowerCase()}catch{return value.toLowerCase()}})();if(pathname.endsWith(".png"))return"image/png";if(pathname.endsWith(".webp"))return"image/webp";if(pathname.endsWith(".gif"))return"image/gif";if(pathname.endsWith(".svg"))return"image/svg+xml";if(pathname.endsWith(".jpg")||pathname.endsWith(".jpeg"))return"image/jpeg";if(pathname.endsWith(".avif"))return"image/avif"}function computeChecksum(content){return`sha256:${createHash("sha256").update(content).digest("hex")}`}function inferRemoteImageFileName(url,mimeType){let lastSegment=(()=>{try{return new URL2(url).pathname}catch{return url}})().split("/").filter(Boolean).at(-1);return lastSegment&&/\.[a-z0-9]{2,6}$/i.test(lastSegment)?decodeURIComponent(lastSegment):`remote-image.${(()=>{switch(mimeType){case"image/png":return"png";case"image/webp":return"webp";case"image/gif":return"gif";case"image/svg+xml":return"svg";case"image/avif":return"avif";case"image/jpeg":default:return"jpg"}})()}`}function buildTenantAssetReference(asset){return{asset_id:asset.asset.asset_id,title:asset.asset.title,media_type:asset.asset.media_type,mime_type:asset.asset.mime_type,size_bytes:asset.original_file.size_bytes,folder_id:asset.asset.folder_id,original_url:asset.original_url,variant_urls:asset.variant_urls}}function replaceImageAttributeUrls(html,replacementsByUrl,attribute2){let pattern=new RegExp(`(<img\\b[^>]*?\\s${attribute2}\\s*=\\s*)(["'])(.*?)\\2`,"gi");return html.replace(pattern,(fullMatch,prefix,quote,rawUrl)=>{let replacement=replacementsByUrl.get(rawUrl);return!replacement||replacement.finalUrl===rawUrl?fullMatch:`${prefix}${quote}${replacement.finalUrl}${quote}`})}function stripImageAttributes(html,attributes){let nextHtml=html;for(let attribute2 of attributes){let pattern=new RegExp(`\\s${attribute2}\\s*=\\s*(["']).*?\\1`,"gi");nextHtml=nextHtml.replace(pattern,"")}return nextHtml}async function fetchRemoteImageBinary(args){let response=await(args.fetchImpl??fetch)(args.url,{headers:{accept:"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"}});if(!response.ok)throw new Error(`\u56FE\u7247\u62C9\u53D6\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`);let normalizedMimeType=String(response.headers.get("content-type")??"").split(";")[0]?.trim().toLowerCase()||inferMimeTypeFromUrl(args.url);if(!normalizedMimeType||!normalizedMimeType.startsWith("image/"))throw new Error("\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u53D7\u652F\u6301\u7684\u56FE\u7247\u7C7B\u578B");let content=new Uint8Array(await response.arrayBuffer()),maxBytes=args.maxBytes??20*1024*1024;if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");if(content.byteLength>maxBytes)throw new Error(`\u8FDC\u7A0B\u56FE\u7247\u8D85\u8FC7\u5927\u5C0F\u9650\u5236\uFF08${content.byteLength} bytes\uFF09`);return{content,mimeType:normalizedMimeType}}async function ingestRemoteImageCandidates(args){let uniqueCandidates=new Map;for(let candidate of args.candidates)uniqueCandidates.has(candidate.url)||uniqueCandidates.set(candidate.url,candidate);let resultsByUrl=new Map,resultsByChecksum=new Map,warnings=[];for(let candidate of uniqueCandidates.values())try{let{content,mimeType}=await fetchRemoteImageBinary({url:candidate.url,fetchImpl:args.fetchImpl,maxBytes:args.maxBytes}),checksum3=computeChecksum(content),existingByChecksum=resultsByChecksum.get(checksum3);if(existingByChecksum){let reused={...existingByChecksum,originalUrl:candidate.url,status:"reused"};resultsByUrl.set(candidate.url,reused);continue}let fileName=inferRemoteImageFileName(candidate.url,mimeType),uploadedAsset=await args.sdk.createTenantAssetBinary({fileName,mimeType,content,title:candidate.title,...args.folderId?{folderId:args.folderId}:{}}),uploaded={originalUrl:candidate.url,finalUrl:uploadedAsset.original_url,asset:uploadedAsset,assetReference:buildTenantAssetReference(uploadedAsset),mimeType,checksum:checksum3,status:"uploaded"};resultsByUrl.set(candidate.url,uploaded),resultsByChecksum.set(checksum3,uploaded)}catch(error){let message=error instanceof Error?error.message:"\u5916\u94FE\u56FE\u7247\u8D44\u4EA7\u5316\u5931\u8D25";warnings.push(`\u56FE\u7247 \`${candidate.url}\` \u8D44\u4EA7\u5316\u5931\u8D25\uFF0C\u5DF2\u56DE\u9000\u539F\u94FE\u63A5\uFF1A${message}`),resultsByUrl.set(candidate.url,{originalUrl:candidate.url,finalUrl:candidate.url,mimeType:inferMimeTypeFromUrl(candidate.url),status:"fallback",warning:message})}return{resultsByUrl,warnings}}function collectExternalImageCandidatesFromHtml(args){let candidates=new Map;return args.html.replace(/<img\b[^>]*>/gi,tag=>{for(let attribute2 of IMAGE_URL_ATTRS){let rawUrl=tag.match(new RegExp(`(?:^|\\s)${attribute2}\\s*=\\s*(["'])(.*?)\\1`,"i"))?.[2],normalizedUrl=normalizeUrl(rawUrl,args.baseUrl);!normalizedUrl||normalizedUrl.startsWith("data:")||isPlatformHostedAssetUrl(normalizedUrl)||candidates.has(normalizedUrl)||candidates.set(normalizedUrl,{url:normalizedUrl,title:args.title,source:"body"})}return""}),[...candidates.values()]}async function assetizeExternalImagesInHtml(args){let bodyCandidates=collectExternalImageCandidatesFromHtml({html:args.html,baseUrl:args.baseUrl,title:args.bodyTitle}),normalizedCoverUrl=normalizeUrl(args.coverUrl,args.baseUrl),coverCandidate=normalizedCoverUrl&&!normalizedCoverUrl.startsWith("data:")&&!isPlatformHostedAssetUrl(normalizedCoverUrl)?{url:normalizedCoverUrl,title:args.coverTitle??args.bodyTitle,source:"cover"}:null,candidates=coverCandidate?[coverCandidate,...bodyCandidates]:bodyCandidates,{resultsByUrl,warnings}=await ingestRemoteImageCandidates({sdk:args.sdk,candidates,folderId:args.folderId,fetchImpl:args.fetchImpl,maxBytes:args.maxBytes}),html=args.html;for(let attribute2 of IMAGE_URL_ATTRS)html=replaceImageAttributeUrls(html,resultsByUrl,attribute2);html=stripImageAttributes(html,IMAGE_SRCSET_ATTRS);let replacements=[...resultsByUrl.values()].map(result=>({originalUrl:result.originalUrl,finalUrl:result.finalUrl,...result.asset?.asset.asset_id?{assetId:result.asset.asset.asset_id}:{},status:result.status}));if(!normalizedCoverUrl)return{html,cover:{mode:"none"},replacements,warnings};let coverResult=resultsByUrl.get(normalizedCoverUrl);return coverResult?.assetReference?{html,cover:{mode:"asset",value:coverResult.assetReference},replacements,warnings}:{html,cover:{mode:"remote",value:{title:args.coverTitle??args.bodyTitle??"Remote cover",...coverResult?.mimeType||args.coverMimeType?{mime_type:coverResult?.mimeType??args.coverMimeType}:{},original_url:normalizedCoverUrl}},replacements,warnings}}var PlatformApiError=class extends Error{status;code;detail;requestId;capability;category;remediation;constructor(message,status,code2,detail,requestId,capability,category,remediation){super(message),this.status=status,this.code=code2,this.detail=detail,this.requestId=requestId,this.capability=capability,this.category=category,this.remediation=remediation,this.name="PlatformApiError"}},BasePlatformSdk=class{options;fetchImpl;constructor(options){this.options=options,this.fetchImpl=options.fetchImpl??fetch}async request(path2,init={}){return this.requestUrl(new URL(path2,this.options.baseUrl),init)}async requestBinary(path2,init={}){return this.requestBinaryUrl(new URL(path2,this.options.baseUrl),init)}async requestVoid(path2,init={}){return this.requestVoidUrl(new URL(path2,this.options.baseUrl),init)}async requestUrl(url,init={}){let response=await this.fetchResponse(url,init),payload=await parseJsonResponse(response);if(!response.ok){let errorPayload=payload,error=errorPayload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??errorPayload.detail,errorPayload.request_id,error?.capability,error?.category,error?.remediation)}return payload}async requestBinaryUrl(url,init={}){let response=await this.fetchResponse(url,init);if(!response.ok){let payload=await parseJsonResponse(response),error=payload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??payload.detail,payload.request_id,error?.capability,error?.category,error?.remediation)}return new Uint8Array(await response.arrayBuffer())}async requestVoidUrl(url,init={}){let response=await this.fetchResponse(url,init);if(!response.ok){let payload=await parseJsonResponse(response),error=payload.error;throw new PlatformApiError(error?.message??`Request failed: ${response.status}`,response.status,error?.code,error?.detail??payload.detail,payload.request_id,error?.capability,error?.category,error?.remediation)}}async fetchResponse(url,init={}){let headers=new Headers(init.headers);!headers.has("Content-Type")&&init.body&&headers.set("Content-Type","application/json");let extraHeaders=await this.options.getHeaders?.();return extraHeaders&&new Headers(extraHeaders).forEach((value,key)=>{headers.set(key,value)}),this.fetchImpl(url,{...init,headers})}};async function parseJsonResponse(response){let text2=await response.text();if(text2.trim().length===0)return{};try{return JSON.parse(text2)}catch{if(response.ok)return{};throw new PlatformApiError(`Request failed with non-JSON response: ${response.status}`,response.status,"non_json_response",{content_type:response.headers.get("content-type")??void 0,body_preview:text2.replace(/\s+/g," ").slice(0,240)})}}var PlatformSdk=class extends BasePlatformSdk{notification;constructor(options){super(options),this.notification=new NotificationSdkNamespace(this)}async listNotificationInbox(filters={}){let url=new URL("/api/tenant/notification/inbox",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"inbox_type",filters.inbox_type),setOptionalSearchParam(url,"status",filters.status),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async updateNotificationInboxItemStatus(itemId,payload){return(await this.request(`/api/tenant/notification/inbox/${encodeURIComponent(itemId)}`,{method:"PATCH",body:JSON.stringify(payload)})).item}async batchUpdateNotificationInboxItemsStatus(payload){return this.request("/api/tenant/notification/inbox:batch",{method:"PATCH",body:JSON.stringify(payload)})}async listNotificationDeliveries(filters={}){let url=new URL("/api/tenant/notification/deliveries",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async announcePlatformNotification(payload){return(await this.request("/api/admin/notification/announcements/platform",{method:"POST",body:JSON.stringify(payload)})).item}async announceAppNotification(appId,payload){return(await this.request(`/api/tenant/notification/apps/${encodeURIComponent(appId)}/announcements`,{method:"POST",body:JSON.stringify(payload)})).item}async getAppNotificationConfig(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/config`)}async listAppNotificationAnnouncements(appId,options={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements`,this.options.baseUrl);return typeof options.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async createAppNotificationAnnouncement(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements`,{method:"POST",body:JSON.stringify(payload)})}async archiveAppNotificationAnnouncement(appId,announcementId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/announcements/${encodeURIComponent(announcementId)}:archive`,{method:"POST"})}async publishEndUserNotification(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/publish`,{method:"POST",body:JSON.stringify(payload)})}async createEndUserNotificationReminder(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/reminders`,{method:"POST",body:JSON.stringify(payload)})}async projectEndUserTaskNotification(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/task-projections`,{method:"POST",body:JSON.stringify(payload)})}async listEndUserNotificationInbox(appId,query){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/inbox`,this.options.baseUrl);return url.searchParams.set("end_user_id",query.end_user_id),setOptionalSearchParam(url,"status",query.status),setOptionalSearchParam(url,"inbox_type",query.inbox_type),typeof query.limit=="number"&&Number.isFinite(query.limit)&&url.searchParams.set("limit",String(query.limit)),this.request(`${url.pathname}${url.search}`)}async getEndUserNotificationUnreadCount(appId,endUserId){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/notification/agent/unread-count`,this.options.baseUrl);return url.searchParams.set("end_user_id",endUserId),this.request(`${url.pathname}${url.search}`)}async createWorkflowDefinition(payload){return(await this.request("/api/workflow/definitions",{method:"POST",body:JSON.stringify(payload)})).item}async listWorkflowTemplates(){return(await this.request("/api/workflow/templates")).items}async listWorkflowDefinitions(filters={}){let url=new URL("/api/workflow/definitions",this.options.baseUrl);return setOptionalSearchParam(url,"target_id",filters.target_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async listWorkflowBindings(filters={}){let url=new URL("/api/workflow/bindings",this.options.baseUrl);return setOptionalSearchParam(url,"target_id",filters.target_id),setOptionalSearchParam(url,"definition_key",filters.definition_key),(await this.request(`${url.pathname}${url.search}`)).items}async updateWorkflowDefinitionMetadata(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}`,{method:"PATCH",body:JSON.stringify(payload)})).item}async saveWorkflowRoleBindings(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}/role-bindings`,{method:"POST",body:JSON.stringify(payload)})).items}async getWorkflowBindingOverride(args){let url=new URL(`/api/workflow/definitions/${encodeURIComponent(args.definition_key)}/binding-override`,this.options.baseUrl);return setOptionalSearchParam(url,"target_scope",args.target_scope),setOptionalSearchParam(url,"target_id",args.target_id),(await this.request(`${url.pathname}${url.search}`)).item}async saveWorkflowBindingOverride(payload){return(await this.request(`/api/workflow/definitions/${encodeURIComponent(payload.definition_key)}/binding-override`,{method:"POST",body:JSON.stringify(payload)})).item}async listWorkflowRoleBindings(args){let url=new URL(`/api/workflow/definitions/${encodeURIComponent(args.definition_key)}/role-bindings`,this.options.baseUrl);return setOptionalSearchParam(url,"target_scope",args.target_scope),setOptionalSearchParam(url,"target_id",args.target_id),(await this.request(`${url.pathname}${url.search}`)).items}async startWorkflow(payload){return(await this.request("/api/workflow/instances/start",{method:"POST",body:JSON.stringify(payload)})).item}async performWorkflowAction(instanceId,payload){return(await this.request(`/api/workflow/instances/${encodeURIComponent(instanceId)}/actions`,{method:"POST",body:JSON.stringify(payload)})).item}async getWorkflowInstance(instanceId){return(await this.request(`/api/workflow/instances/${encodeURIComponent(instanceId)}`)).item}async listWorkflowTasks(filters={}){let url=new URL("/api/workflow/tasks",this.options.baseUrl);return setOptionalSearchParam(url,"app_id",filters.app_id),setOptionalSearchParam(url,"status",filters.status),(await this.request(`${url.pathname}${url.search}`)).items}async getWhoAmI(){return this.request("/api/auth/whoami")}async getResolvedPermissions(){return this.request("/api/auth/permissions")}async switchTenantContext(payload){return this.request("/api/auth/context/switch-tenant",{method:"POST",body:JSON.stringify(payload)})}async listTenantWorkspaces(){return this.request("/api/auth/workspaces")}async ensurePersonalWorkspace(){return this.request("/api/auth/workspaces/ensure-personal",{method:"POST"})}async getAdminOverview(){return this.request("/api/admin/overview")}async listAdminWorkbenchEntries(){return this.request("/api/admin/workbench-entries")}async getAdminWorkbenchEntryDetail(entryKey){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}`)}async updateAdminWorkbenchEntryVisibility(entryKey,payload){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility`,{method:"PUT",body:JSON.stringify(payload)})}async resetAdminWorkbenchEntryVisibility(entryKey){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility`,{method:"DELETE"})}async previewAdminWorkbenchEntryVisibility(entryKey,payload){return this.request(`/api/admin/workbench-entries/${encodeURIComponent(entryKey)}/visibility:preview`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAsset(payload){return this.request("/api/tenant/assets",{method:"POST",body:JSON.stringify(payload)})}async createTenantAssetBinary(args){let headers=new Headers({"Content-Type":args.mimeType,"X-Asset-File-Name":encodeURIComponent(args.fileName)});return args.title?.trim()&&headers.set("X-Asset-Title",encodeURIComponent(args.title.trim())),args.folderId?.trim()&&headers.set("X-Asset-Folder-Id",encodeURIComponent(args.folderId.trim())),this.request("/api/tenant/assets/upload",{method:"POST",headers,body:Buffer.from(args.content)})}async listTenantAssets(filters={}){let url=new URL("/api/tenant/assets",this.options.baseUrl);return setOptionalSearchParam(url,"q",filters.q),setOptionalSearchParam(url,"media_type",filters.media_type),setOptionalSearchParam(url,"mime_type",filters.mime_type),setOptionalSearchParam(url,"folder_id",filters.folder_id),setOptionalSearchParam(url,"tag_ids",filters.tag_ids?.join(",")),setOptionalSearchParam(url,"scene",filters.scene),setOptionalSearchParam(url,"objects",filters.objects?.join(",")),setOptionalSearchParam(url,"safety_flags",filters.safety_flags?.join(",")),setOptionalSearchParam(url,"orientation",filters.orientation),setOptionalBooleanSearchParam(url,"has_ocr",filters.has_ocr),setOptionalBooleanSearchParam(url,"has_person",filters.has_person),setOptionalBooleanSearchParam(url,"is_svg",filters.is_svg),typeof filters.page=="number"&&Number.isFinite(filters.page)&&url.searchParams.set("page",String(filters.page)),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantAsset(assetId){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}`)}async deleteTenantAsset(assetId){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}`,{method:"DELETE"})}async batchUpdateTenantAssets(payload){return this.request("/api/tenant/assets/batch",{method:"POST",body:JSON.stringify(payload)})}async listTenantAssetFolders(){return this.request("/api/tenant/assets/folders")}async createTenantAssetFolder(payload){return this.request("/api/tenant/assets/folders",{method:"POST",body:JSON.stringify(payload)})}async updateTenantAssetFolderMetadata(folderId,payload){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteTenantAssetFolder(folderId){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}`,{method:"DELETE"})}async moveTenantAssetFolder(folderId,direction){return this.request(`/api/tenant/assets/folders/${encodeURIComponent(folderId)}/move-${direction}`,{method:"POST"})}async updateTenantAssetFolder(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/folder`,{method:"PATCH",body:JSON.stringify(payload)})}async updateTenantAssetMetadata(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/metadata`,{method:"PATCH",body:JSON.stringify(payload)})}async listTenantAssetTags(options){let url=new URL("/api/tenant/assets/tags",this.options.baseUrl);return options?.assetId&&url.searchParams.set("asset_id",options.assetId),this.request(`${url.pathname}${url.search}`)}async addTenantAssetTag(assetId,payload){return this.request(`/api/tenant/assets/${encodeURIComponent(assetId)}/tags`,{method:"POST",body:JSON.stringify(payload)})}async removeTenantAssetTag(assetId,label){let url=new URL(`/api/tenant/assets/${encodeURIComponent(assetId)}/tags`,this.options.baseUrl);return url.searchParams.set("label",label),this.request(`${url.pathname}${url.search}`,{method:"DELETE"})}async downloadTenantAssetOriginal(assetId){return this.requestBinary(`/api/tenant/assets/${encodeURIComponent(assetId)}/original`)}async downloadTenantAssetVariant(assetId,variantKind){return this.requestBinary(`/assets/${encodeURIComponent(assetId)}/variants/${encodeURIComponent(variantKind)}`)}async createTenantBlobUploadSession(payload){return this.request("/api/tenant/blobs/upload-sessions",{method:"POST",body:JSON.stringify(payload)})}async uploadTenantBlobBinary(uploadSessionId,payload){let url=resolveRelativeOrAbsoluteUrl(payload.upload_url??`/api/tenant/blobs/upload-sessions/${encodeURIComponent(uploadSessionId)}/content`,this.options.baseUrl),headers=new Headers(payload.headers);headers.set("Content-Type",payload.content_type?.trim()||"application/octet-stream"),await this.requestVoidUrl(url,{method:"PUT",headers,body:Buffer.from(payload.content)})}async completeTenantBlobUpload(uploadSessionId,payload={}){return this.request(`/api/tenant/blobs/upload-sessions/${encodeURIComponent(uploadSessionId)}/complete`,{method:"POST",body:JSON.stringify(payload)})}async createTenantBlobBinary(args){let contentType=args.contentType?.trim()||"application/octet-stream",session=await this.createTenantBlobUploadSession({original_filename:args.fileName,content_type:contentType,size_bytes:args.content.byteLength,...args.appId?.trim()?{app_id:args.appId.trim()}:{},...args.clientRequestId?.trim()?{client_request_id:args.clientRequestId.trim()}:{}});return await this.uploadTenantBlobBinary(session.upload_session_id,{content:args.content,content_type:contentType,upload_url:session.upload_url,headers:session.headers}),this.completeTenantBlobUpload(session.upload_session_id,{size_bytes:args.content.byteLength,...args.sha256?.trim()?{sha256:args.sha256.trim()}:{}})}async listTenantBlobs(filters={}){let url=new URL("/api/tenant/blobs",this.options.baseUrl);return setOptionalSearchParam(url,"cursor",filters.cursor),setOptionalSearchParam(url,"app_id",filters.app_id??void 0),setOptionalSearchParam(url,"q",filters.q??void 0),typeof filters.limit=="number"&&Number.isFinite(filters.limit)&&url.searchParams.set("limit",String(filters.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantBlob(blobId){return this.request(`/api/tenant/blobs/${encodeURIComponent(blobId)}`)}async issueTenantBlobDownloadUrl(blobId,payload={}){return this.request(`/api/tenant/blobs/${encodeURIComponent(blobId)}/download-url`,{method:"POST",body:JSON.stringify(payload)})}async getTenantOverview(){return this.request("/api/tenant/overview")}async getTenantEffectiveState(){return this.request("/api/tenant/effective-state")}async getTenantWorkbenchNavigation(){return this.request("/api/tenant/workbench/navigation")}async createTenantApp(payload){return this.request("/api/tenant/apps",{method:"POST",body:JSON.stringify(payload)})}async updateTenantApp(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async listAppTemplates(){return this.request("/api/tenant/app-templates")}async createAppTemplate(payload){return this.request("/api/tenant/app-templates",{method:"POST",body:JSON.stringify(payload)})}async getAppTemplate(templateId){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`)}async openAppTemplatePreview(templateId){return this.requestVoid(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/preview`)}async updateAppTemplateSettings(templateId,payload){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteAppTemplate(templateId,payload={}){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}`,{method:"DELETE",body:JSON.stringify(payload)})}async createAppTemplateInitializationTask(templateId,payload){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/initialization-tasks`,{method:"POST",body:JSON.stringify(payload)})}async getAppTemplateInitializationTask(taskId){return this.request(`/api/tenant/app-template-initialization-tasks/${encodeURIComponent(taskId)}`)}async createAppMarketSubmission(templateId,payload={}){return this.request(`/api/tenant/app-templates/${encodeURIComponent(templateId)}/market-submissions`,{method:"POST",body:JSON.stringify(payload)})}async cancelAppMarketSubmission(submissionId){return this.request(`/api/tenant/app-market/submissions/${encodeURIComponent(submissionId)}/cancel`,{method:"POST"})}async listTenantAppMarketSubmissions(options){let url=new URL("/api/tenant/app-market/submissions",this.options.baseUrl);return options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async listAppMarketListings(options){let url=new URL("/api/tenant/app-market/listings",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.tag&&url.searchParams.set("tag",options.tag),this.request(`${url.pathname}${url.search}`)}async listAdminAppMarketListings(options){let url=new URL("/api/admin/app-market/listings",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.tag&&url.searchParams.set("tag",options.tag),this.request(`${url.pathname}${url.search}`)}async getAppMarketListing(listingId){return this.request(`/api/tenant/app-market/listings/${encodeURIComponent(listingId)}`)}async openAppMarketSubmissionPreview(submissionId){return this.requestVoid(`/api/tenant/app-market/submissions/${encodeURIComponent(submissionId)}/preview`)}async createAppMarketInstall(listingId,payload){return this.request(`/api/tenant/app-market/listings/${encodeURIComponent(listingId)}/installs`,{method:"POST",body:JSON.stringify(payload)})}async listAdminAppMarketSubmissions(options){let url=new URL("/api/admin/app-market/submissions",this.options.baseUrl);return options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async approveAppMarketSubmission(submissionId){return this.request(`/api/admin/app-market/submissions/${encodeURIComponent(submissionId)}/approve`,{method:"POST"})}async rejectAppMarketSubmission(submissionId,payload={}){return this.request(`/api/admin/app-market/submissions/${encodeURIComponent(submissionId)}/reject`,{method:"POST",body:JSON.stringify(payload)})}async unlistAppMarketListing(listingId,payload={}){return this.request(`/api/admin/app-market/listings/${encodeURIComponent(listingId)}/unlist`,{method:"POST",body:JSON.stringify(payload)})}async publishAppMarketListing(listingId,payload={}){return this.request(`/api/admin/app-market/listings/${encodeURIComponent(listingId)}/publish`,{method:"POST",body:JSON.stringify(payload)})}async listAdminLightAppLibraries(options){let url=new URL("/api/admin/light-app-library/libraries",this.options.baseUrl);return options?.visibility&&url.searchParams.set("visibility",options.visibility),this.request(`${url.pathname}${url.search}`)}async setAdminLightAppLibraryVisibility(libraryId,payload){return this.request(`/api/admin/light-app-library/libraries/${encodeURIComponent(libraryId)}/visibility`,{method:"POST",body:JSON.stringify(payload)})}async listLightAppLibraryEntries(options){let url=new URL("/api/tenant/light-app-library/entries",this.options.baseUrl);return options?.query&&url.searchParams.set("query",options.query),options?.status&&url.searchParams.set("status",options.status),options?.template_key&&url.searchParams.set("template_key",options.template_key),options?.tag&&url.searchParams.set("tag",options.tag),options?.visibility&&url.searchParams.set("visibility",options.visibility),typeof options?.include_public=="boolean"&&url.searchParams.set("include_public",String(options.include_public)),this.request(`${url.pathname}${url.search}`)}async searchLightAppLibraryEntries(query){let url=new URL("/api/tenant/light-app-library/entries/search",this.options.baseUrl);return url.searchParams.set("query",query),this.request(`${url.pathname}${url.search}`)}async getLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`)}async createLightAppLibraryEntry(payload){return this.request("/api/tenant/light-app-library/entries",{method:"POST",body:JSON.stringify(payload)})}async updateLightAppLibraryEntry(entryId,payload){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async submitLightAppLibraryEntrySnapshot(entryId,payload){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/snapshots`,{method:"POST",body:JSON.stringify(payload)})}async publishLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/publish`,{method:"POST"})}async unpublishLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/unpublish`,{method:"POST"})}async archiveLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/archive`,{method:"POST"})}async deleteLightAppLibraryEntry(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}`,{method:"DELETE"})}async getLightAppLibraryEntrySource(entryId){return this.request(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source`)}async readLightAppLibraryEntrySourceFile(entryId,path2){let url=new URL(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source/files`,this.options.baseUrl);return url.searchParams.set("path",path2),this.request(`${url.pathname}${url.search}`)}async searchLightAppLibraryEntrySource(entryId,query){let url=new URL(`/api/tenant/light-app-library/entries/${encodeURIComponent(entryId)}/source/search`,this.options.baseUrl);return url.searchParams.set("query",query),this.request(`${url.pathname}${url.search}`)}async listLightAppPrototypeEntries(options){let url=new URL("/api/tenant/prototypes",this.options.baseUrl);return options?.q&&url.searchParams.set("q",options.q),options?.status&&url.searchParams.set("status",options.status),this.request(`${url.pathname}${url.search}`)}async getLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`)}async createLightAppPrototypeEntry(payload){return this.request("/api/tenant/prototypes",{method:"POST",body:JSON.stringify(payload)})}async updateLightAppPrototypeEntry(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async copyLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/copy`,{method:"POST"})}async deleteLightAppPrototypeEntry(entryId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}`,{method:"DELETE"})}async saveLightAppPrototypeCurrentVersion(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/current-version`,{method:"PUT",body:JSON.stringify(payload)})}async submitLightAppPrototypeVersion(entryId,payload){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/versions`,{method:"POST",body:JSON.stringify(payload)})}async getLightAppPrototypeVersion(entryId,versionId){return this.request(`/api/tenant/prototypes/entries/${encodeURIComponent(entryId)}/versions/${encodeURIComponent(versionId)}`)}async deleteTenantApp(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}`,{method:"DELETE"})}async getTenantAppDeletePreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/delete-preview`,{method:"POST"})}async getTenantAppDeleteJob(jobId){return this.request(`/api/tenant/app-delete-jobs/${encodeURIComponent(jobId)}`)}async getTenantAppUndeployPreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/undeploy-preview`,{method:"POST"})}async undeployTenantApp(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/undeploy`,{method:"POST"})}async getTenantAppUndeployJob(jobId){return this.request(`/api/tenant/app-undeploy-jobs/${encodeURIComponent(jobId)}`)}async createBuild(payload){return this.request("/api/builds",{method:"POST",body:JSON.stringify(payload)})}async listBuilds(appId,options){let url=new URL("/api/builds",this.options.baseUrl);return url.searchParams.set("app_id",appId),typeof options?.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async getBuildPrecheck(appId,args){let url=new URL("/api/builds/precheck",this.options.baseUrl);return url.searchParams.set("app_id",appId),url.searchParams.set("source_version_id",args.source_version_id),args.build_config?.dockerfile_path&&url.searchParams.set("dockerfile_path",args.build_config.dockerfile_path),args.build_config?.context_subdir&&url.searchParams.set("context_subdir",args.build_config.context_subdir),args.build_config?.target&&url.searchParams.set("target",args.build_config.target),this.request(`${url.pathname}${url.search}`)}async getBuild(buildId){return this.request(`/api/builds/${encodeURIComponent(buildId)}`)}async listBuildEvents(buildId){return this.request(`/api/builds/${encodeURIComponent(buildId)}/events`)}async createLocalBuildSession(payload){return this.request("/api/builds/local-sessions",{method:"POST",body:JSON.stringify(payload)})}async completeLocalBuildSession(buildId,payload){return this.request(`/api/builds/${encodeURIComponent(buildId)}/local-complete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppSourceWorkspace(appId,options){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/source-workspace`,this.options.baseUrl);return options?.sourceVersionId&&url.searchParams.set("source_version_id",options.sourceVersionId),this.request(`${url.pathname}${url.search}`)}async getTenantAppDevWorkspace(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace`)}async pushTenantAppDevWorkspace(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/push`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(payload)})}async createTenantAppDevWorkspacePreview(appId,payload={}){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/preview`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppDevWorkspacePreview(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/dev-workspace/preview`)}async listTenantAppSourceVersions(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions`)}async updateTenantAppSourceVersion(appId,sourceVersionId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}`,{method:"PATCH",body:JSON.stringify(payload)})}async getTenantAppEndUserAuthConfig(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/config`)}async getTenantAppEndUserAuthDiscovery(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/discovery`)}async getTenantAppEndUserAuthInspect(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/inspect`)}async configureTenantAppEndUserAuth(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/configure`,{method:"POST",body:JSON.stringify(payload)})}async bindTenantAppEndUserAuth(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/bind`,{method:"POST",body:JSON.stringify(payload)})}async listTenantAppEndUsers(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users`)}async listTenantAppEndUserRoles(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles`)}async createTenantAppEndUserRole(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppEndUserRole(appId,roleKey){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles/${encodeURIComponent(roleKey)}`)}async updateTenantAppEndUserRole(appId,roleKey,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/roles/${encodeURIComponent(roleKey)}`,{method:"PATCH",body:JSON.stringify(payload)})}async listTenantAppUserRoles(appId,appUserId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles`)}async assignTenantAppUserRoles(appId,appUserId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles:assign`,{method:"POST",body:JSON.stringify(payload)})}async replaceTenantAppUserRoles(appId,appUserId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles`,{method:"PUT",body:JSON.stringify(payload)})}async removeTenantAppUserRole(appId,appUserId,roleKey){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/end-user-auth/app-users/${encodeURIComponent(appUserId)}/roles/${encodeURIComponent(roleKey)}`,{method:"DELETE"})}async discoverTenantCmsCollection(collection){let url=new URL("/api/tenant/cms/discover",this.options.baseUrl);return url.searchParams.set("collection",collection),this.request(`${url.pathname}${url.search}`)}async listTenantCmsCollections(){return this.request("/api/tenant/cms/collections")}async inspectTenantCmsSchema(collection){let url=new URL("/api/tenant/cms/inspect/schema",this.options.baseUrl);return url.searchParams.set("collection",collection),this.request(`${url.pathname}${url.search}`)}async listTenantCmsItems(args){let url=new URL("/api/tenant/cms/items",this.options.baseUrl);return url.searchParams.set("collection",args.collection),typeof args.page=="number"&&Number.isFinite(args.page)&&url.searchParams.set("page",String(args.page)),typeof args.pageSize=="number"&&Number.isFinite(args.pageSize)&&url.searchParams.set("page_size",String(args.pageSize)),setOptionalSearchParam(url,"category_id",args.categoryId),setOptionalSearchParam(url,"status",args.status),setOptionalSearchParam(url,"q",args.query),this.request(`${url.pathname}${url.search}`)}async getTenantCmsItem(args){let url=new URL(`/api/tenant/cms/items/${encodeURIComponent(args.id)}`,this.options.baseUrl);return url.searchParams.set("collection",args.collection),this.request(`${url.pathname}${url.search}`)}async configureTenantCmsCollection(spec){return this.request("/api/tenant/cms/configure/collection",{method:"POST",body:JSON.stringify(spec)})}async configureTenantCmsItem(payload){return this.request("/api/tenant/cms/configure/item",{method:"POST",body:JSON.stringify(payload)})}async configureTenantCmsCategory(payload){return this.request("/api/tenant/cms/configure/category",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsSchema(payload){return this.request("/api/tenant/cms/apply/schema",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsCollectionStatus(payload){return this.request("/api/tenant/cms/apply/collection-status",{method:"POST",body:JSON.stringify(payload)})}async applyTenantCmsPublish(payload){return this.request("/api/tenant/cms/apply/publish",{method:"POST",body:JSON.stringify(payload)})}async listPublicCmsItems(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items`,this.options.baseUrl);url.searchParams.set("tenant_id",args.tenantId),typeof args.page=="number"&&Number.isFinite(args.page)&&url.searchParams.set("page",String(args.page)),typeof args.pageSize=="number"&&Number.isFinite(args.pageSize)&&url.searchParams.set("page_size",String(args.pageSize)),setOptionalSearchParam(url,"category_id",args.categoryId),setOptionalSearchParam(url,"sort_field",args.sortField),setOptionalSearchParam(url,"sort_direction",args.sortDirection);for(let tag of args.tags??[])url.searchParams.append("tag",tag);return this.request(`${url.pathname}${url.search}`)}async getPublicCmsItemBySlug(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items/by-slug/${encodeURIComponent(args.slug)}`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async getPublicCmsItemById(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/items/${encodeURIComponent(args.id)}`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async listPublicCmsCategories(args){let url=new URL(`/api/public/cms/collections/${encodeURIComponent(args.collection)}/categories`,this.options.baseUrl);return url.searchParams.set("tenant_id",args.tenantId),this.request(`${url.pathname}${url.search}`)}async listTenantAppDeploymentTimeline(appId,options){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/deployments`,this.options.baseUrl);return typeof options?.limit=="number"&&Number.isFinite(options.limit)&&url.searchParams.set("limit",String(options.limit)),this.request(`${url.pathname}${url.search}`)}async getTenantAppPublishSettings(appId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings`)}async updateTenantAppPublishSettings(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings`,{method:"PATCH",body:JSON.stringify(payload)})}async setTenantAppCurrentPublishedVersion(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/publish-settings/current-version`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppPreview(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/previews`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppSourceVersion(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions`,{method:"POST",body:JSON.stringify(payload)})}async createTenantAppSourceVersionFromTemplate(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions:from-template`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppReleaseDeletePreview(appId,releaseId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/releases/${encodeURIComponent(releaseId)}/delete-preview`,{method:"POST"})}async deleteTenantAppRelease(appId,releaseId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/releases/${encodeURIComponent(releaseId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppSourceVersionDeletePreview(appId,sourceVersionId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}/delete-preview`,{method:"POST"})}async deleteTenantAppSourceVersion(appId,sourceVersionId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/source-versions/${encodeURIComponent(sourceVersionId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantVersionDeleteJob(jobId){return this.request(`/api/tenant/version-delete-jobs/${encodeURIComponent(jobId)}`)}async getTenantAppBuildDeletePreview(appId,buildId){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/builds/${encodeURIComponent(buildId)}/delete-preview`,{method:"POST"})}async deleteTenantAppBuild(appId,buildId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/builds/${encodeURIComponent(buildId)}/delete`,{method:"POST",body:JSON.stringify(payload)})}async getTenantAppDbInstance(appId,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbRuntimeBindings(appId,env="preview",purpose){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/runtime-bindings`,this.options.baseUrl);return url.searchParams.set("env",env),purpose&&url.searchParams.set("purpose",purpose),this.requestUrl(url)}async resolveDevRuntimeBindings(payload){return this.request("/api/dev-runtime-bindings/resolve",{method:"POST",body:JSON.stringify(payload)})}async revokeDevRuntimeBindings(payload){return this.request("/api/dev-runtime-bindings/revoke",{method:"POST",body:JSON.stringify(payload)})}async listTenantAppDbTables(appId,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbTableSchema(appId,tableName,env="preview"){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/schema`,this.options.baseUrl);return url.searchParams.set("env",env),this.requestUrl(url)}async getTenantAppDbTableRows(appId,tableName,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.page=="number"&&url.searchParams.set("page",String(args.page)),typeof args.page_size=="number"&&url.searchParams.set("page_size",String(args.page_size)),typeof args.sort_by=="string"&&args.sort_by.trim().length>0&&url.searchParams.set("sort_by",args.sort_by),args.sort_order==="desc"&&url.searchParams.set("sort_order","desc"),typeof args.filter_column=="string"&&args.filter_column.trim().length>0&&url.searchParams.set("filter_column",args.filter_column),typeof args.filter_value=="string"&&args.filter_value.length>0&&url.searchParams.set("filter_value",args.filter_value),typeof args.search_query=="string"&&args.search_query.trim().length>0&&url.searchParams.set("search_query",args.search_query),this.requestUrl(url)}async listTenantAppDbMigrationRuns(appId,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/migrations`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.limit=="number"&&url.searchParams.set("limit",String(args.limit)),this.requestUrl(url)}async listTenantAppDbChangeAudits(appId,args={}){let url=new URL(`/api/tenant/apps/${encodeURIComponent(appId)}/db/audits`,this.options.baseUrl);return url.searchParams.set("env",args.env??"preview"),typeof args.table_name=="string"&&args.table_name.trim().length>0&&url.searchParams.set("table_name",args.table_name),typeof args.limit=="number"&&url.searchParams.set("limit",String(args.limit)),this.requestUrl(url)}async insertTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"POST",body:JSON.stringify(payload)})}async updateTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"PATCH",body:JSON.stringify(payload)})}async deleteTenantAppDbRow(appId,tableName,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/tables/${encodeURIComponent(tableName)}/rows`,{method:"DELETE",body:JSON.stringify(payload)})}async queryTenantAppDb(appId,payload){return this.request(`/api/tenant/apps/${encodeURIComponent(appId)}/db/query`,{method:"POST",body:JSON.stringify(payload)})}async createWorkspace(payload){return this.request("/api/admin/workspaces",{method:"POST",body:JSON.stringify(payload)})}async deleteWorkspace(workspaceId,payload){return this.request(`/api/admin/workspaces/${encodeURIComponent(workspaceId)}`,{method:"DELETE",...payload?{body:JSON.stringify(payload)}:{}})}async createApproval(payload){return this.request("/api/admin/resource-approvals",{method:"POST",body:JSON.stringify(payload)})}async listApprovals(filters){let url=new URL("/api/admin/resource-approvals",this.options.baseUrl);return filters?.tenant_id&&url.searchParams.set("tenant_id",filters.tenant_id),filters?.app_id&&url.searchParams.set("app_id",filters.app_id),filters?.status&&url.searchParams.set("status",filters.status),filters?.operation&&url.searchParams.set("operation",filters.operation),this.requestUrl(url)}async decideApproval(approvalId,payload){return this.request(`/api/admin/resource-approvals/${approvalId}/decision`,{method:"POST",body:JSON.stringify(payload)})}async listResourceLocks(filters){let url=new URL("/api/admin/resource-locks",this.options.baseUrl);return filters?.tenant_id&&url.searchParams.set("tenant_id",filters.tenant_id),filters?.app_id&&url.searchParams.set("app_id",filters.app_id),filters?.env&&url.searchParams.set("env",filters.env),this.requestUrl(url)}async diffResources(payload){return this.request("/api/resources/diff",{method:"POST",body:JSON.stringify(payload)})}async applyResources(payload){return this.request("/api/resources/apply",{method:"POST",body:JSON.stringify(payload)})}async rollbackResources(payload){return this.request("/api/resources/rollback",{method:"POST",body:JSON.stringify(payload)})}async deployRelease(payload){return this.request("/api/releases/deploy",{method:"POST",body:JSON.stringify(payload)})}async rollbackRelease(payload){return this.request("/api/releases/rollback",{method:"POST",body:JSON.stringify(payload)})}async queryLogs(payload){return this.request("/api/logs/query",{method:"POST",body:JSON.stringify(payload)})}};function setOptionalSearchParam(url,key,value){typeof value=="string"&&value.trim().length>0&&url.searchParams.set(key,value)}function setOptionalBooleanSearchParam(url,key,value){typeof value=="boolean"&&url.searchParams.set(key,value?"true":"false")}function resolveRelativeOrAbsoluteUrl(pathOrUrl,baseUrl){return new URL(pathOrUrl,baseUrl)}function createPlatformSdk(options){return new PlatformSdk(options)}var NotificationSdkNamespace=class{sdk;endUser;constructor(sdk){this.sdk=sdk,this.endUser=new EndUserNotificationNamespace(sdk)}},EndUserNotificationNamespace=class{sdk;constructor(sdk){this.sdk=sdk}forApp(appId){return new EndUserNotificationAppClient(this.sdk,appId)}},EndUserNotificationAppClient=class{sdk;appId;announcements;constructor(sdk,appId){this.sdk=sdk,this.appId=appId,this.announcements=new EndUserNotificationAppAnnouncementsClient(sdk,appId)}listUsers(){return this.sdk.listTenantAppEndUsers(this.appId)}forUser(endUserId){return new EndUserNotificationUserClient(this.sdk,this.appId,endUserId)}listInbox(endUserId,query={}){return this.sdk.listEndUserNotificationInbox(this.appId,{end_user_id:endUserId,...query})}getUnreadCount(endUserId){return this.sdk.getEndUserNotificationUnreadCount(this.appId,endUserId)}publish(input){return this.sdk.publishEndUserNotification(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),title:input.title,body:input.body??null,notification_type:input.notification_type??"notification",object_ref:input.object_ref,action_ref:input.action_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("publish",this.appId,input.end_user_id),deliver_to:input.deliver_to})}remind(input){return this.sdk.createEndUserNotificationReminder(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),remind_at:input.remind_at,title:input.title,body:input.body??null,object_ref:input.object_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("reminder",this.appId,input.end_user_id)})}projectTask(input){return this.sdk.projectEndUserTaskNotification(this.appId,{recipient:buildDirectEndUserRecipientRef(this.appId,input.end_user_id),source_task_ref:input.source_task_ref,title:input.title,summary:input.summary??null,due_at:input.due_at??null,source_event_id:input.source_event_id??null,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("task-projection",this.appId,input.end_user_id)})}},EndUserNotificationAppAnnouncementsClient=class{sdk;appId;constructor(sdk,appId){this.sdk=sdk,this.appId=appId}getConfig(){return this.sdk.getAppNotificationConfig(this.appId)}list(limit){return this.sdk.listAppNotificationAnnouncements(this.appId,{limit})}create(input){return this.sdk.createAppNotificationAnnouncement(this.appId,input)}archive(announcementId){return this.sdk.archiveAppNotificationAnnouncement(this.appId,announcementId)}},EndUserNotificationUserClient=class{sdk;appId;endUserId;constructor(sdk,appId,endUserId){this.sdk=sdk,this.appId=appId,this.endUserId=endUserId}buildRecipientRef(){return buildDirectEndUserRecipientRef(this.appId,this.endUserId)}listInbox(query={}){return this.sdk.listEndUserNotificationInbox(this.appId,{end_user_id:this.endUserId,...query})}getUnreadCount(){return this.sdk.getEndUserNotificationUnreadCount(this.appId,this.endUserId)}publish(input){return this.sdk.publishEndUserNotification(this.appId,{recipient:this.buildRecipientRef(),title:input.title,body:input.body??null,notification_type:input.notification_type??"notification",object_ref:input.object_ref,action_ref:input.action_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("publish",this.appId,this.endUserId),deliver_to:input.deliver_to})}remind(input){return this.sdk.createEndUserNotificationReminder(this.appId,{recipient:this.buildRecipientRef(),remind_at:input.remind_at,title:input.title,body:input.body??null,object_ref:input.object_ref,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("reminder",this.appId,this.endUserId)})}projectTask(input){return this.sdk.projectEndUserTaskNotification(this.appId,{recipient:this.buildRecipientRef(),source_task_ref:input.source_task_ref,title:input.title,summary:input.summary??null,due_at:input.due_at??null,source_event_id:input.source_event_id??null,idempotency_key:input.idempotency_key??buildNotificationIdempotencyKey("task-projection",this.appId,this.endUserId)})}};function buildDirectEndUserRecipientRef(appId,endUserId){return{app_id:appId,end_user_id:endUserId,recipient_type:"direct_user"}}function buildNotificationIdempotencyKey(prefix,appId,endUserId){return`${prefix}:${appId}:${endUserId}:${Date.now()}`}var AUTH_PAGE_HTML=String.raw`<!doctype html>
3
3
  <html lang="zh-CN">
4
4
  <head>
5
5
  <meta charset="utf-8" />
@@ -1383,9 +1383,8 @@ function setupSignInMethodActions() {
1383
1383
 
1384
1384
  setupSignInMethodActions();`,AUTH_RUNTIME_ACTION_SECTION_SOURCE=[AUTH_RUNTIME_EMAIL_MAGIC_LINK_ACTIONS_SOURCE,AUTH_RUNTIME_PASSWORD_ACTIONS_SOURCE,AUTH_RUNTIME_PHONE_SMS_OTP_ACTIONS_SOURCE,AUTH_RUNTIME_DYNAMIC_METHOD_ACTIONS_SOURCE,AUTH_RUNTIME_ACTION_REGISTRY_SOURCE].join(`
1385
1385
 
1386
- `);var PREVIEW_TYPED_PATH_PATTERN="^/previews/([rs])/(t-[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:/|$)",PREVIEW_TENANT_PATH_PATTERN="^/previews/(t-[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:/|$)",PREVIEW_LEGACY_PATH_PATTERN="^/previews/(?!(?:[rs]|t-[^/]+)/)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:/|$)",PROD_PATH_PATTERN="^/apps/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)/([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:/|$)";function buildInlineParsePlatformPathSource(functionName="parsePlatformPath"){return[`function ${functionName}(pathname) {`,` const typedPreviewMatch = pathname.match(new RegExp(${JSON.stringify(PREVIEW_TYPED_PATH_PATTERN)}));`," if (typedPreviewMatch) {"," const routeBasePath = '/previews/' + typedPreviewMatch[1] + '/' + typedPreviewMatch[2] + '/' + typedPreviewMatch[3] + '/' + typedPreviewMatch[4];"," return { kind: 'typed-preview', mode: 'preview', routeMode: 'path', routeKind: typedPreviewMatch[1] === 's' ? 'static' : 'runtime', tenantId: typedPreviewMatch[2], appId: typedPreviewMatch[3], releaseId: typedPreviewMatch[4], routeBasePath, upstreamPath: inferInlineUpstreamPath(pathname, routeBasePath) };"," }",` const tenantPreviewMatch = pathname.match(new RegExp(${JSON.stringify(PREVIEW_TENANT_PATH_PATTERN)}));`," if (tenantPreviewMatch) {"," const routeBasePath = '/previews/' + tenantPreviewMatch[1] + '/' + tenantPreviewMatch[2] + '/' + tenantPreviewMatch[3];"," return { kind: 'tenant-preview', mode: 'preview', routeMode: 'path', routeKind: 'runtime', tenantId: tenantPreviewMatch[1], appId: tenantPreviewMatch[2], releaseId: tenantPreviewMatch[3], routeBasePath, upstreamPath: inferInlineUpstreamPath(pathname, routeBasePath) };"," }",` const previewMatch = pathname.match(new RegExp(${JSON.stringify(PREVIEW_LEGACY_PATH_PATTERN)}));`," if (previewMatch) {"," const routeBasePath = '/previews/' + previewMatch[1] + '/' + previewMatch[2];"," return { kind: 'legacy-preview', mode: 'preview', routeMode: 'path', routeKind: 'static', tenantId: '', appId: previewMatch[1], releaseId: previewMatch[2], routeBasePath, upstreamPath: inferInlineUpstreamPath(pathname, routeBasePath) };"," }",` const prodMatch = pathname.match(new RegExp(${JSON.stringify(PROD_PATH_PATTERN)}));`," if (prodMatch) {"," const routeBasePath = '/apps/' + prodMatch[1] + '/' + prodMatch[2];"," return { kind: 'prod-path', mode: 'prod-path', routeMode: 'path', routeKind: 'runtime', tenantId: prodMatch[1], appId: prodMatch[2], routeBasePath, upstreamPath: inferInlineUpstreamPath(pathname, routeBasePath) };"," }"," return null;","}","function inferInlineUpstreamPath(pathname, routeBasePath) {"," if (pathname === routeBasePath || pathname === routeBasePath + '/') {"," return '/';"," }"," if (pathname.startsWith(routeBasePath + '/')) {"," return pathname.slice(routeBasePath.length) || '/';"," }"," return '/';","}"].join(`
1387
- `)}function buildPathRouteHelpersSource(options={}){let deriveBasePathName=options.deriveBasePathName||"deriveAppBasePath",buildPathName=options.buildPathName||"buildAppPath",buildAuthPathName=options.buildAuthPathName||"buildAuthPath",pathnameExpression=options.pathnameExpression||"window.location.pathname",defaultReturnToExpression=options.defaultReturnToExpression||`${buildPathName}('/app')`,lines=[buildInlineParsePlatformPathSource("parseCurrentPlatformPath"),`function ${deriveBasePathName}(pathname = ${pathnameExpression}) {`," const parsedPath = parseCurrentPlatformPath(pathname);"," return parsedPath ? parsedPath.routeBasePath : '';","}",`function ${buildPathName}(path) {`," const normalizedPath = typeof path === 'string' && path ? (path.startsWith('/') ? path : '/' + path) : '/';",` const basePath = ${deriveBasePathName}();`," return basePath ? (basePath + normalizedPath) : normalizedPath;","}",`function ${buildAuthPathName}(returnTo) {`,` const targetReturnTo = typeof returnTo === 'string' && returnTo ? returnTo : ${defaultReturnToExpression};`,` return ${buildPathName}('/auth') + '?return_to=' + encodeURIComponent(targetReturnTo);`,"}"];return options.sessionStorageKeyName&&lines.push(`const ${options.sessionStorageKeyName} = 'platform:end-user-auth:' + window.location.origin + ':' + ${buildPathName}('/auth');`),lines.join(`
1388
- `)}var AUTH_RUNTIME_ROOT_HTML=buildAuthRuntimeRootHtml(),AUTH_ROUTE_HELPERS=buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",pathnameExpression:"window.location.pathname",defaultReturnToExpression:"buildAppPath('/app')"}),AUTH_RUNTIME_STATE_SECTION=String.raw`document.body.classList.add('app-auth-page');
1386
+ `);function buildPathRouteHelpersSource(options={}){let deriveBasePathName=options.deriveBasePathName||"deriveAppBasePath",buildPathName=options.buildPathName||"buildAppPath",buildAuthPathName=options.buildAuthPathName||"buildAuthPath",runtimeConfigExpression=options.runtimeConfigExpression||"window.__PLATFORM_RUNTIME_CONFIG__",defaultReturnToExpression=options.defaultReturnToExpression||`${buildPathName}('/app')`,lines=[`function ${deriveBasePathName}() {`,` const injectedRuntimeConfig = ${runtimeConfigExpression};`," const injectedBasePath = injectedRuntimeConfig && typeof injectedRuntimeConfig.basePath === 'string' ? injectedRuntimeConfig.basePath.trim() : '';"," if (!injectedBasePath || injectedBasePath === '/') return '';"," const normalizedBasePath = injectedBasePath.startsWith('/') ? injectedBasePath : '/' + injectedBasePath;"," return normalizedBasePath.replace(/\\/+$/g, '') || '';","}",`function ${buildPathName}(path) {`," const normalizedPath = typeof path === 'string' && path ? (path.startsWith('/') ? path : '/' + path) : '/';",` const basePath = ${deriveBasePathName}();`," return basePath ? (basePath + normalizedPath) : normalizedPath;","}",`function ${buildAuthPathName}(returnTo) {`,` const targetReturnTo = typeof returnTo === 'string' && returnTo ? returnTo : ${defaultReturnToExpression};`,` return ${buildPathName}('/auth') + '?return_to=' + encodeURIComponent(targetReturnTo);`,"}"];return options.sessionStorageKeyName&&lines.push(`const ${options.sessionStorageKeyName} = 'platform:end-user-auth:' + window.location.origin + ':' + ${buildPathName}('/auth');`),lines.join(`
1387
+ `)}var AUTH_RUNTIME_ROOT_HTML=buildAuthRuntimeRootHtml(),AUTH_ROUTE_HELPERS=buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",runtimeConfigExpression:"window.__PLATFORM_RUNTIME_CONFIG__",defaultReturnToExpression:"buildAppPath('/app')"}),AUTH_RUNTIME_STATE_SECTION=String.raw`document.body.classList.add('app-auth-page');
1389
1388
 
1390
1389
  ${AUTH_ROUTE_HELPERS}
1391
1390
  const search = new URLSearchParams(window.location.search);
@@ -1793,7 +1792,7 @@ function resolveBootstrapFeedback(error) {
1793
1792
  </style>
1794
1793
  <script>
1795
1794
  (function guardProtectedAppPage() {
1796
- ${buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",pathnameExpression:"window.location.pathname",defaultReturnToExpression:"buildAppPath('/app')"})}
1795
+ ${buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",runtimeConfigExpression:"window.__PLATFORM_RUNTIME_CONFIG__",defaultReturnToExpression:"buildAppPath('/app')"})}
1797
1796
  document.documentElement.classList.add('app-protected-guard');
1798
1797
  try {
1799
1798
  const token = window.sessionStorage.getItem(SESSION_STORAGE_KEY) || '';
@@ -1825,7 +1824,7 @@ function resolveBootstrapFeedback(error) {
1825
1824
  </div>
1826
1825
  </main>
1827
1826
  <script type="module">
1828
- ${buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",pathnameExpression:"window.location.pathname",defaultReturnToExpression:"buildAppPath('/app')"})}
1827
+ ${buildPathRouteHelpersSource({deriveBasePathName:"deriveAppBasePath",buildPathName:"buildAppPath",buildAuthPathName:"buildAuthPath",sessionStorageKeyName:"SESSION_STORAGE_KEY",runtimeConfigExpression:"window.__PLATFORM_RUNTIME_CONFIG__",defaultReturnToExpression:"buildAppPath('/app')"})}
1829
1828
  const statusEl = document.getElementById('app-status');
1830
1829
  const identityEl = document.getElementById('app-identity');
1831
1830
  const appUserEl = document.getElementById('app-app-user');
@@ -2122,7 +2121,7 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2122
2121
  }
2123
2122
  return "/";
2124
2123
  }
2125
- `}import{existsSync,readdirSync,readFileSync,statSync}from"node:fs";import{createRequire}from"node:module";import{dirname,resolve,posix as pathPosix2}from"node:path";import{fileURLToPath}from"node:url";function resolveRuntimeSdkDistDirForTest({workspaceCandidates,exists,isDirectory,resolvePackageEntrypoint}){let workspaceDir=workspaceCandidates.find(candidate=>exists(candidate)&&isDirectory(candidate));if(workspaceDir)return workspaceDir;try{let runtimeSdkEntrypoint=resolvePackageEntrypoint(),packagedDir=dirname(runtimeSdkEntrypoint);if(exists(packagedDir)&&isDirectory(packagedDir))return packagedDir}catch{}throw new Error(`Missing runtime-sdk dist directory for template vendor scaffold. Checked ${workspaceCandidates.map(candidate=>resolve(candidate)).join(", ")} and package entrypoint @platform/runtime-sdk.`)}function resolveRuntimeSdkDistDir(){let require2=createRequire(import.meta.url),workspaceCandidates=[new URL("../../../../runtime-sdk/dist/",import.meta.url),new URL("../../../../../runtime-sdk/dist/",import.meta.url)].map(candidate=>fileURLToPath(candidate));return resolveRuntimeSdkDistDirForTest({workspaceCandidates,exists:existsSync,isDirectory:path=>statSync(path).isDirectory(),resolvePackageEntrypoint:()=>require2.resolve("@platform/runtime-sdk")})}function collectRuntimeSdkDistFiles(dirPath,relativeDir=""){let entries=readdirSync(dirPath,{withFileTypes:!0}).sort((a,b)=>a.name.localeCompare(b.name)),files=[];for(let entry of entries){let nextRelativePath=relativeDir?`${relativeDir}/${entry.name}`:entry.name,entryPath=resolve(dirPath,entry.name);if(entry.isDirectory()){files.push(...collectRuntimeSdkDistFiles(entryPath,nextRelativePath));continue}entry.name.includes(".test.")||/\.(?:js|d\.ts)$/u.test(entry.name)&&files.push({path:nextRelativePath,content:readFileSync(entryPath,"utf8")})}return files}function buildVendorRoot(prefix){let normalizedPrefix=prefix.replace(/^\/+|\/+$/gu,""),prefixDir=normalizedPrefix.includes("/")?pathPosix2.dirname(normalizedPrefix):normalizedPrefix;return prefixDir==="."?"vendor/runtime-sdk":`${prefixDir}/vendor/runtime-sdk`}function buildRuntimeSdkVendorFiles(prefix){let vendorRoot=buildVendorRoot(prefix);return collectRuntimeSdkDistFiles(resolveRuntimeSdkDistDir()).map(file=>({path:`${vendorRoot}/${file.path}`,content:file.content}))}function buildPrefixedPath3(prefix,relativePath){return`${prefix.replace(/\/+$/u,"")}/${relativePath}`}function readTemplateBlockSource(relativePath){let fileUrl=[new URL(`../../template-blocks/${relativePath}`,import.meta.url),new URL(`../../../src/template-blocks/${relativePath}`,import.meta.url)].find(candidate=>existsSync2(candidate));if(!fileUrl)throw new Error(`Missing template block source for ${relativePath}`);return readFileSync2(fileUrl,"utf8")}function scaffoldTemplateBlock(relativePath,outputPath){return relativePath==="contract/route-path-patterns.ts"?{path:outputPath,content:buildRoutePathPatternsSource()}:{path:outputPath,content:readTemplateBlockSource(relativePath)}}function buildWebSharedPlatformFiles(prefix,builders){let platformPrefix=buildPrefixedPath3(prefix,"platform");return[...buildRuntimeSdkVendorFiles(prefix),scaffoldTemplateBlock("contract/capabilities.ts",`${platformPrefix}/contract/capabilities.ts`),scaffoldTemplateBlock("contract/route-path-patterns.ts",`${platformPrefix}/contract/route-path-patterns.ts`),scaffoldTemplateBlock("contract/runtime-config.ts",`${platformPrefix}/contract/runtime-config.ts`),scaffoldTemplateBlock("contract/path-builders.ts",`${platformPrefix}/contract/path-builders.ts`),scaffoldTemplateBlock("protocol/auth-routes.ts",`${platformPrefix}/protocol/auth-routes.ts`),scaffoldTemplateBlock("protocol/public-app-routes.ts",`${platformPrefix}/protocol/public-app-routes.ts`),scaffoldTemplateBlock("protocol/cms-routes.ts",`${platformPrefix}/protocol/cms-routes.ts`),scaffoldTemplateBlock("protocol/route-map.ts",`${platformPrefix}/protocol/route-map.ts`),scaffoldTemplateBlock("dev-support/vite/runtime-config.ts",`${platformPrefix}/dev/vite/runtime-config.ts`),scaffoldTemplateBlock("dev-support/vite/auth-shell.ts",`${platformPrefix}/dev/vite/auth-shell.ts`),scaffoldTemplateBlock("dev-support/vite/proxy.ts",`${platformPrefix}/dev/vite/proxy.ts`),{path:`${platformPrefix}/config.ts`,content:builders.buildPlatformConfigSource()},{path:`${platformPrefix}/client.ts`,content:builders.buildPlatformClientSource(prefix)},{path:`${platformPrefix}/errors.ts`,content:builders.buildPlatformErrorsSource()},{path:`${platformPrefix}/capabilities/index.ts`,content:builders.buildCapabilitiesIndexSource()},{path:`${platformPrefix}/capabilities/auth.ts`,content:builders.buildCapabilitySource("auth",prefix)},{path:`${platformPrefix}/capabilities/workflow.ts`,content:builders.buildCapabilitySource("workflow",prefix)},{path:`${platformPrefix}/capabilities/cms.ts`,content:builders.buildCapabilitySource("cms",prefix)},{path:`${platformPrefix}/capabilities/blob.ts`,content:builders.buildCapabilitySource("blob",prefix)},{path:`${platformPrefix}/capabilities/data-form.ts`,content:builders.buildCapabilitySource("data-form",prefix)}]}import{posix as pathPosix3}from"node:path";function buildPlatformConfigSource(){return['import { getRuntimeConfig, type PlatformRuntimeConfig } from "./contract/runtime-config";',"","export type FrontendPlatformConfig = PlatformRuntimeConfig;","","export function getPlatformConfig(): FrontendPlatformConfig {"," return getRuntimeConfig();","}",""].join(`
2124
+ `}import{existsSync,readdirSync,readFileSync,statSync}from"node:fs";import{createRequire}from"node:module";import{dirname,resolve,posix as pathPosix2}from"node:path";import{fileURLToPath}from"node:url";function resolveRuntimeSdkDistDirForTest({workspaceCandidates,exists,isDirectory,resolvePackageEntrypoint}){let workspaceDir=workspaceCandidates.find(candidate=>exists(candidate)&&isDirectory(candidate));if(workspaceDir)return workspaceDir;try{let runtimeSdkEntrypoint=resolvePackageEntrypoint(),packagedDir=dirname(runtimeSdkEntrypoint);if(exists(packagedDir)&&isDirectory(packagedDir))return packagedDir}catch{}throw new Error(`Missing runtime-sdk dist directory for template vendor scaffold. Checked ${workspaceCandidates.map(candidate=>resolve(candidate)).join(", ")} and package entrypoint @platform/runtime-sdk.`)}function resolveRuntimeSdkDistDir(){let require2=createRequire(import.meta.url),workspaceCandidates=[new URL("../../../../runtime-sdk/dist/",import.meta.url),new URL("../../../../../runtime-sdk/dist/",import.meta.url)].map(candidate=>fileURLToPath(candidate));return resolveRuntimeSdkDistDirForTest({workspaceCandidates,exists:existsSync,isDirectory:path2=>statSync(path2).isDirectory(),resolvePackageEntrypoint:()=>require2.resolve("@platform/runtime-sdk")})}function collectRuntimeSdkDistFiles(dirPath,relativeDir=""){let entries=readdirSync(dirPath,{withFileTypes:!0}).sort((a,b)=>a.name.localeCompare(b.name)),files=[];for(let entry of entries){let nextRelativePath=relativeDir?`${relativeDir}/${entry.name}`:entry.name,entryPath=resolve(dirPath,entry.name);if(entry.isDirectory()){files.push(...collectRuntimeSdkDistFiles(entryPath,nextRelativePath));continue}entry.name.includes(".test.")||/\.(?:js|d\.ts)$/u.test(entry.name)&&files.push({path:nextRelativePath,content:readFileSync(entryPath,"utf8")})}return files}function buildVendorRoot(prefix){let normalizedPrefix=prefix.replace(/^\/+|\/+$/gu,""),prefixDir=normalizedPrefix.includes("/")?pathPosix2.dirname(normalizedPrefix):normalizedPrefix;return prefixDir==="."?"vendor/runtime-sdk":`${prefixDir}/vendor/runtime-sdk`}function buildRuntimeSdkVendorFiles(prefix){let vendorRoot=buildVendorRoot(prefix);return collectRuntimeSdkDistFiles(resolveRuntimeSdkDistDir()).map(file=>({path:`${vendorRoot}/${file.path}`,content:file.content}))}function buildPrefixedPath3(prefix,relativePath){return`${prefix.replace(/\/+$/u,"")}/${relativePath}`}function readTemplateBlockSource(relativePath){let fileUrl=[new URL(`../../template-blocks/${relativePath}`,import.meta.url),new URL(`../../../src/template-blocks/${relativePath}`,import.meta.url)].find(candidate=>existsSync2(candidate));if(!fileUrl)throw new Error(`Missing template block source for ${relativePath}`);return readFileSync2(fileUrl,"utf8")}function scaffoldTemplateBlock(relativePath,outputPath){return relativePath==="contract/route-path-patterns.ts"?{path:outputPath,content:buildRoutePathPatternsSource()}:{path:outputPath,content:readTemplateBlockSource(relativePath)}}function buildWebSharedPlatformFiles(prefix,builders){let platformPrefix=buildPrefixedPath3(prefix,"platform");return[...buildRuntimeSdkVendorFiles(prefix),scaffoldTemplateBlock("contract/capabilities.ts",`${platformPrefix}/contract/capabilities.ts`),scaffoldTemplateBlock("contract/runtime-config.ts",`${platformPrefix}/contract/runtime-config.ts`),scaffoldTemplateBlock("contract/path-builders.ts",`${platformPrefix}/contract/path-builders.ts`),scaffoldTemplateBlock("protocol/auth-routes.ts",`${platformPrefix}/protocol/auth-routes.ts`),scaffoldTemplateBlock("protocol/public-app-routes.ts",`${platformPrefix}/protocol/public-app-routes.ts`),scaffoldTemplateBlock("protocol/cms-routes.ts",`${platformPrefix}/protocol/cms-routes.ts`),scaffoldTemplateBlock("protocol/route-map.ts",`${platformPrefix}/protocol/route-map.ts`),scaffoldTemplateBlock("dev-support/vite/runtime-config.ts",`${platformPrefix}/dev/vite/runtime-config.ts`),scaffoldTemplateBlock("dev-support/vite/auth-shell.ts",`${platformPrefix}/dev/vite/auth-shell.ts`),scaffoldTemplateBlock("dev-support/vite/proxy.ts",`${platformPrefix}/dev/vite/proxy.ts`),{path:`${platformPrefix}/config.ts`,content:builders.buildPlatformConfigSource()},{path:`${platformPrefix}/client.ts`,content:builders.buildPlatformClientSource(prefix)},{path:`${platformPrefix}/errors.ts`,content:builders.buildPlatformErrorsSource()},{path:`${platformPrefix}/capabilities/index.ts`,content:builders.buildCapabilitiesIndexSource()},{path:`${platformPrefix}/capabilities/auth.ts`,content:builders.buildCapabilitySource("auth",prefix)},{path:`${platformPrefix}/capabilities/workflow.ts`,content:builders.buildCapabilitySource("workflow",prefix)},{path:`${platformPrefix}/capabilities/cms.ts`,content:builders.buildCapabilitySource("cms",prefix)},{path:`${platformPrefix}/capabilities/blob.ts`,content:builders.buildCapabilitySource("blob",prefix)},{path:`${platformPrefix}/capabilities/data-form.ts`,content:builders.buildCapabilitySource("data-form",prefix)}]}import{posix as pathPosix3}from"node:path";function buildPlatformConfigSource(){return['import { getRuntimeConfig, type PlatformRuntimeConfig } from "./contract/runtime-config";',"","export type FrontendPlatformConfig = PlatformRuntimeConfig;","","export function getPlatformConfig(): FrontendPlatformConfig {"," return getRuntimeConfig();","}",""].join(`
2126
2125
  `)}function buildVendorRuntimeImport2(prefix,fromRelativeDir,runtimeSdkPath){let normalizedPrefix=prefix.replace(/^\/+|\/+$/gu,""),vendorBase=normalizedPrefix.includes("/")?pathPosix3.join(pathPosix3.dirname(normalizedPrefix),"vendor/runtime-sdk"):pathPosix3.join(normalizedPrefix,"vendor/runtime-sdk"),fromDir=pathPosix3.join(normalizedPrefix,fromRelativeDir),relativePath=pathPosix3.relative(fromDir,pathPosix3.join(vendorBase,runtimeSdkPath));return relativePath.startsWith(".")?relativePath:`./${relativePath}`}function buildPlatformClientSource(prefix="src"){return[`import { createBrowserRuntimeApp } from "${buildVendorRuntimeImport2(prefix,"platform","browser.js")}";`,'import { buildPlatformAbsoluteUrl as buildPlatformAbsoluteUrlFromContract, buildPlatformAuthPath as buildPlatformAuthPathFromContract, buildPlatformPath as buildPlatformPathFromContract } from "./contract/path-builders";','import { getPlatformConfig } from "./config";','import { PlatformRuntimeUnavailableError } from "./errors";',"","let runtimeApp: ReturnType<typeof createBrowserRuntimeApp> | null = null;","",'export function buildPlatformPath(path = "/") {'," return buildPlatformPathFromContract(getPlatformConfig(), path);","}","",'export function buildPlatformAbsoluteUrl(path = "/") {'," return buildPlatformAbsoluteUrlFromContract(getPlatformConfig(), path);","}","","export function buildPlatformAuthPath() {"," return buildPlatformAuthPathFromContract(getPlatformConfig());","}","","export function getPlatformRuntimeContext() {"," return getPlatformConfig();","}","","export { getPlatformConfig };","","export function hasPlatformRuntimeBinding() {"," return Boolean(getPlatformRuntimeContext().appId);","}","","export function getPlatformRuntimeApp() {"," if (runtimeApp) {"," return runtimeApp;"," }"," const config = getPlatformRuntimeContext();"," if (!config.appId) {",' throw new PlatformRuntimeUnavailableError("platform appId is not available in current location context");'," }"," runtimeApp = createBrowserRuntimeApp({",' baseUrl: buildPlatformAbsoluteUrl("/"),'," appId: config.appId,"," env: config.env || undefined,"," authPath: buildPlatformAuthPath(),"," sessionOptions: { authPath: buildPlatformAuthPath() },"," });"," return runtimeApp;","}","","export function tryGetPlatformRuntimeApp() {"," return hasPlatformRuntimeBinding() ? getPlatformRuntimeApp() : null;","}",""].join(`
2127
2126
  `)}function buildPlatformErrorsSource(){return["export class PlatformRuntimeUnavailableError extends Error {",' constructor(message = "platform runtime is not available in current location context") {'," super(message);",' this.name = "PlatformRuntimeUnavailableError";'," }","}","",'export function getPlatformCapabilityErrorMessage(error: unknown, fallback = "\u5E73\u53F0\u80FD\u529B\u6682\u4E0D\u53EF\u7528\u3002") {'," if (error instanceof PlatformRuntimeUnavailableError) {"," return error.message;"," }"," if (error instanceof Error && error.message.trim()) {"," return error.message;"," }"," return fallback;","}",""].join(`
2128
2127
  `)}function buildCapabilitySource(kind,prefix="src"){return kind==="auth"?[`import { createBrowserSessionStore } from "${buildVendorRuntimeImport2(prefix,"platform/capabilities","browser.js")}";`,'import { buildPlatformAbsoluteUrl, buildPlatformAuthPath, buildPlatformPath, getPlatformRuntimeApp, getPlatformRuntimeContext, hasPlatformRuntimeBinding } from "../client";',"","type AuthUiConfig = {"," auth_enabled: boolean;"," sign_in_methods: Array<{ method: string; label: string }>;"," default_method?: string;","};","","type StartEmailMagicLinkResult =",' | { next_action: "wait_for_verification"; masked_target: string; magic_link_url?: string }',' | { next_action: "registration_blocked"; message: string };',"","function buildSameOriginAuthEndpoint(path: string) {",' const normalizedPath = path.startsWith("/") ? path : `/${path}`;'," return buildPlatformAbsoluteUrl(`/api/auth${normalizedPath}`);","}","","async function requestPublicAuth<T>(path: string, init?: RequestInit): Promise<T> {"," const response = await fetch(buildSameOriginAuthEndpoint(path), {",' credentials: "include",'," ...init,"," headers: {",' "Content-Type": "application/json",'," ...(init?.headers ?? {}),"," },"," });"," if (!response.ok) {"," let message = `Request failed: ${response.status}`;"," try {"," const payload = (await response.json()) as { error?: { message?: string } };"," if (payload.error?.message) {"," message = payload.error.message;"," }"," } catch {}"," throw new Error(message);"," }"," return (await response.json()) as T;","}","","export async function getCurrentEndUser() {"," return getPlatformRuntimeApp().getCurrentEndUser();","}","","export async function getCurrentEndUserRoles() {"," return getPlatformRuntimeApp().getCurrentEndUserRoles();","}","","function getSessionStore() {"," return createBrowserSessionStore({ authPath: buildPlatformAuthPath() });","}","","export function saveEndUserSessionToken(token: string) {"," getSessionStore().writeToken(token);","}","","export function clearEndUserSessionToken() {"," getSessionStore().clearToken();","}","","export function hasEndUserSessionToken() {"," return Boolean(getSessionStore().readToken());","}","","export function readEndUserSessionToken() {"," return getSessionStore().readToken();","}","","export async function getEndUserSessionState() {"," try {"," const endUser = await getCurrentEndUser();"," const access = getPlatformRuntimeApp().resolveAccess(endUser);",' return { signedIn: access.kind === "ready", endUser, access };'," } catch {"," return { signedIn: false, endUser: null, access: null };"," }","}","","export async function getAuthUiConfig() {",' return requestPublicAuth<AuthUiConfig>("/ui-config", { method: "GET" });',"}","","export async function startEmailMagicLinkSignIn(args: { email: string; redirectUri?: string }) {",' return requestPublicAuth<StartEmailMagicLinkResult>("/sign-in/email_magic_link/start", {',' method: "POST",'," body: JSON.stringify({"," email: args.email,"," redirect_uri: args.redirectUri,"," }),"," });","}","","export async function signInWithPassword(args: { email: string; password: string }) {",' const result = await requestPublicAuth<{ session_token: string }>("/sign-in/admin_provisioned_password/start", {',' method: "POST",'," body: JSON.stringify(args),"," });"," if (result.session_token) {"," saveEndUserSessionToken(result.session_token);"," }"," return result;","}","","export async function completeEmailMagicLinkSignIn(token: string) {",' const url = new URL(buildSameOriginAuthEndpoint("/callback/email_magic_link"));',' url.searchParams.set("token", token);'," const response = await fetch(url.toString(), {",' method: "GET",',' credentials: "include",'," });"," if (!response.ok) {"," let message = `Request failed: ${response.status}`;"," try {"," const payload = (await response.json()) as { error?: { message?: string } };"," if (payload.error?.message) {"," message = payload.error.message;"," }"," } catch {}"," throw new Error(message);"," }"," const result = (await response.json()) as { session_token?: string };"," if (result.session_token) {"," saveEndUserSessionToken(result.session_token);"," }"," return result;","}","",'export function buildSignInHref(returnTo = "/app") {'," return getPlatformRuntimeApp().buildSignInUrl(returnTo);","}","","async function requestSameOriginSignOut(sessionToken: string) {",' const response = await fetch(buildSameOriginAuthEndpoint("/sign-out"), {',' method: "POST",',' credentials: "include",'," headers: {",' "Content-Type": "application/json",'," },"," body: JSON.stringify({ session_token: sessionToken })"," });"," if (response.ok) {"," return;"," }"," let message = `Request failed: ${response.status}`;"," try {"," const payload = (await response.json()) as { error?: { message?: string } };"," if (payload.error?.message) {"," message = payload.error.message;"," }"," } catch {}"," throw new Error(message);","}","","export async function signOutEndUser() {"," const sessionToken = readEndUserSessionToken();"," if (sessionToken) {"," try {"," await requestSameOriginSignOut(sessionToken);"," } finally {"," clearEndUserSessionToken();"," }"," return;"," }"," if (!hasPlatformRuntimeBinding()) {"," clearEndUserSessionToken();"," return;"," }"," await getPlatformRuntimeApp().signOut();","}","","export async function ensureEndUserAuthenticated(args: { returnTo?: string; redirectToSignIn?: boolean } = {}) {"," return getPlatformRuntimeApp().ensureAuthenticated(args);","}","","export function getAuthCapabilityState() {"," return {"," ready: hasPlatformRuntimeBinding(),"," mode: getPlatformRuntimeContext().mode,"," };","}",""].join(`
@@ -2140,7 +2139,7 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2140
2139
  `)}function buildProtectedPageSource(){return['import React from "react";','import { ensureEndUserAuthenticated, getAuthCapabilityState, getCurrentEndUserRoles, signOutEndUser } from "../platform/capabilities/auth";','import { buildPlatformPath } from "../platform/client";','import { getPlatformCapabilityErrorMessage } from "../platform/errors";',"",'type AuthState = "loading" | "ready" | "error";',"","export function ProtectedPage() {"," const authCapability = getAuthCapabilityState();",' const [authState, setAuthState] = React.useState<AuthState>("loading");'," const [authError, setAuthError] = React.useState<string | null>(null);"," const [currentEndUser, setCurrentEndUser] = React.useState<Awaited<ReturnType<typeof ensureEndUserAuthenticated>> | null>(null);"," const [currentRoles, setCurrentRoles] = React.useState<Awaited<ReturnType<typeof getCurrentEndUserRoles>>>([]);",""," React.useEffect(() => {"," let cancelled = false;"," async function loadProtectedState() {",' setAuthState("loading");'," setAuthError(null);"," try {",' const endUser = await ensureEndUserAuthenticated({ returnTo: "/protected", redirectToSignIn: true });'," if (!endUser || cancelled) {"," return;"," }"," const roles = await getCurrentEndUserRoles();"," if (cancelled) {"," return;"," }"," setCurrentEndUser(endUser);"," setCurrentRoles(roles);",' setAuthState("ready");'," } catch (error) {"," if (cancelled) {"," return;"," }",' setAuthState("error");',' setAuthError(getPlatformCapabilityErrorMessage(error, "\u4FDD\u62A4\u9875\u767B\u5F55\u6001\u8BFB\u53D6\u5931\u8D25\u3002"));'," }"," }"," void loadProtectedState();"," return () => {"," cancelled = true;"," };"," }, []);",""," const handleSignOut = React.useCallback(async () => {"," try {"," await signOutEndUser();"," } finally {",' window.location.assign(buildPlatformPath("/app"));'," }"," }, []);",""," return (",' <main className="min-h-screen bg-slate-950 text-slate-50">',' <section className="mx-auto flex min-h-screen max-w-4xl flex-col justify-center gap-8 px-6 py-16">',' <a href={buildPlatformPath("/app")} className="text-sm text-slate-400 underline-offset-4 hover:text-slate-200 hover:underline">\u8FD4\u56DE\u9996\u9875</a>',' <div className="space-y-4">',' <div className="inline-flex w-fit rounded-full border border-sky-400/30 bg-sky-400/10 px-3 py-1 text-xs font-medium tracking-wide text-sky-200">\u4FDD\u62A4\u9875</div>',' <h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">\u9700\u767B\u5F55\u9875\u9762\u9AA8\u67B6</h1>',' <p className="max-w-2xl text-sm leading-7 text-slate-300 sm:text-base">'," \u8FD9\u662F\u4E00\u4E2A\u767B\u5F55\u540E\u624D\u80FD\u8BBF\u95EE\u7684\u9875\u9762\u793A\u4F8B\u3002\u5F53\u524D\u4F1A\u81EA\u52A8\u663E\u793A\u5F53\u524D\u7528\u6237\u548C\u89D2\u8272\uFF0C\u540E\u7EED\u53EF\u4EE5\u76F4\u63A5\u66FF\u6362\u6210\u4F60\u7684\u6B63\u5F0F\u4E1A\u52A1\u9875\u9762\u3002"," </p>"," </div>",' <div className="rounded-3xl border border-white/10 bg-slate-900/70 p-6">',' <div className="flex flex-wrap items-center gap-3">',' <button type="button" className="rounded-full bg-white px-4 py-2 text-sm font-medium text-slate-950 transition hover:bg-slate-200 disabled:cursor-not-allowed disabled:bg-slate-700 disabled:text-slate-300" disabled={authState === "loading"} onClick={() => void handleSignOut()}>\u9000\u51FA\u767B\u5F55</button>',' <span className={`rounded-full border px-2.5 py-1 text-[11px] font-medium ${authCapability.ready ? "border-emerald-400/30 bg-emerald-400/10 text-emerald-200" : "border-amber-400/30 bg-amber-400/10 text-amber-100"}`}>{authCapability.ready ? "\u5E73\u53F0\u4E0A\u4E0B\u6587\u53EF\u7528" : "\u5F53\u524D\u4E3A standalone / \u672A\u7ED1\u5B9A"}</span>'," </div>",' <div className="mt-5 rounded-2xl border border-white/10 bg-black/20 p-4">',' {authError ? <p className="text-sm text-rose-300">{authError}</p> : null}',' {!authError && authState === "loading" ? <p className="text-sm text-slate-400">\u6B63\u5728\u6821\u9A8C\u767B\u5F55\u6001\u5E76\u52A0\u8F7D\u5F53\u524D\u7528\u6237\u4FE1\u606F...</p> : null}',' {!authError && authState === "ready" ? (',' <div className="space-y-3 text-sm text-slate-200">',' <div><div className="text-xs text-slate-500">\u7528\u6237 ID</div><div className="mt-1 break-all font-mono text-[13px]">{currentEndUser?.app_user?.app_user_id || currentEndUser?.identity?.identity_id || "\u672A\u767B\u5F55 / \u672A\u8FD4\u56DE"}</div></div>',' <div><div className="text-xs text-slate-500">\u663E\u793A\u540D\u79F0</div><div className="mt-1">{currentEndUser?.app_user?.display_name || currentEndUser?.identity?.email || currentEndUser?.identity?.phone || "\u672A\u767B\u5F55 / \u672A\u8FD4\u56DE"}</div></div>',' <div><div className="text-xs text-slate-500">\u89D2\u8272\u5217\u8868</div><div className="mt-2 flex flex-wrap gap-2">{currentRoles.length > 0 ? currentRoles.map((role: Awaited<ReturnType<typeof getCurrentEndUserRoles>>[number]) => <span key={role.role_key} className="rounded-full border border-sky-400/30 bg-sky-400/10 px-2.5 py-1 text-xs text-sky-100">{role.display_name || role.role_key}</span>) : <span className="text-sm text-slate-400">\u6682\u65E0\u89D2\u8272\u6216\u5F53\u524D\u672A\u767B\u5F55\u3002</span>}</div></div>'," </div>"," ) : null}"," </div>"," </div>"," </section>"," </main>"," );","}",""].join(`
2141
2140
  `)}function buildCmsPageSource(){return['import React from "react";','import { getCmsCapabilityState, getCurrentAppCmsCollectionMeta, listCurrentAppCmsCollections, listCurrentAppCmsItems, resolveCmsItemCategoryName, resolveCmsItemTagLabels, resolveCurrentAppCmsTenantId } from "../platform/capabilities/cms";','import { buildPlatformPath, getPlatformConfig, getPlatformRuntimeApp } from "../platform/client";','import { getPlatformCapabilityErrorMessage } from "../platform/errors";',"",'type CmsState = "idle" | "loading" | "ready" | "error";','type CmsCollection = Awaited<ReturnType<typeof listCurrentAppCmsCollections>>["items"][number];',"type CmsCollectionMeta = Awaited<ReturnType<typeof getCurrentAppCmsCollectionMeta>>;",'type CmsItem = Awaited<ReturnType<typeof listCurrentAppCmsItems>>["items"][number];',"","function pickCmsTitle(item: CmsItem): string {",' if (typeof item.presentation?.title === "string" && item.presentation.title.trim()) {'," return item.presentation.title.trim();"," }"," const contentTitle = item.content?.title;",' if (typeof contentTitle === "string" && contentTitle.trim()) {'," return contentTitle.trim();"," }",' return item.system.slug || item.system.id || "\u672A\u547D\u540D\u5185\u5BB9";',"}","","function pickCmsSummary(item: CmsItem): string | null {",' if (typeof item.presentation?.summary === "string" && item.presentation.summary.trim()) {'," return item.presentation.summary.trim();"," }"," return null;","}","","function pickCmsCoverImageUrl(item: CmsItem): string | null {"," return getPlatformRuntimeApp().resolveCmsCoverImageUrl(item);","}","","function isSampleMode(cmsCapabilityReady: boolean, cmsTenantId: string, cmsCollections: CmsCollection[]): boolean {"," return !cmsCapabilityReady || !cmsTenantId.trim() || cmsCollections.length === 0;","}","","export function CmsPage() {"," const config = getPlatformConfig();"," const cmsCapability = getCmsCapabilityState();",' const [cmsState, setCmsState] = React.useState<CmsState>("idle");'," const [cmsError, setCmsError] = React.useState<string | null>(null);",' const [cmsTenantId, setCmsTenantId] = React.useState(config.tenantId || "");'," const [cmsCollections, setCmsCollections] = React.useState<CmsCollection[]>([]);"," const [cmsItems, setCmsItems] = React.useState<CmsItem[]>([]);"," const [cmsPrimaryCollection, setCmsPrimaryCollection] = React.useState<string | null>(null);"," const [cmsCollectionMeta, setCmsCollectionMeta] = React.useState<CmsCollectionMeta | null>(null);"," const [selectedItemId, setSelectedItemId] = React.useState<string | null>(null);",""," const loadCmsExample = React.useCallback(async () => {",' const tenantId = ((cmsTenantId || "").trim() || (await resolveCurrentAppCmsTenantId()).trim());'," if (!tenantId) {",' setCmsTenantId("");',' setCmsState("error");',' setCmsError("\u5F53\u524D\u672A\u62FF\u5230\u53EF\u7528 tenantId\uFF0C\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D CMS \u793A\u4F8B\u3002");'," return;"," }"," setCmsTenantId(tenantId);",' setCmsState("loading");'," setCmsError(null);"," try {"," const collectionsResult = await listCurrentAppCmsCollections();"," const collections = collectionsResult.items;"," setCmsCollections(collections);"," const firstCollection = collections[0]?.collection ?? null;"," setCmsPrimaryCollection(firstCollection);"," if (!firstCollection) {"," setCmsItems([]);"," setSelectedItemId(null);",' setCmsState("ready");'," return;"," }"," const [metaResult, itemsResult] = await Promise.all(["," getCurrentAppCmsCollectionMeta({ collection: firstCollection }),"," listCurrentAppCmsItems({ collection: firstCollection, page: 1, pageSize: 20 })"," ]);"," setCmsCollectionMeta(metaResult);"," setCmsItems(itemsResult.items);"," setSelectedItemId(itemsResult.items[0]?.system.id || itemsResult.items[0]?.system.slug || null);",' setCmsState("ready");'," } catch (error) {",' setCmsError(getPlatformCapabilityErrorMessage(error, "CMS \u793A\u4F8B\u8BF7\u6C42\u5931\u8D25\u3002"));',' setCmsState("error");'," }"," }, [cmsTenantId]);",""," React.useEffect(() => {"," if (!cmsCapability.ready) {"," return;"," }"," void loadCmsExample();"," }, [cmsCapability.ready, loadCmsExample]);",""," const selectedCollectionMeta = React.useMemo(() => cmsCollectionMeta, [cmsCollectionMeta]);"," const selectedItem = React.useMemo(() => cmsItems.find((item) => (item.system.id || item.system.slug) === selectedItemId) ?? cmsItems[0] ?? null, [cmsItems, selectedItemId]);"," const sampleMode = isSampleMode(cmsCapability.ready, cmsTenantId, cmsCollections);",""," const handleCollectionChange = React.useCallback(async (collectionName: string) => {",' const tenantId = ((cmsTenantId || "").trim() || (await resolveCurrentAppCmsTenantId()).trim());'," if (!tenantId) {",' setCmsTenantId("");',' setCmsError("\u5F53\u524D\u672A\u62FF\u5230\u53EF\u7528 tenantId\uFF0C\u6682\u65F6\u65E0\u6CD5\u52A0\u8F7D CMS \u793A\u4F8B\u3002");',' setCmsState("error");'," return;"," }"," setCmsTenantId(tenantId);",' setCmsState("loading");'," setCmsError(null);"," setCmsPrimaryCollection(collectionName);"," try {"," const [metaResult, itemsResult] = await Promise.all(["," getCurrentAppCmsCollectionMeta({ collection: collectionName }),"," listCurrentAppCmsItems({ collection: collectionName, page: 1, pageSize: 20 })"," ]);"," setCmsCollectionMeta(metaResult);"," setCmsItems(itemsResult.items);"," setSelectedItemId(itemsResult.items[0]?.system.id || itemsResult.items[0]?.system.slug || null);",' setCmsState("ready");'," } catch (error) {",' setCmsError(getPlatformCapabilityErrorMessage(error, "CMS \u5185\u5BB9\u52A0\u8F7D\u5931\u8D25\u3002"));',' setCmsState("error");'," }"," }, [cmsTenantId]);",""," return (",' <main className="min-h-screen bg-slate-950 text-slate-50">',' <section className="mx-auto flex min-h-screen max-w-6xl flex-col justify-center gap-8 px-6 py-16">',' <a href={buildPlatformPath("/app")} className="text-sm text-slate-400 underline-offset-4 hover:text-slate-200 hover:underline">\u8FD4\u56DE\u9996\u9875</a>',' <div className="space-y-4">',' <div className="flex flex-wrap items-center gap-3"><div className="inline-flex w-fit rounded-full border border-emerald-400/30 bg-emerald-400/10 px-3 py-1 text-xs font-medium tracking-wide text-emerald-200">CMS \u9875</div><span className={`rounded-full border px-3 py-1 text-xs font-medium ${sampleMode ? "border-amber-400/20 bg-amber-400/10 text-amber-100" : "border-emerald-400/20 bg-emerald-400/10 text-emerald-100"}`}>{sampleMode ? "\u5F53\u524D\u4E3A\u793A\u4F8B\u6A21\u5F0F" : "\u5F53\u524D\u4E3A\u771F\u5B9E\u8D44\u6E90\u6A21\u5F0F"}</span></div>',' <h1 className="text-4xl font-semibold tracking-tight sm:text-5xl">\u5185\u5BB9\u4E2D\u5FC3\u793A\u4F8B</h1>',' <p className="max-w-3xl text-sm leading-7 text-slate-300 sm:text-base">\u8FD9\u4E2A\u9875\u9762\u5C55\u793A\u5F53\u524D\u5E94\u7528\u53EF\u8BBF\u95EE\u7684\u5185\u5BB9\u5217\u8868\u4E0E\u8BE6\u60C5\u3002\u4F60\u53EF\u4EE5\u5728\u6B64\u57FA\u7840\u4E0A\u7EE7\u7EED\u505A\u5185\u5BB9\u5B98\u7F51\u3001\u5E2E\u52A9\u4E2D\u5FC3\u3001\u6D3B\u52A8\u9875\u6216\u8D44\u8BAF\u9875\u3002</p>'," </div>",' {sampleMode ? <div className="rounded-3xl border border-amber-400/20 bg-amber-400/10 p-5 text-sm leading-7 text-amber-50"><div className="font-medium">\u5F53\u524D\u5148\u5C55\u793A CMS \u9875\u9762\u9AA8\u67B6</div><div className="mt-2 text-amber-100/90">\u5982\u679C\u5F53\u524D app \u5C1A\u672A\u7ED1\u5B9A\u5185\u5BB9\u670D\u52A1\u3001\u672A\u6CE8\u5165 tenantId\uFF0C\u6216\u5F53\u524D\u79DF\u6237\u4E0B\u8FD8\u6CA1\u6709\u5185\u5BB9\u96C6\u5408\uFF0C\u8FD9\u4E00\u9875\u4F1A\u5148\u4FDD\u7559\u793A\u4F8B\u5E03\u5C40\uFF0C\u65B9\u4FBF\u5148\u8C03\u6574\u5BFC\u822A\u3001\u5361\u7247\u3001\u8BE6\u60C5\u533A\u548C\u6837\u5F0F\u3002\u63A5\u901A\u771F\u5B9E\u5185\u5BB9\u540E\uFF0C\u65E0\u9700\u91CD\u5199\u9875\u9762\u7ED3\u6784\u3002</div></div> : <div className="rounded-3xl border border-emerald-400/20 bg-emerald-400/10 p-5 text-sm leading-7 text-emerald-50"><div className="font-medium">\u5F53\u524D\u5DF2\u63A5\u5165\u771F\u5B9E CMS \u5185\u5BB9</div><div className="mt-2 text-emerald-100/90">\u9875\u9762\u6B63\u5728\u8BFB\u53D6\u5F53\u524D\u5E94\u7528\u7ED1\u5B9A\u7684\u5185\u5BB9\u96C6\u5408\u3001\u5217\u8868\u548C\u8BE6\u60C5\uFF0C\u53EF\u76F4\u63A5\u7EE7\u7EED\u6309\u771F\u5B9E\u6570\u636E\u7ED3\u6784\u6269\u5C55\u5C55\u793A\u3002</div></div>}',' <div className="rounded-3xl border border-white/10 bg-slate-900/70 p-6">',' <div className="flex items-start justify-between gap-4">',' <div className="space-y-1"><div className="text-sm font-semibold text-white">\u5F53\u524D\u5185\u5BB9\u6E90</div><p className="text-sm leading-6 text-slate-400">\u9875\u9762\u4F1A\u81EA\u52A8\u8BFB\u53D6\u5F53\u524D\u5E94\u7528\u7ED1\u5B9A\u7684\u5185\u5BB9\uFF0C\u4E0D\u518D\u63D0\u4F9B\u624B\u5DE5\u5207\u6362\u79DF\u6237\u5165\u53E3\uFF0C\u907F\u514D\u8BEF\u8BFB\u5230\u5176\u4ED6\u5185\u5BB9\u8303\u56F4\u3002</p></div>',' <span className={`rounded-full border px-2.5 py-1 text-[11px] font-medium ${cmsCapability.ready ? "border-emerald-400/30 bg-emerald-400/10 text-emerald-200" : "border-amber-400/30 bg-amber-400/10 text-amber-100"}`}>{cmsCapability.ready ? "\u5185\u5BB9\u670D\u52A1\u53EF\u7528" : "\u5F53\u524D\u672A\u8FDE\u63A5\u5185\u5BB9\u670D\u52A1"}</span>'," </div>",' <div className="mt-5 flex flex-col gap-3 sm:flex-row">',' <div className="min-w-0 flex-1 rounded-2xl border border-white/10 bg-black/20 px-4 py-2.5 text-sm text-slate-200">{cmsTenantId || "\u5F53\u524D\u5E94\u7528\u6682\u672A\u6CE8\u5165\u5185\u5BB9\u79DF\u6237"}</div>',' <div className="rounded-full border border-white/10 px-4 py-2 text-sm text-slate-300">{cmsState === "loading" ? "\u5185\u5BB9\u52A0\u8F7D\u4E2D..." : "\u5DF2\u81EA\u52A8\u52A0\u8F7D"}</div>'," </div>",' {cmsError ? <p className="mt-4 text-sm text-rose-300">{cmsError}</p> : null}',' <div className="mt-5 flex flex-wrap gap-2">{cmsCollections.length > 0 ? cmsCollections.map((collection) => <button key={collection.collection} type="button" onClick={() => void handleCollectionChange(collection.collection)} className={`rounded-full border px-3 py-1.5 text-xs font-medium transition ${cmsPrimaryCollection === collection.collection ? "border-emerald-400/30 bg-emerald-400/10 text-emerald-100" : "border-white/10 bg-white/5 text-slate-300 hover:border-white/20 hover:text-white"}`}>{collection.label}<span className="ml-2 text-[11px] text-slate-400">{collection.published_item_count}</span></button>) : sampleMode ? <span className="rounded-full border border-dashed border-white/10 px-3 py-1.5 text-xs text-slate-400">\u5F85\u63A5\u5165\u771F\u5B9E\u5185\u5BB9\u96C6\u5408\u540E\u663E\u793A</span> : null}</div>',' <div className="mt-5 grid gap-4 xl:grid-cols-[320px_minmax(0,1fr)]">',' <div className="rounded-2xl border border-white/10 bg-black/20 p-4"><div className="flex items-center justify-between gap-3"><div className="text-xs uppercase tracking-[0.2em] text-slate-500">\u5185\u5BB9\u5217\u8868</div>{selectedCollectionMeta ? <div className="text-xs text-slate-400">{selectedCollectionMeta.collection}</div> : null}</div><div className="mt-3 space-y-2">{cmsItems.length > 0 ? cmsItems.map((item) => { const itemKey = item.system.id || item.system.slug || pickCmsTitle(item); const categoryName = resolveCmsItemCategoryName(item, selectedCollectionMeta ?? undefined); const tagLabels = resolveCmsItemTagLabels(item); const coverImageUrl = pickCmsCoverImageUrl(item); return <button key={itemKey} type="button" onClick={() => setSelectedItemId(itemKey)} className={`block w-full rounded-2xl border px-3 py-3 text-left text-sm transition ${selectedItemId === itemKey || (!selectedItemId && selectedItem === item) ? "border-emerald-400/30 bg-emerald-400/10 text-emerald-100" : "border-white/10 bg-white/5 text-slate-200 hover:border-white/20"}`}>{coverImageUrl ? <img src={coverImageUrl} alt={pickCmsTitle(item)} className="mb-3 h-32 w-full rounded-xl object-cover" loading="lazy" /> : null}<div className="font-medium text-white">{pickCmsTitle(item)}</div>{pickCmsSummary(item) ? <div className="mt-1 line-clamp-2 text-xs leading-5 text-slate-400">{pickCmsSummary(item)}</div> : null}<div className="mt-2 flex flex-wrap gap-2 text-[11px] text-slate-400"><span>\u5206\u7C7B\uFF1A{categoryName}</span>{tagLabels.slice(0, 3).map((tag: string) => <span key={tag}>#{tag}</span>)}</div></button>; }) : sampleMode ? <div className="space-y-2"><div className="rounded-2xl border border-dashed border-white/10 px-3 py-4 text-sm text-slate-400">\u5F53\u524D\u5148\u5C55\u793A\u5217\u8868\u9AA8\u67B6\u3002\u63A5\u5165\u771F\u5B9E CMS \u540E\uFF0C\u8FD9\u91CC\u4F1A\u81EA\u52A8\u5207\u6362\u4E3A\u5185\u5BB9\u6761\u76EE\u3002</div><div className="rounded-2xl border border-white/10 bg-white/5 px-3 py-3 text-sm text-slate-300"><div className="font-medium text-white">\u793A\u4F8B\u5361\u7247\u7ED3\u6784</div><div className="mt-1 text-xs leading-5 text-slate-400">\u6807\u9898\u3001\u6458\u8981\u3001\u5206\u7C7B\u3001\u5C01\u9762\u56FE\u548C\u6807\u7B7E\u5EFA\u8BAE\u4FDD\u7559\u4E3A\u5361\u7247\u7684\u9ED8\u8BA4\u4FE1\u606F\u5C42\u7EA7\u3002</div></div></div> : <div className="rounded-2xl border border-dashed border-white/10 px-3 py-4 text-sm text-slate-400">\u5F53\u524D\u79DF\u6237\u4E0B\u6682\u65E0\u53EF\u5C55\u793A\u5185\u5BB9\u3002</div>}</div></div>',' <div className="rounded-2xl border border-white/10 bg-black/20 p-4"><div className="flex items-center justify-between gap-3"><div className="text-xs uppercase tracking-[0.2em] text-slate-500">\u5185\u5BB9\u8BE6\u60C5</div>{selectedItem?.system.slug ? <div className="text-xs text-slate-400">slug: {selectedItem?.system.slug}</div> : null}</div>{selectedItem ? <article className="mt-4 space-y-4"><div>{pickCmsCoverImageUrl(selectedItem) ? <img src={pickCmsCoverImageUrl(selectedItem) || undefined} alt={pickCmsTitle(selectedItem)} className="mb-4 h-64 w-full rounded-2xl object-cover" /> : null}<h2 className="text-2xl font-semibold text-white">{pickCmsTitle(selectedItem)}</h2>{pickCmsSummary(selectedItem) ? <p className="mt-2 text-sm leading-6 text-slate-300">{pickCmsSummary(selectedItem)}</p> : null}</div><div className="flex flex-wrap gap-2 text-xs text-slate-300"><span className="rounded-full border border-white/10 bg-white/5 px-2.5 py-1">\u5206\u7C7B\uFF1A{resolveCmsItemCategoryName(selectedItem, selectedCollectionMeta ?? undefined)}</span>{resolveCmsItemTagLabels(selectedItem).length > 0 ? resolveCmsItemTagLabels(selectedItem).map((tag: string) => <span key={tag} className="rounded-full border border-sky-400/20 bg-sky-400/10 px-2.5 py-1 text-sky-100">#{tag}</span>) : <span className="rounded-full border border-white/10 bg-white/5 px-2.5 py-1 text-slate-400">\u65E0\u6807\u7B7E</span>}</div>{selectedItem.system.rendered_html ? <div className="cms-content rounded-2xl bg-white px-4 py-4 text-sm" dangerouslySetInnerHTML={{ __html: selectedItem.system.rendered_html }} /> : <div className="rounded-2xl border border-dashed border-white/10 px-4 py-5 text-sm text-slate-400">\u5F53\u524D\u5185\u5BB9\u6CA1\u6709 `rendered_html`\uFF0C\u53EF\u4EE5\u7EE7\u7EED\u5C55\u793A\u7ED3\u6784\u5316\u5B57\u6BB5\u3002</div>}<div className="grid gap-3 md:grid-cols-2"><div className="rounded-2xl border border-white/10 bg-white/5 p-4 text-sm text-slate-300"><div className="text-xs uppercase tracking-[0.2em] text-slate-500">\u53D1\u5E03\u72B6\u6001</div><div className="mt-2">{selectedItem.system.publish_status || "-"}</div></div><div className="rounded-2xl border border-white/10 bg-white/5 p-4 text-sm text-slate-300"><div className="text-xs uppercase tracking-[0.2em] text-slate-500">\u5185\u5BB9 ID</div><div className="mt-2 break-all font-mono text-[13px]">{selectedItem.system.id || "-"}</div></div></div></article> : sampleMode ? <div className="mt-4 rounded-2xl border border-dashed border-white/10 px-4 py-6 text-sm text-slate-400">\u5F53\u524D\u5148\u5C55\u793A\u8BE6\u60C5\u9AA8\u67B6\u3002\u63A5\u5165\u771F\u5B9E\u5185\u5BB9\u540E\uFF0C\u8FD9\u91CC\u4F1A\u81EA\u52A8\u6E32\u67D3\u6B63\u6587\u3001\u5C01\u9762\u56FE\u3001\u6807\u7B7E\u548C\u53D1\u5E03\u4FE1\u606F\u3002</div> : <div className="mt-4 rounded-2xl border border-dashed border-white/10 px-3 py-6 text-sm text-slate-400">\u5F53\u524D\u6CA1\u6709\u9009\u4E2D\u7684\u5185\u5BB9\u6761\u76EE\u3002</div>}</div>'," </div>"," </div>"," </section>"," </main>"," );","}",""].join(`
2142
2141
  `)}function buildStylesSource(){return['@import "tailwindcss";','@source "../../public/**/*.html";',"","@theme inline {"," --color-background: var(--background);"," --color-foreground: var(--foreground);"," --color-border: var(--border);"," --color-input: var(--input);"," --color-ring: var(--ring);"," --color-muted: var(--muted);"," --color-muted-foreground: var(--muted-foreground);"," --color-accent: var(--accent);"," --color-accent-foreground: var(--accent-foreground);"," --color-primary: var(--primary);"," --color-primary-foreground: var(--primary-foreground);"," --color-popover: var(--popover);"," --color-popover-foreground: var(--popover-foreground);","}","",":root {",' font-family: Inter, "PingFang SC", "Hiragino Sans GB", sans-serif;'," color-scheme: dark;"," --background: #0f172a;"," --foreground: #e5eefb;"," --border: #334155;"," --input: #475569;"," --ring: #38bdf8;"," --muted: #162033;"," --muted-foreground: #94a3b8;"," --accent: #1e293b;"," --accent-foreground: #f8fafc;"," --primary: #f8fafc;"," --primary-foreground: #0f172a;"," --popover: rgba(15, 23, 42, 0.98);"," --popover-foreground: #e5eefb;","}","","html {"," background: var(--background);"," color: var(--foreground);","}","","body {"," margin: 0;"," background: var(--background);"," color: var(--foreground);","}","","code {",' font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", monospace;',"}",""].join(`
2143
- `)}function buildCmsContentStylesSource(){return buildWebBackendLiteCmsContentPresetCssSource()}import{createHash as createHash2}from"node:crypto";var BACKEND_PLATFORM_OWNED_FILES=new Set(["src/server/app.ts","src/server/routes/seo-pages.ts"]),PLATFORM_BLOCKS_RELEASES={"frontend-app-vite":"2026.06.30.1","backend-app-node":"2026.06.30.1"};function isManagedPlatformFilePath(templateKey,filePath){return templateKey==="frontend-app-vite"?filePath.startsWith("src/platform/"):filePath.startsWith("src/web/platform/")||filePath.startsWith("src/server/platform/")||BACKEND_PLATFORM_OWNED_FILES.has(filePath)}function getPlatformBlocksRelease(templateKey){return PLATFORM_BLOCKS_RELEASES[templateKey]}function buildPlatformBlocksManifestFromTemplateFiles(templateKey,files){let managedFiles=files.filter(file=>isManagedPlatformFilePath(templateKey,file.path)).map(file=>({path:file.path,block_id:buildManagedPlatformBlockId(file.path),policy:"replace",content_sha256:checksum(file.content)})).sort((left,right)=>left.path.localeCompare(right.path));return{schema_version:1,template_key:templateKey,platform_blocks_release:getPlatformBlocksRelease(templateKey),platform_blocks_revision:buildPlatformBlocksRevision(managedFiles),managed_files:managedFiles}}function buildManagedPlatformBlockId(path){return path.replace(/\.[^/.]+$/u,"").replace(/[^a-zA-Z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").toLowerCase()}function buildPlatformBlocksRevision(files){return`platform-blocks@${createHash2("sha256").update(JSON.stringify(files)).digest("hex").slice(0,16)}`}function checksum(content){return`sha256-${createHash2("sha256").update(content).digest("hex")}`}function readTemplateBlockSource2(relativePath){let fileUrl=[new URL(`../template-blocks/${relativePath}`,import.meta.url),new URL(`../../src/template-blocks/${relativePath}`,import.meta.url)].find(candidate=>existsSync3(candidate));if(!fileUrl)throw new Error(`Missing template block source for ${relativePath}`);return readFileSync3(fileUrl,"utf8")}function scaffoldTemplateBlock2(relativePath,outputPath){return{path:outputPath,content:readTemplateBlockSource2(relativePath)}}function buildAppYamlSource(templatePackageName){return[`name: ${templatePackageName}`,"version: 0.1.0","entry:"," command: npm run dev"," port: 3000"," health_check: /healthz",""].join(`
2142
+ `)}function buildCmsContentStylesSource(){return buildWebBackendLiteCmsContentPresetCssSource()}import{createHash as createHash2}from"node:crypto";var BACKEND_PLATFORM_OWNED_FILES=new Set(["src/server/app.ts","src/server/routes/seo-pages.ts"]),PLATFORM_BLOCKS_RELEASES={"frontend-app-vite":"2026.07.19.1","backend-app-node":"2026.07.19.1"};function isManagedPlatformFilePath(templateKey,filePath){return templateKey==="frontend-app-vite"?filePath.startsWith("src/platform/"):filePath.startsWith("src/web/platform/")||filePath.startsWith("src/server/platform/")||BACKEND_PLATFORM_OWNED_FILES.has(filePath)}function getPlatformBlocksRelease(templateKey){return PLATFORM_BLOCKS_RELEASES[templateKey]}function buildPlatformBlocksManifestFromTemplateFiles(templateKey,files){let managedFiles=files.filter(file=>isManagedPlatformFilePath(templateKey,file.path)).map(file=>({path:file.path,block_id:buildManagedPlatformBlockId(file.path),policy:"replace",content_sha256:checksum(file.content)})).sort((left,right)=>left.path.localeCompare(right.path));return{schema_version:1,template_key:templateKey,platform_blocks_release:getPlatformBlocksRelease(templateKey),platform_blocks_revision:buildPlatformBlocksRevision(managedFiles),managed_files:managedFiles}}function buildManagedPlatformBlockId(path2){return path2.replace(/\.[^/.]+$/u,"").replace(/[^a-zA-Z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").toLowerCase()}function buildPlatformBlocksRevision(files){return`platform-blocks@${createHash2("sha256").update(JSON.stringify(files)).digest("hex").slice(0,16)}`}function checksum(content){return`sha256-${createHash2("sha256").update(content).digest("hex")}`}function readTemplateBlockSource2(relativePath){let fileUrl=[new URL(`../template-blocks/${relativePath}`,import.meta.url),new URL(`../../src/template-blocks/${relativePath}`,import.meta.url)].find(candidate=>existsSync3(candidate));if(!fileUrl)throw new Error(`Missing template block source for ${relativePath}`);return readFileSync3(fileUrl,"utf8")}function scaffoldTemplateBlock2(relativePath,outputPath){return{path:outputPath,content:readTemplateBlockSource2(relativePath)}}function buildAppYamlSource(templatePackageName){return[`name: ${templatePackageName}`,"version: 0.1.0","entry:"," command: npm run dev"," port: 3000"," health_check: /healthz",""].join(`
2144
2143
  `)}function buildPackageJsonManifest(templatePackageName){return{name:templatePackageName,version:"0.1.0",private:!0,type:"module",scripts:{dev:"node ./scripts/dev.mjs","dev:web":"vite --config vite.config.ts","dev:server":"tsx watch src/server/entry.ts",build:"npm run build:web && npm run build:server","build:web":"vite build","build:server":"tsc -p tsconfig.server.json",preview:"vite preview",start:"node dist/server/entry.js"},dependencies:{"@radix-ui/react-checkbox":"^1.3.3","@radix-ui/react-popover":"^1.1.15","@radix-ui/react-select":"^2.2.6","lucide-react":"^0.577.0",react:"18.3.1","react-day-picker":"^9.11.1","react-dom":"18.3.1"},devDependencies:{"@tailwindcss/vite":"4.2.2","@types/node":"22.15.17","@types/react":"19.2.2","@types/react-dom":"19.2.2","@vitejs/plugin-react":"4.3.4",tailwindcss:"4.2.2",tsx:"4.19.4",typescript:"5.8.2",vite:"6.3.5"}}}function buildPackageJsonSource(templatePackageName){return JSON.stringify(buildPackageJsonManifest(templatePackageName),null,2)+`
2145
2144
  `}function buildPackageLockSource(templatePackageName){let manifest=buildPackageJsonManifest(templatePackageName);return JSON.stringify({name:manifest.name,version:manifest.version,lockfileVersion:3,requires:!0,packages:{"":{name:manifest.name,version:manifest.version,dependencies:manifest.dependencies,devDependencies:manifest.devDependencies}}},null,2)+`
2146
2145
  `}function buildReadmeSource(){return["# Backend App \u4F7F\u7528\u8BF4\u660E","","\u8FD9\u4E2A\u6A21\u677F\u9002\u5408\u9700\u8981\u79C1\u6709 API\u3001\u6570\u636E\u5E93\u3001Webhook\u3001\u4EFB\u52A1\u5904\u7406\uFF0C\u6216\u9700\u8981\u670D\u52A1\u7AEF\u76F4\u51FA HTML \u7684 SEO \u53CB\u597D\u9875\u9762\u578B\u8F7B\u5E94\u7528\u3002","\u5B83\u7684\u524D\u7AEF\u9875\u9762\u5C42\u548C\u524D\u7AEF\u6A21\u677F\u4FDD\u6301\u540C\u4E00\u5957\u4F7F\u7528\u65B9\u5F0F\uFF0C\u4F46\u9ED8\u8BA4\u4F1A\u4F18\u5148\u751F\u6210\u4E00\u6761\u670D\u52A1\u7AEF SEO \u9875\u9762\u4E3B\u94FE\u3002","","## \u5148\u770B\u8FD9\u51E0\u4E2A\u76EE\u5F55","","- `src/web/*`\uFF1A\u524D\u7AEF\u9875\u9762\u3001\u7EC4\u4EF6\u548C\u5E73\u53F0\u63A5\u5165","- `src/server/entry.ts`\uFF1A\u670D\u52A1\u5165\u53E3","- `src/server/app.ts`\uFF1AHTTP \u8DEF\u7531\u88C5\u914D\uFF0C\u4E5F\u662F platform-managed \u8584\u58F3\u5165\u53E3","- `src/server/routes/api.ts`\uFF1A\u4E1A\u52A1 API","- `src/server/routes/seo-pages.ts`\uFF1ASEO \u9875\u9762\u4E3B\u94FE\u8DEF\u7531\uFF0C\u4E5F\u662F platform-managed \u8584\u58F3\u5165\u53E3","- `src/server/lib/seo-html.ts`\uFF1A\u9875\u9762 HTML \u7EC4\u88C5\u5668","- `src/server/lib/cms-seo.ts`\uFF1ACMS SEO \u6570\u636E\u67E5\u8BE2\u4E0E\u6620\u5C04","- `src/server/platform/cms.ts`\uFF1A\u670D\u52A1\u7AEF CMS helper","- `src/server/content/site-config.ts`\uFF1A\u7AD9\u70B9\u7EA7 SEO \u914D\u7F6E","- `src/server/content/static-pages.ts`\uFF1A\u9759\u6001\u9875\u5185\u5BB9","- `src/server/platform/data-form.ts`\uFF1A\u670D\u52A1\u7AEF Data Form helper","- `src/server/platform/runtime.ts`\uFF1A\u670D\u52A1\u7AEF\u5E73\u53F0\u63A5\u5165","- `resources/db/migrations/*.sql`\uFF1A\u6570\u636E\u5E93\u8FC1\u79FB","- `index.html`\uFF1A\u524D\u7AEF app shell \u6A21\u677F\uFF0Cserver \u4F1A\u5728\u8FD4\u56DE\u524D\u6CE8\u5165\u8FD0\u884C\u65F6\u914D\u7F6E\u548C `<base href>`","- `public/auth` \u4E0E `public/__app`\uFF1A\u767B\u5F55\u9875\u9759\u6001\u5165\u53E3\u3001\u767B\u5F55\u9875\u6587\u6848\u548C\u5C40\u90E8\u6837\u5F0F\u8986\u76D6","","## \u9ED8\u8BA4\u9875\u9762\u4E3B\u94FE","","- `/`\uFF1A\u670D\u52A1\u7AEF\u9996\u9875\uFF0C\u9996\u5C4F HTML \u53EF\u76F4\u63A5\u6293\u53D6","- `/about`\uFF1A\u670D\u52A1\u7AEF\u9759\u6001\u9875\u793A\u4F8B","- `/contact`\uFF1A\u670D\u52A1\u7AEF\u8054\u7CFB\u9875\u793A\u4F8B","- `/articles`\uFF1A\u670D\u52A1\u7AEF CMS \u5217\u8868\u9875","- `/articles/:slug`\uFF1A\u670D\u52A1\u7AEF CMS \u8BE6\u60C5\u9875","- `/app`\uFF1A\u524D\u7AEF SPA \u5E94\u7528\u9996\u9875\uFF0C\u5BF9\u5E94 `src/web/pages/HomePage.tsx`","- `/protected`\uFF1A\u524D\u7AEF\u4FDD\u62A4\u9875\u793A\u4F8B\uFF0C\u5BF9\u5E94 `src/web/pages/ProtectedPage.tsx`","- `/form`\uFF1A\u524D\u7AEF\u8868\u5355\u9875\u793A\u4F8B\uFF0C\u5BF9\u5E94 `src/web/pages/FormPage.tsx`","- `/cms`\uFF1A\u524D\u7AEF CMS \u80FD\u529B\u793A\u4F8B\u9875\uFF0C\u5BF9\u5E94 `src/web/pages/CmsPage.tsx`\uFF0C\u4E0D\u4F5C\u4E3A\u6B63\u5F0F\u5185\u5BB9\u7AD9\u4E3B\u8DEF\u5F84","","## \u63A8\u8350\u5F00\u53D1\u65B9\u5F0F","","- \u65E5\u5E38\u5F00\u53D1\u76F4\u63A5\u7528 `platform dev`\uFF0C\u6A21\u677F\u4F1A\u81EA\u52A8\u62C9\u8D77\u524D\u7AEF\u70ED\u66F4\u65B0\u548C server \u81EA\u52A8\u91CD\u542F\u3002","- \u9700\u8981\u8054\u8C03\u8FDC\u7AEF\u80FD\u529B\u65F6\u7EE7\u7EED\u5728 `platform dev` \u4E0A\u52A0 `--remote-bindings`\uFF0C\u4F8B\u5982 `platform dev --remote-bindings=db`\u3002","- \u4E91\u7AEF\u9A8C\u8BC1\u7528 `platform preview generate`\uFF0C\u6B63\u5F0F\u53D1\u5E03\u7528 `platform publish`\u3002","- SEO \u9875\u9762\u4F18\u5148\u4ECE `src/server/*` \u8D77\u6B65\uFF1B\u524D\u7AEF `src/web/*` \u53EA\u627F\u62C5 SPA \u5E94\u7528\u9996\u9875\u3001\u8868\u5355\u9875\u3001\u4FDD\u62A4\u9875\u548C\u80FD\u529B\u793A\u4F8B\u9875\u3002","- \u6D4F\u89C8\u5668\u59CB\u7EC8\u8BBF\u95EE public port\uFF0C`/api` \u548C `/healthz` \u4F1A\u901A\u8FC7 Vite \u4EE3\u7406\u5230\u672C\u5730 backend \u8FDB\u7A0B\uFF1B\u6392\u67E5\u672C\u5730\u8054\u8C03\u95EE\u9898\u65F6\u5148\u6309\u8FD9\u4E2A\u5FC3\u667A\u7406\u89E3\u3002","- \u65B0\u5EFA app \u4F1A\u9ED8\u8BA4\u751F\u6210 `.platform/platform-blocks.lock.json`\uFF1B\u5982\u679C\u4F60 checkout \u7684\u662F\u5386\u53F2 app\uFF0C\u5148\u6267\u884C `platform app sync-platform-blocks --adopt` \u8865\u7EB3\u7BA1\u3002","- \u63A8\u8350\u540C\u6B65\u987A\u5E8F\uFF1A`platform app sync-platform-blocks --dry-run` -> `--apply` -> \u672C\u5730\u9A8C\u8BC1\uFF1B\u9700\u8981\u65F6\u518D `--rollback --last`\u3002","","## \u5E38\u89C1\u5751","","- \u4E0D\u8981\u5728\u9875\u9762\u91CC\u5199\u6B7B `/previews/...`\u3001`/apps/...`\u3001`https://...` \u8FD9\u7C7B\u5E73\u53F0\u8DEF\u5F84\u524D\u7F00\u3002","- \u6D4F\u89C8\u5668\u4FA7\u8BF7\u6C42\u548C\u8DF3\u8F6C\u4F18\u5148\u7528\u6A21\u677F\u5DF2\u6709 helper\uFF1B\u5982\u679C\u53EA\u662F\u540C\u6E90\u63A5\u53E3\u6216\u9759\u6001\u8D44\u6E90\uFF0C\u4F18\u5148\u4F7F\u7528\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u4F8B\u5982 `./api/...`\u3001`./assets/...`\u3002",'- \u4E0D\u8981\u76F4\u63A5\u5199\u6839\u8DEF\u5F84\u5F15\u7528\uFF0C\u4F8B\u5982 `fetch(\'/api/...\')`\u3001`href="/..."`\u3001`src="/..."`\uFF0C\u8FD9\u7C7B\u5199\u6CD5\u5728 preview path \u6A21\u5F0F\u4E0B\u6700\u5BB9\u6613\u51FA\u9519\u3002',"- `src/web/*` \u8D1F\u8D23\u524D\u7AEF\u4EA4\u4E92\u578B\u9875\u9762\uFF1B`src/server/*` \u8D1F\u8D23\u79C1\u6709 API \u4E0E SEO \u9875\u9762\u76F4\u51FA\uFF0C\u4E0D\u8981\u628A\u4E24\u5C42\u804C\u8D23\u6DF7\u5728\u4E00\u8D77\u3002","- \u60F3\u6539\u670D\u52A1\u7AEF\u9996\u9875\u3001\u9759\u6001\u9875\u3001\u6587\u7AE0\u5217\u8868\u548C\u6587\u7AE0\u8BE6\u60C5\uFF0C\u5C31\u6539 `src/server/*`\uFF1B\u60F3\u6539\u65E7\u7684 SPA \u5E94\u7528\u9996\u9875\u6216\u4EA4\u4E92\u793A\u4F8B\u9875\uFF0C\u5C31\u6539 `src/web/*`\u3002","- \u82E5\u53EA\u662F\u4E1A\u52A1 API \u6269\u5C55\uFF0C\u4F18\u5148\u65B0\u589E\u81EA\u5DF1\u7684 server \u6A21\u5757\u6216\u8DEF\u7531\uFF0C\u4E0D\u8981\u5148\u6539 `src/server/app.ts` \u8FD9\u7C7B\u5E73\u53F0\u8584\u58F3\u5165\u53E3\u3002","- \u65B0\u589E\u79C1\u6709\u63A5\u53E3\u4F18\u5148\u4ECE `src/server/routes/api.ts` \u8D77\u6B65\uFF1B\u65B0\u589E SEO \u9875\u9762\u4F18\u5148\u4ECE `src/server/routes/seo-pages.ts` \u8D77\u6B65\u3002","- \u9700\u8981\u5728 server \u5185\u90E8\u53D7\u63A7\u8BFB\u5199 Data Form \u8D44\u6E90\u65F6\uFF0C\u4F18\u5148\u590D\u7528 `src/server/platform/data-form.ts`\uFF0C\u4E0D\u8981\u624B\u5199\u5E73\u884C fetch client\u3002","- \u9700\u8981\u5728 server \u5185\u90E8\u8BFB\u53D6 CMS \u5185\u5BB9\u65F6\uFF0C\u4F18\u5148\u590D\u7528 `src/server/platform/cms.ts`\uFF0C\u4E0D\u8981\u5728\u6BCF\u4E2A\u9875\u9762\u91CC\u5206\u6563\u624B\u5199\u8BF7\u6C42\u3002","","## \u6570\u636E\u5E93\u4ECE\u54EA\u91CC\u5F00\u59CB","","- \u9996\u6761 migration \u4ECE `resources/db/migrations/0001_init.sql` \u5F00\u59CB\u6539\u3002","- \u8FD9\u4E2A\u6587\u4EF6\u9ED8\u8BA4\u662F\u6CE8\u91CA\u6001\u793A\u4F8B\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u521B\u5EFA\u771F\u5B9E\u8868\u3002","- \u9700\u8981\u843D\u5E93\u65F6\uFF0C\u5148\u628A\u5B83\u6539\u6210\u7B2C\u4E00\u6761\u771F\u5B9E migration\uFF0C\u518D\u6267\u884C\u5E73\u53F0\u7684 DB migrate \u6D41\u7A0B\u3002","- \u6539\u5B8C\u540E\u5EFA\u8BAE\u7ACB\u523B\u6267\u884C `platform db migrate`\uFF0C\u518D\u7528 `platform db status` \u6216 `platform db query` \u9A8C\u8BC1\u8868\u7ED3\u6784\u662F\u5426\u5DF2\u751F\u6548\u3002","","## Data Form \u4ECE\u54EA\u91CC\u5F00\u59CB","","- `Data Form` \u7684\u58F0\u660E\u5165\u53E3\u7EA6\u5B9A\u5728 `resources/data-forms/*.yaml`\u3002","- \u6A21\u677F\u9ED8\u8BA4\u63D0\u4F9B `resources/data-forms/README.md` \u548C `0001_event_signup.yaml.example`\u3002","- `.yaml.example` \u662F\u6CE8\u91CA\u6001\u793A\u4F8B\uFF0C\u4E0D\u4F1A\u88AB `platform data-form validate` \u626B\u63CF\u3002","- \u793A\u4F8B\u5B57\u6BB5\u4E0E\u9ED8\u8BA4 `/form` \u9875\u9762\u4FDD\u6301\u4E00\u81F4\uFF1B\u628A\u5B83\u590D\u5236\u6216\u6539\u540D\u6210\u6B63\u5F0F `*.yaml` \u540E\u5373\u53EF\u76F4\u63A5\u63A5\u771F\u5B9E\u63D0\u4EA4\u6D41\u7A0B\u3002","","## \u4E00\u6761\u7ECF\u9A8C","","- \u5982\u679C\u4E1A\u52A1\u8FD8\u4E0D\u9700\u8981\u79C1\u6709 API \u6216\u6570\u636E\u5E93\uFF0C\u4F18\u5148\u5148\u7528\u524D\u7AEF\u6A21\u677F\u8D77\u6B65\uFF1B\u9700\u8981\u540E\u7AEF\u80FD\u529B\u65F6\uFF0C\u518D\u8FC1\u5230\u8FD9\u4E2A\u6A21\u677F\u5373\u53EF\uFF0C\u524D\u7AEF\u9875\u9762\u5C42\u53EF\u4EE5\u57FA\u672C\u539F\u6837\u590D\u7528\u3002","","## \u6A21\u677F\u66F4\u65B0\u4E0E\u5E73\u53F0\u7EF4\u62A4\u533A","","- `src/web/platform/*`\u3001`src/server/platform/*`\u3001`src/server/app.ts`\u3001`src/server/routes/seo-pages.ts` \u4E0E `.platform/platform-blocks.lock.json` \u9ED8\u8BA4\u5C5E\u4E8E\u7CFB\u7EDF\u7EDF\u4E00\u7EF4\u62A4\u533A\u3002","- \u5E73\u53F0\u6A21\u677F\u5347\u7EA7\u65F6\uFF0C\u4F18\u5148\u6267\u884C `platform app sync-platform-blocks --dry-run` \u770B\u5DEE\u5F02\uFF1B\u786E\u8BA4\u65E0\u51B2\u7A81\u540E\u518D\u6267\u884C `--apply`\u3002","- \u5982\u679C\u5F53\u524D\u5DE5\u7A0B\u662F\u5386\u53F2 app \u4E14\u8FD8\u6CA1\u6709 `.platform/platform-blocks.lock.json`\uFF0C\u5148\u6267\u884C `platform app sync-platform-blocks --adopt`\uFF0C\u518D\u8FDB\u5165\u540E\u7EED\u5347\u7EA7\u3002","- \u82E5\u4F60\u4E3B\u52A8\u4FEE\u6539\u4E86\u8FD9\u4E9B platform-managed \u6587\u4EF6\uFF0C\u540E\u7EED `--apply` \u53EF\u80FD\u8FDB\u5165 conflict\uFF1B\u8FD9\u5C5E\u4E8E\u4FDD\u62A4\u884C\u4E3A\uFF0C\u4E0D\u4F1A\u9759\u9ED8\u8986\u76D6\u3002","- Agent \u5F00\u53D1\u4E1A\u52A1\u529F\u80FD\u65F6\uFF0C\u524D\u7AEF\u4EA4\u4E92\u4F18\u5148\u653E\u5728 `src/web/pages`\u3001`src/web/components`\u3001`public/__app/*`\uFF0C\u540E\u7AEF\u4E1A\u52A1\u63A5\u53E3\u4F18\u5148\u653E\u5728 `src/server/routes/api.ts` \u548C\u4E1A\u52A1\u81EA\u6709\u6A21\u5757\uFF0C\u4E0D\u8981\u5148\u6539\u5E73\u53F0\u8584\u58F3\u3002","- \u82E5 apply \u540E\u9700\u8981\u56DE\u9000\uFF0C\u53EA\u652F\u6301 `platform app sync-platform-blocks --rollback --last`\uFF0C\u5B83\u4F1A\u6062\u590D\u6700\u8FD1\u4E00\u6B21\u771F\u5B9E\u8986\u76D6\u3002",""].join(`
@@ -2194,7 +2193,7 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2194
2193
  `}function buildPageRenderShellExampleSource(){return buildPageRenderShellSource()}function buildPageRenderArticleListTemplateSource(){return["<!doctype html>",'<html lang="zh-CN">'," <head>",' <meta charset="UTF-8">',' <meta name="viewport" content="width=device-width, initial-scale=1.0">'," </head>",' <body class="min-h-screen bg-[linear-gradient(180deg,#f7f4ed_0%,#efebe3_100%)] text-slate-900">',' <div data-shell-slot="header"></div>',' <main class="mx-auto w-[min(1120px,calc(100%-32px))] px-0 py-6 pb-14">',' <section class="grid gap-4 rounded-[24px] border border-stone-300 bg-stone-50 px-7 py-7 shadow-[0_12px_32px_rgba(15,23,42,0.06)]">',' <div class="w-fit rounded-full bg-amber-100 px-3 py-1 text-xs font-bold tracking-[0.12em] text-amber-700">PAGE RENDER SAMPLE</div>',' <h1 class="m-0 text-[clamp(28px,4vw,44px)] font-extrabold leading-[1.1] tracking-tight text-slate-900">\u5185\u5BB9\u5217\u8868\u9875\u6A21\u677F</h1>',' <p class="m-0 text-base leading-7 text-slate-600">\u8FD9\u4E2A\u9875\u9762\u7531\u5E73\u53F0\u5728\u8BF7\u6C42\u65F6\u6309 CMS collection \u6E32\u67D3\u3002\u5217\u8868\u5361\u7247\u3001\u5206\u9875\u548C\u8BE6\u60C5\u8DF3\u8F6C\u90FD\u7531 `page-render` \u914D\u7F6E\u9A71\u52A8\u3002</p>'," </section>",' <form class="mt-6 grid grid-cols-[repeat(auto-fit,minmax(180px,1fr))] gap-3" method="get" action="">',' <input type="search" name="keyword" placeholder="\u6309\u5173\u952E\u5B57\u641C\u7D22" class="min-h-12 rounded-2xl border border-slate-300 bg-white/95 px-4 text-base text-slate-900 placeholder:text-slate-500">',' <input type="text" name="category" placeholder="\u6309\u5206\u7C7B slug \u8FC7\u6EE4" class="min-h-12 rounded-2xl border border-slate-300 bg-white/95 px-4 text-base text-slate-900 placeholder:text-slate-500">',' <button type="submit" class="min-h-12 rounded-2xl border border-slate-800 bg-slate-800 px-4 text-base font-bold text-slate-50">\u5237\u65B0\u5217\u8868</button>'," </form>",' <div data-render-list="article-list-main" class="mt-5 grid grid-cols-[repeat(auto-fit,minmax(260px,1fr))] gap-[18px]">',' <article data-render-template="article-card" class="grid min-h-full gap-3.5 rounded-[22px] border border-slate-200 bg-white p-[18px] shadow-[0_10px_24px_rgba(15,23,42,0.05)]">',' <img data-field="cover" alt="cover" class="aspect-[16/10] w-full rounded-2xl bg-stone-200 object-cover">',' <h2 data-field="title" class="m-0 text-[22px] font-bold leading-[1.3] text-slate-900">\u6587\u7AE0\u6807\u9898</h2>',' <p data-field="summary" class="m-0 text-base leading-7 text-slate-600">\u6587\u7AE0\u6458\u8981</p>',' <a data-field="link" class="inline-flex w-fit items-center gap-2 text-sm font-bold text-amber-700" href="#">\u67E5\u770B\u8BE6\u60C5</a>'," </article>"," </div>",' <nav data-render-pagination="article-list-main" class="mt-6 flex flex-wrap gap-2.5 [&>a]:inline-flex [&>a]:h-10 [&>a]:min-w-10 [&>a]:items-center [&>a]:justify-center [&>a]:rounded-full [&>a]:border [&>a]:border-slate-300 [&>a]:bg-white [&>a]:px-3 [&>a]:text-sm [&>a]:font-semibold [&>a]:text-slate-900 [&>a.is-active]:border-slate-800 [&>a.is-active]:bg-slate-800 [&>a.is-active]:text-white"></nav>'," </main>",' <div data-shell-slot="footer"></div>',' <header data-shell-template="site-header" class="mx-auto flex w-[min(1120px,calc(100%-32px))] items-center justify-between gap-4 border-b border-slate-900/8 py-5">',' <strong class="text-[15px] font-bold text-slate-900">Page Render Sample</strong>',' <nav class="flex flex-wrap gap-3 [&>a]:inline-flex [&>a]:min-h-9 [&>a]:items-center [&>a]:rounded-full [&>a]:border [&>a]:border-slate-900/10 [&>a]:bg-white/80 [&>a]:px-3.5 [&>a]:text-sm [&>a]:font-semibold [&>a]:text-slate-900">',' <a href="./app">App Home</a>',' <a href="./articles">Articles</a>',' <a href="./cms">CMS Page</a>'," </nav>"," </header>",' <footer data-shell-template="site-footer" class="mx-auto flex w-[min(1120px,calc(100%-32px))] items-center justify-between gap-4 border-t border-slate-900/8 py-5 text-sm text-slate-600">',' <span class="text-slate-600">On-demand rendered from CMS delivery data</span>',' <span class="text-slate-600">Progressive enhancement assets loaded from current app build</span>'," </footer>"," </body>","</html>",""].join(`
2195
2194
  `)}function buildPageRenderArticleDetailTemplateSource(){return["<!doctype html>",'<html lang="zh-CN">'," <head>",' <meta charset="UTF-8">',' <meta name="viewport" content="width=device-width, initial-scale=1.0">'," </head>",' <body class="min-h-screen bg-[radial-gradient(circle_at_top_left,rgba(15,118,110,0.12),transparent_30%),linear-gradient(180deg,#fdfaf3_0%,#f3efe7_100%)] text-slate-900">',' <div data-shell-slot="header"></div>',' <main class="mx-auto grid w-[min(1120px,calc(100%-32px))] gap-6 py-6 pb-14">',' <article data-render-detail="article-main" class="rounded-[24px] border border-stone-300 bg-stone-50 px-7 py-7 shadow-[0_12px_32px_rgba(15,23,42,0.06)]">',' <h1 data-field="title" class="mb-4 text-[clamp(30px,4vw,48px)] font-extrabold leading-[1.08] tracking-tight text-slate-900">\u6587\u7AE0\u6807\u9898</h1>',' <div data-field="body" class="article-content text-[15px] leading-8 text-slate-700"><p>\u8FD9\u91CC\u5C06\u7531\u5E73\u53F0\u6309 CMS \u8BE6\u60C5\u5185\u5BB9\u6E32\u67D3\u5BCC\u6587\u672C\u6B63\u6587\u3002</p></div>'," </article>",' <section class="rounded-[24px] border border-stone-300 bg-white px-6 py-6 shadow-[0_10px_24px_rgba(15,23,42,0.05)]">',' <div class="mb-3 w-fit rounded-full bg-teal-100 px-3 py-1 text-xs font-bold tracking-[0.12em] text-teal-700">RELATED</div>',' <h2 class="m-0 text-2xl font-extrabold tracking-tight text-slate-900">\u63A8\u8350\u9605\u8BFB</h2>',' <p class="mb-5 mt-3 text-base leading-7 text-slate-600">\u8BE6\u60C5\u9875\u53EF\u4EE5\u540C\u65F6\u6302\u63A5\u5185\u5BB9\u8BE6\u60C5\u548C\u63A8\u8350\u5217\u8868\uFF0C\u4E0D\u9700\u8981\u5355\u72EC\u8D77\u5E94\u7528\u8FD0\u884C\u65F6\u3002</p>',' <div data-render-list="related-articles" class="grid grid-cols-[repeat(auto-fit,minmax(220px,1fr))] gap-4">',' <article data-render-template="related-card" class="grid min-h-full gap-2.5 rounded-[18px] border border-slate-200 bg-slate-50 p-[18px]">',' <h3 data-field="title" class="m-0 text-xl font-bold leading-[1.35] text-slate-900">\u63A8\u8350\u5185\u5BB9\u6807\u9898</h3>',' <p data-field="summary" class="m-0 text-sm leading-7 text-slate-600">\u63A8\u8350\u5185\u5BB9\u6458\u8981</p>',' <a data-field="link" class="inline-flex w-fit items-center gap-2 text-sm font-bold text-teal-700" href="#">\u7EE7\u7EED\u9605\u8BFB</a>'," </article>"," </div>"," </section>",' <section class="rounded-[24px] border border-stone-300 bg-white px-6 py-6 shadow-[0_10px_24px_rgba(15,23,42,0.05)]">',' <div class="mb-3 w-fit rounded-full bg-fuchsia-100 px-3 py-1 text-xs font-bold tracking-[0.12em] text-fuchsia-700">REACT ISLAND</div>',' <h2 class="m-0 text-2xl font-extrabold tracking-tight text-slate-900">\u6D3B\u52A8\u62A5\u540D\u8868\u5355</h2>',' <p class="mb-5 mt-3 text-base leading-7 text-slate-600">\u6B63\u6587\u548C\u63A8\u8350\u5185\u5BB9\u4ECD\u7531 HTML + CMS \u6E32\u67D3\uFF0C\u4E0B\u9762\u7684\u5B8C\u6574\u8868\u5355\u5219\u5728\u9875\u9762\u52A0\u8F7D\u540E\u7531\u5F53\u524D app bundle \u6302\u8F7D\uFF0C\u590D\u7528\u5DF2\u6709 shadcn/Data Form \u7EC4\u4EF6\u4F53\u7CFB\u3002</p>',' <div data-platform-react-island="event-signup-form"></div>'," </section>"," </main>",' <div data-shell-slot="footer"></div>',' <header data-shell-template="site-header" class="mx-auto flex w-[min(1120px,calc(100%-32px))] items-center justify-between gap-4 border-b border-slate-900/8 py-5">',' <strong class="text-[15px] font-bold text-slate-900">Page Render Sample</strong>',' <nav class="flex flex-wrap gap-3 [&>a]:inline-flex [&>a]:min-h-9 [&>a]:items-center [&>a]:rounded-full [&>a]:border [&>a]:border-slate-900/10 [&>a]:bg-white/80 [&>a]:px-3.5 [&>a]:text-sm [&>a]:font-semibold [&>a]:text-slate-900">',' <a href="./app">App Home</a>',' <a href="./articles">Articles</a>',' <a href="./cms">CMS Page</a>'," </nav>"," </header>",' <footer data-shell-template="site-footer" class="mx-auto flex w-[min(1120px,calc(100%-32px))] items-center justify-between gap-4 border-t border-slate-900/8 py-5 text-sm text-slate-600">',' <span class="text-slate-600">Detail template with progressive enhancement assets</span>',' <span class="text-slate-600">Rendered on demand from CMS delivery data</span>'," </footer>"," </body>","</html>",""].join(`
2196
2195
  `)}function buildPageRenderPostBuildScriptSource(){return['import { cp, mkdir, readFile, rm, stat, writeFile } from "node:fs/promises";','import { join, relative, resolve } from "node:path";',"","const appRoot = process.cwd();",'const sourceDir = resolve(appRoot, "page-render");','const registryPath = resolve(sourceDir, "registry.json");','const distDir = resolve(appRoot, "dist");','const distPageRenderDir = resolve(distDir, "page-render");',"","async function main() {"," if (!(await pathExists(registryPath))) {",' process.stdout.write("[page-render-postbuild] skipped: page-render/registry.json not found\\n");'," return;"," }"," if (!(await pathExists(distDir))) {",' throw new Error("dist directory not found; run vite build before page-render postbuild");'," }",""," await validateJsonFile(registryPath);"," const assetsManifest = await collectAssetsManifest(distDir);",""," await rm(distPageRenderDir, { recursive: true, force: true });"," await mkdir(distPageRenderDir, { recursive: true });"," await cp(sourceDir, distPageRenderDir, { recursive: true });"," await writeFile(",' join(distPageRenderDir, "assets-manifest.json"),',' JSON.stringify(assetsManifest, null, 2) + "\\n",',' "utf8"'," );","",' process.stdout.write("[page-render-postbuild] emitted dist/page-render assets manifest\\n");',"}","","async function collectAssetsManifest(distRoot) {",' const viteManifestPath = join(distRoot, ".vite", "manifest.json");',' const fallbackEntryHtmlPath = join(distRoot, "index.html");'," const css = [];"," const js = [];"," if (await pathExists(viteManifestPath)) {"," const manifest = await readJsonFile(viteManifestPath);"," const entryAssets = collectEntryAssetsFromViteManifest(manifest);"," css.push(...entryAssets.css);"," js.push(...entryAssets.js);"," } else if (await pathExists(fallbackEntryHtmlPath)) {"," const fallbackAssets = await collectAssetsFromHtmlEntry(fallbackEntryHtmlPath);"," css.push(...fallbackAssets.css);"," js.push(...fallbackAssets.js);"," }"," return {"," version: 1,",' mode: "progressive-enhancement",'," css: uniqueStable(css),"," js: uniqueStable(js)"," };","}","","function collectEntryAssetsFromViteManifest(manifest) {",' const entryKey = typeof manifest["index.html"] === "object" && manifest["index.html"] ? "index.html" : findFirstManifestEntryKey(manifest);'," if (!entryKey) {"," return { css: [], js: [] };"," }"," const css = [];"," const js = [];"," const visited = new Set();"," walkManifestEntry(manifest, entryKey, visited, { css, js }, true);"," return { css, js };","}","","function findFirstManifestEntryKey(manifest) {"," for (const [key, value] of Object.entries(manifest)) {",' if (value && typeof value === "object" && value.isEntry && typeof value.file === "string") {'," return key;"," }"," }"," return undefined;","}","","function walkManifestEntry(manifest, entryKey, visited, assets, includeJs) {"," if (visited.has(entryKey)) {"," return;"," }"," visited.add(entryKey);"," const entry = manifest[entryKey];",' if (!entry || typeof entry !== "object") {'," return;"," }",' if (includeJs && typeof entry.file === "string" && entry.file.endsWith(".js")) {'," assets.js.push(stripLeadingSlash(entry.file));"," }"," if (Array.isArray(entry.css)) {"," for (const cssFile of entry.css) {",' if (typeof cssFile === "string" && cssFile.endsWith(".css")) {'," assets.css.push(stripLeadingSlash(cssFile));"," }"," }"," }"," if (Array.isArray(entry.imports)) {"," for (const importKey of entry.imports) {",' if (typeof importKey === "string") {'," walkManifestEntry(manifest, importKey, visited, assets, false);"," }"," }"," }","}","","async function collectAssetsFromHtmlEntry(entryHtmlPath) {",' const html = await readFile(entryHtmlPath, "utf8");',` const css = Array.from(html.matchAll(/<link[^>]+rel=["']stylesheet["'][^>]+href=["']([^"']+)["']/gu)).map((match) => stripLeadingSlash(resolveAssetPath(match[1]))).filter(Boolean);`,` const js = Array.from(html.matchAll(/<script[^>]+type=["']module["'][^>]+src=["']([^"']+)["'][^>]*><\\/script>/gu)).map((match) => stripLeadingSlash(resolveAssetPath(match[1]))).filter(Boolean);`," return { css, js };","}","","function resolveAssetPath(value) {",' if (typeof value !== "string") {',' return "";'," }"," const trimmed = value.trim();",' if (!trimmed || /^https?:\\/\\//.test(trimmed) || trimmed.startsWith("data:")) {',' return "";'," }",' return trimmed.replace(/^\\.\\//, "");',"}","","function stripLeadingSlash(value) {",' return String(value).replace(/^\\/+/, "");',"}","","function uniqueStable(values) {"," const seen = new Set();"," return values.filter((value) => {"," if (!value || seen.has(value)) {"," return false;"," }"," seen.add(value);"," return true;"," });","}","","async function readJsonFile(filePath) {",' const raw = await readFile(filePath, "utf8");'," try {"," return JSON.parse(raw);"," } catch (error) {"," throw new Error(`invalid json file: ${relative(appRoot, filePath)} ${error instanceof Error ? error.message : String(error)}`);"," }","}","","async function validateJsonFile(filePath) {",' const raw = await readFile(filePath, "utf8");'," try {"," JSON.parse(raw);"," } catch (error) {"," throw new Error("," `invalid page-render json: ${relative(appRoot, filePath)} ${error instanceof Error ? error.message : String(error)}`"," );"," }","}","","async function pathExists(targetPath) {"," const target = await stat(targetPath).catch(() => null);"," return Boolean(target);","}","","main().catch((error) => {"," const message = error instanceof Error ? error.stack || error.message : String(error);"," process.stderr.write(`${message}\\n`);"," process.exit(1);","});",""].join(`
2197
- `)}function buildFrontendAppViteTemplateFiles(){let templatePackageName=DEFAULT_TEMPLATE_PACKAGE_NAME;return[{path:"app.yaml",content:buildAppYamlSource2(templatePackageName)},{path:"package.json",content:buildPackageJsonSource2(templatePackageName)},{path:"package-lock.json",content:buildPackageLockSource2(templatePackageName)},{path:"pnpm-workspace.yaml",content:buildPnpmWorkspaceSource()},{path:"README.md",content:buildReadmeSource2()},{path:".env.example",content:buildEnvExampleSource2(templatePackageName)},{path:"scripts/page-render-postbuild.mjs",content:buildPageRenderPostBuildScriptSource()},{path:"tsconfig.json",content:buildTsconfigSource2()},{path:"vite.config.ts",content:buildViteConfigSource2()},{path:"index.html",content:buildIndexHtmlSource2()},{path:"page-render/README.md",content:buildPageRenderReadmeSource()},{path:"page-render/registry.json",content:buildPageRenderRegistrySource()},{path:"page-render/registry.json.example",content:buildPageRenderRegistryExampleSource()},{path:"page-render/pages/article-list.page-render.json",content:buildPageRenderListConfigSource()},{path:"page-render/pages/article-list.page-render.json.example",content:buildPageRenderListExampleSource()},{path:"page-render/pages/article-detail.page-render.json",content:buildPageRenderDetailConfigSource()},{path:"page-render/pages/article-detail.page-render.json.example",content:buildPageRenderDetailExampleSource()},{path:"page-render/shells/default.shell.json",content:buildPageRenderShellSource()},{path:"page-render/shells/default.shell.json.example",content:buildPageRenderShellExampleSource()},{path:"public/site/article-list.html",content:buildPageRenderArticleListTemplateSource()},{path:"public/site/article-detail.html",content:buildPageRenderArticleDetailTemplateSource()},{path:"public/shared/shells/.gitkeep",content:""},{path:"public/shared/styles/.gitkeep",content:""},{path:"public/shared/scripts/.gitkeep",content:""},{path:"src/main.tsx",content:buildMainSource()},{path:"src/page-render/react-islands.tsx",content:buildReactIslandsSource()},...buildWebSharedPageFiles("src",{buildRouterAppSource,buildHomePageSource:()=>buildFrontendShowcaseHomePageSource(),buildFormPageSource,buildEventSignupFormSource,buildProtectedPageSource,buildCmsPageSource}),{path:"public/auth/index.html",content:buildAuthIndexHtmlSource()},{path:"public/__app/auth-ui.config.json",content:buildAuthUiConfigJsonSource()},{path:"public/__app/auth-ui.override.css",content:buildGeneratedAppAuthUiOverrideCssModuleSource()},{path:"src/styles/index.css",content:buildStylesSource()},{path:"src/styles/cms-content.css",content:buildCmsContentStylesSource()},{path:"src/vite-env.d.ts",content:buildViteEnvSource()},...buildWebSharedDataFormUiFiles("src"),{path:"resources/data-forms/README.md",content:buildDataFormsReadmeSource2()},{path:"resources/data-forms/0001_event_signup.yaml.example",content:buildDataFormExampleSource2()},...buildWebSharedPlatformFiles("src",{buildPlatformConfigSource,buildPlatformClientSource,buildPlatformErrorsSource,buildCapabilitiesIndexSource,buildCapabilitySource})]}function assembleFrontendAppViteTemplate(){let files=buildFrontendAppViteTemplateFiles(),manifest=buildPlatformBlocksManifestFromTemplateFiles("frontend-app-vite",files);return[...files,{path:".platform/platform-blocks.lock.json",content:stringifyPlatformBlocksLockfile(buildPlatformBlocksLockfile(manifest))}]}function getPlatformBlocksManifest(templateKey){let files=templateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();return buildPlatformBlocksManifestFromTemplateFiles(templateKey,files)}import{mkdtempSync,readFileSync as readFileSync4,writeFileSync}from"node:fs";import{basename,extname,join,resolve as resolve2}from"node:path";import{tmpdir}from"node:os";import{spawn}from"node:child_process";async function runAssetCommand(args,deps){if(hasHelpFlag(args)||args.rest.length===0){printAssetHelp();return}let subcommand=args.rest[0];if(subcommand==="upload"){await runAssetUpload(args,deps);return}if(subcommand==="list"){await runAssetList(args,deps);return}if(subcommand==="folder"){await runAssetFolder(args,deps);return}if(subcommand==="get"){await runAssetGet(args,deps);return}if(subcommand==="move"){await runAssetMove(args,deps);return}if(subcommand==="update"){await runAssetUpdate(args,deps);return}if(subcommand==="analyze"){await runAssetAnalyze(args,deps);return}if(subcommand==="open"){await runAssetOpen(args,deps);return}if(subcommand==="download"){await runAssetDownload(args,deps);return}if(subcommand==="tag"){await runAssetTag(args,deps);return}throw new Error("`platform asset` \u4EC5\u652F\u6301 `upload`\u3001`list`\u3001`get`\u3001`move`\u3001`update`\u3001`analyze`\u3001`open`\u3001`download`\u3001`folder`\u3001`tag`\u3002")}function printAssetHelp(){process.stdout.write(["platform asset <command>","","Commands:"," platform asset upload <file-path> [--title <title>] [--folder-id <folder-id>] [--json]"," platform asset list [--q <keyword>] [--media-type image|video] [--mime-type <mime>] [--folder-id <folder-id>] [--tag-ids <id,id>] [--has-ocr true|false] [--has-person true|false] [--is-svg true|false] [--scene <scene>] [--objects <name,name>] [--safety-flags <flag,flag>] [--orientation landscape|portrait|square] [--page <n>] [--limit <n>] [--json]"," platform asset folder list [--json]"," platform asset folder create <name> [--parent-folder-id <folder-id>] [--json]"," platform asset folder rename <folder-id> --name <name> [--parent-folder-id <folder-id>] [--root] [--json]"," platform asset get <asset-id> [--json]"," platform asset move <asset-id> [--folder-id <folder-id> | --root] [--json]"," platform asset update <asset-id> [--title <title>] [--folder-id <folder-id> | --root] [--summary <text>] [--caption <text>] [--scene <scene>] [--objects <name,name>] [--ocr <text>] [--colors <hex,hex>] [--safety-flags <flag,flag>] [--tags <label,label>] [--json]"," 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>] [--json]"," platform asset tag add <asset-id> <label> [--json]"," platform asset tag remove <asset-id> <label> [--json]","","Notes:"," - \u7B2C\u4E00\u9636\u6BB5\u4EE5 tenant/workspace \u4E3A\u4E3B\uFF0C\u4E0D\u8981\u6C42 app/consumer \u4E0A\u4E0B\u6587"," - `list` \u652F\u6301\u7CBE\u786E\u68C0\u7D22 + \u7ED3\u6784\u5316\u8FC7\u6EE4\uFF1B\u4E0D\u5355\u72EC\u63D0\u4F9B `search` \u5B50\u547D\u4EE4"," - `update` \u4E00\u6B21\u547D\u4EE4\u53EF patch \u591A\u4E2A\u5143\u6570\u636E\u5B57\u6BB5\uFF1B\u4E0D\u66FF\u6362\u539F\u59CB\u6587\u4EF6"," - `analyze` \u4E0D\u8C03\u7528\u89C6\u89C9\u6A21\u578B\u3001\u4E0D\u4E0A\u4F20\u56FE\u7247\uFF1B\u4EC5\u6839\u636E\u5143\u6570\u636E\u7ED9\u51FA\u300C\u4E0B\u8F7D\u54EA\u4E00\u7248 + \u5982\u4F55 update\u300D\u7684\u5EFA\u8BAE\uFF1B`--json` \u8F93\u51FA\u540C\u4E0A\u7ED3\u6784\u4FBF\u4E8E\u811A\u672C\u89E3\u6790"," - `analyze` \u53EF\u7528\u4E8E\u7ED9\u4EBA\u5DE5\u6216\u52A9\u624B\u751F\u6210\u5206\u6790\u64CD\u4F5C\u63D0\u793A\uFF0C\u4E0D\u76F4\u63A5\u8BFB\u53D6\u50CF\u7D20\u5185\u5BB9"," - `open` \u4F1A\u4E0B\u8F7D\u539F\u59CB\u6587\u4EF6\uFF1B\u672A\u6307\u5B9A `--output` \u65F6\u4F1A\u5199\u5165\u4E34\u65F6\u76EE\u5F55\u5E76\u5C1D\u8BD5\u6253\u5F00"," - `download --variant` \u7528\u4E8E\u660E\u786E\u4E0B\u8F7D\u6307\u5B9A\u53D8\u4F53\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u6253\u5F00",""].join(`
2196
+ `)}function buildFrontendAppViteTemplateFiles(){let templatePackageName=DEFAULT_TEMPLATE_PACKAGE_NAME;return[{path:"app.yaml",content:buildAppYamlSource2(templatePackageName)},{path:"package.json",content:buildPackageJsonSource2(templatePackageName)},{path:"package-lock.json",content:buildPackageLockSource2(templatePackageName)},{path:"pnpm-workspace.yaml",content:buildPnpmWorkspaceSource()},{path:"README.md",content:buildReadmeSource2()},{path:".env.example",content:buildEnvExampleSource2(templatePackageName)},{path:"scripts/page-render-postbuild.mjs",content:buildPageRenderPostBuildScriptSource()},{path:"tsconfig.json",content:buildTsconfigSource2()},{path:"vite.config.ts",content:buildViteConfigSource2()},{path:"index.html",content:buildIndexHtmlSource2()},{path:"page-render/README.md",content:buildPageRenderReadmeSource()},{path:"page-render/registry.json",content:buildPageRenderRegistrySource()},{path:"page-render/registry.json.example",content:buildPageRenderRegistryExampleSource()},{path:"page-render/pages/article-list.page-render.json",content:buildPageRenderListConfigSource()},{path:"page-render/pages/article-list.page-render.json.example",content:buildPageRenderListExampleSource()},{path:"page-render/pages/article-detail.page-render.json",content:buildPageRenderDetailConfigSource()},{path:"page-render/pages/article-detail.page-render.json.example",content:buildPageRenderDetailExampleSource()},{path:"page-render/shells/default.shell.json",content:buildPageRenderShellSource()},{path:"page-render/shells/default.shell.json.example",content:buildPageRenderShellExampleSource()},{path:"public/site/article-list.html",content:buildPageRenderArticleListTemplateSource()},{path:"public/site/article-detail.html",content:buildPageRenderArticleDetailTemplateSource()},{path:"public/shared/shells/.gitkeep",content:""},{path:"public/shared/styles/.gitkeep",content:""},{path:"public/shared/scripts/.gitkeep",content:""},{path:"src/main.tsx",content:buildMainSource()},{path:"src/page-render/react-islands.tsx",content:buildReactIslandsSource()},...buildWebSharedPageFiles("src",{buildRouterAppSource,buildHomePageSource:()=>buildFrontendShowcaseHomePageSource(),buildFormPageSource,buildEventSignupFormSource,buildProtectedPageSource,buildCmsPageSource}),{path:"public/auth/index.html",content:buildAuthIndexHtmlSource()},{path:"public/__app/auth-ui.config.json",content:buildAuthUiConfigJsonSource()},{path:"public/__app/auth-ui.override.css",content:buildGeneratedAppAuthUiOverrideCssModuleSource()},{path:"src/styles/index.css",content:buildStylesSource()},{path:"src/styles/cms-content.css",content:buildCmsContentStylesSource()},{path:"src/vite-env.d.ts",content:buildViteEnvSource()},...buildWebSharedDataFormUiFiles("src"),{path:"resources/data-forms/README.md",content:buildDataFormsReadmeSource2()},{path:"resources/data-forms/0001_event_signup.yaml.example",content:buildDataFormExampleSource2()},...buildWebSharedPlatformFiles("src",{buildPlatformConfigSource,buildPlatformClientSource,buildPlatformErrorsSource,buildCapabilitiesIndexSource,buildCapabilitySource})]}function assembleFrontendAppViteTemplate(){let files=buildFrontendAppViteTemplateFiles(),manifest=buildPlatformBlocksManifestFromTemplateFiles("frontend-app-vite",files);return[...files,{path:".platform/platform-blocks.lock.json",content:stringifyPlatformBlocksLockfile(buildPlatformBlocksLockfile(manifest))}]}function getPlatformBlocksManifest(templateKey){let files=templateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();return buildPlatformBlocksManifestFromTemplateFiles(templateKey,files)}import{mkdtempSync,readFileSync as readFileSync4,writeFileSync}from"node:fs";import{basename,extname,join,resolve as resolve2}from"node:path";import{tmpdir}from"node:os";import{spawn as nodeSpawn}from"node:child_process";import{readdir,readFile}from"node:fs/promises";import path from"node:path";import crossSpawn from"cross-spawn";import{zipSync}from"fflate";function spawnCrossPlatform(command,args,options={}){return crossSpawn(command,[...args],{...options,shell:!1})}async function terminateProcessTree(pid,options={}){if((options.platform??process.platform)==="win32"){let spawnImpl=options.spawnImpl??nodeSpawn;await new Promise((resolve17,reject)=>{let child;try{child=spawnImpl("taskkill.exe",["/PID",String(pid),"/T","/F"],{shell:!1,stdio:"ignore",windowsHide:!0})}catch(error){reject(error instanceof Error?error:new Error(String(error)));return}child.once("error",error=>{reject(error instanceof Error?error:new Error(String(error)))}),child.once("exit",(code2,signal)=>{if(signal){reject(new Error(`taskkill.exe was terminated by ${signal}`));return}if(code2!==0){reject(new Error(`taskkill.exe exited with status ${code2??"unknown"}`));return}resolve17()})});return}let killImpl=options.killImpl??process.kill.bind(process);try{killImpl(-pid,"SIGTERM")}catch(error){if(error.code==="ESRCH")return;throw error}}async function openExternal(target,options={}){let normalizedTarget=target.trim();if(!normalizedTarget)return{opened:!1,error:"Cannot open an empty target."};let platform=options.platform??process.platform,spawnImpl=options.spawnImpl??nodeSpawn,launcher=platform==="win32"?{command:"rundll32.exe",args:["url.dll,FileProtocolHandler",normalizedTarget]}:platform==="darwin"?{command:"open",args:[normalizedTarget]}:{command:"xdg-open",args:[normalizedTarget]};return await new Promise(resolve17=>{let child;try{child=spawnImpl(launcher.command,launcher.args,{detached:!0,stdio:"ignore",windowsHide:!0})}catch(error){resolve17({opened:!1,error:toErrorMessage(error)});return}child.once("error",error=>{resolve17({opened:!1,error:toErrorMessage(error)})}),child.once("spawn",()=>{child.unref(),resolve17({opened:!0})})})}async function createZipBuffer(directory){let archive=Object.create(null);return await addDirectoryToArchive(path.resolve(directory),"",archive),zipSync(archive,{level:6})}async function addDirectoryToArchive(directory,relativeDirectory,archive){let entries=await readdir(directory,{withFileTypes:!0});entries.sort((left,right)=>compareCodeUnits(left.name,right.name));for(let entry of entries){let absolutePath=path.join(directory,entry.name),relativePath=relativeDirectory?`${relativeDirectory}/${entry.name}`:entry.name;if(entry.isDirectory()){await addDirectoryToArchive(absolutePath,relativePath,archive);continue}if(entry.isSymbolicLink())throw new Error(`Cannot add symbolic link to portable ZIP archive: ${relativePath}`);if(!entry.isFile())throw new Error(`Cannot add unsupported filesystem entry to ZIP archive: ${relativePath}`);if(relativePath==="__proto__")throw new Error("Cannot add reserved root ZIP entry name: __proto__");archive[relativePath]=[await readFile(absolutePath),{mtime:new Date(1980,0,1,0,0,0)}]}}function compareCodeUnits(left,right){return left<right?-1:left>right?1:0}function toErrorMessage(error){return error instanceof Error?error.message:String(error)}async function runAssetCommand(args,deps){if(hasHelpFlag(args)||args.rest.length===0){printAssetHelp();return}let subcommand=args.rest[0];if(subcommand==="upload"){await runAssetUpload(args,deps);return}if(subcommand==="list"){await runAssetList(args,deps);return}if(subcommand==="folder"){await runAssetFolder(args,deps);return}if(subcommand==="get"){await runAssetGet(args,deps);return}if(subcommand==="move"){await runAssetMove(args,deps);return}if(subcommand==="update"){await runAssetUpdate(args,deps);return}if(subcommand==="analyze"){await runAssetAnalyze(args,deps);return}if(subcommand==="open"){await runAssetOpen(args,deps);return}if(subcommand==="download"){await runAssetDownload(args,deps);return}if(subcommand==="tag"){await runAssetTag(args,deps);return}throw new Error("`platform asset` \u4EC5\u652F\u6301 `upload`\u3001`list`\u3001`get`\u3001`move`\u3001`update`\u3001`analyze`\u3001`open`\u3001`download`\u3001`folder`\u3001`tag`\u3002")}function printAssetHelp(){process.stdout.write(["platform asset <command>","","Commands:"," platform asset upload <file-path> [--title <title>] [--folder-id <folder-id>] [--json]"," platform asset list [--q <keyword>] [--media-type image|video] [--mime-type <mime>] [--folder-id <folder-id>] [--tag-ids <id,id>] [--has-ocr true|false] [--has-person true|false] [--is-svg true|false] [--scene <scene>] [--objects <name,name>] [--safety-flags <flag,flag>] [--orientation landscape|portrait|square] [--page <n>] [--limit <n>] [--json]"," platform asset folder list [--json]"," platform asset folder create <name> [--parent-folder-id <folder-id>] [--json]"," platform asset folder rename <folder-id> --name <name> [--parent-folder-id <folder-id>] [--root] [--json]"," platform asset get <asset-id> [--json]"," platform asset move <asset-id> [--folder-id <folder-id> | --root] [--json]"," platform asset update <asset-id> [--title <title>] [--folder-id <folder-id> | --root] [--summary <text>] [--caption <text>] [--scene <scene>] [--objects <name,name>] [--ocr <text>] [--colors <hex,hex>] [--safety-flags <flag,flag>] [--tags <label,label>] [--json]"," 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>] [--json]"," platform asset tag add <asset-id> <label> [--json]"," platform asset tag remove <asset-id> <label> [--json]","","Notes:"," - \u7B2C\u4E00\u9636\u6BB5\u4EE5 tenant/workspace \u4E3A\u4E3B\uFF0C\u4E0D\u8981\u6C42 app/consumer \u4E0A\u4E0B\u6587"," - `list` \u652F\u6301\u7CBE\u786E\u68C0\u7D22 + \u7ED3\u6784\u5316\u8FC7\u6EE4\uFF1B\u4E0D\u5355\u72EC\u63D0\u4F9B `search` \u5B50\u547D\u4EE4"," - `update` \u4E00\u6B21\u547D\u4EE4\u53EF patch \u591A\u4E2A\u5143\u6570\u636E\u5B57\u6BB5\uFF1B\u4E0D\u66FF\u6362\u539F\u59CB\u6587\u4EF6"," - `analyze` \u4E0D\u8C03\u7528\u89C6\u89C9\u6A21\u578B\u3001\u4E0D\u4E0A\u4F20\u56FE\u7247\uFF1B\u4EC5\u6839\u636E\u5143\u6570\u636E\u7ED9\u51FA\u300C\u4E0B\u8F7D\u54EA\u4E00\u7248 + \u5982\u4F55 update\u300D\u7684\u5EFA\u8BAE\uFF1B`--json` \u8F93\u51FA\u540C\u4E0A\u7ED3\u6784\u4FBF\u4E8E\u811A\u672C\u89E3\u6790"," - `analyze` \u53EF\u7528\u4E8E\u7ED9\u4EBA\u5DE5\u6216\u52A9\u624B\u751F\u6210\u5206\u6790\u64CD\u4F5C\u63D0\u793A\uFF0C\u4E0D\u76F4\u63A5\u8BFB\u53D6\u50CF\u7D20\u5185\u5BB9"," - `open` \u4F1A\u4E0B\u8F7D\u539F\u59CB\u6587\u4EF6\uFF1B\u672A\u6307\u5B9A `--output` \u65F6\u4F1A\u5199\u5165\u4E34\u65F6\u76EE\u5F55\u5E76\u5C1D\u8BD5\u6253\u5F00"," - `download --variant` \u7528\u4E8E\u660E\u786E\u4E0B\u8F7D\u6307\u5B9A\u53D8\u4F53\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u6253\u5F00",""].join(`
2198
2197
  `))}async function runAssetList(args,deps){let response=await deps.sdk.listTenantAssets({...readStringOption(args,"q")?{q:readStringOption(args,"q")}:{},...readMediaTypeOption(args)?{media_type:readMediaTypeOption(args)}:{},...readStringOption(args,"mime-type")?{mime_type:readStringOption(args,"mime-type")}:{},...readStringOption(args,"folder-id")?{folder_id:readStringOption(args,"folder-id")}:{},...readCsvOption(args,"tag-ids").length>0?{tag_ids:readCsvOption(args,"tag-ids")}:{},...readBooleanOption(args,"has-ocr")!==void 0?{has_ocr:readBooleanOption(args,"has-ocr")}:{},...readBooleanOption(args,"has-person")!==void 0?{has_person:readBooleanOption(args,"has-person")}:{},...readBooleanOption(args,"is-svg")!==void 0?{is_svg:readBooleanOption(args,"is-svg")}:{},...readStringOption(args,"scene")?{scene:readStringOption(args,"scene")}:{},...readCsvOption(args,"objects").length>0?{objects:readCsvOption(args,"objects")}:{},...readCsvOption(args,"safety-flags").length>0?{safety_flags:readCsvOption(args,"safety-flags")}:{},...readOrientationOption(args)?{orientation:readOrientationOption(args)}:{},...readNumberOption(args,"page")!==void 0?{page:readNumberOption(args,"page")}:{},...readNumberOption(args,"limit")!==void 0?{limit:readNumberOption(args,"limit")}:{}}).catch(error=>{throw formatAssetError(error,"list")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
2199
2198
  `);return}process.stdout.write([`tenant/workspace: ${response.tenant_id}/${response.workspace_id}`,`assets: ${response.items.length}`,`page: ${response.page}/${Math.max(1,Math.ceil(response.total/Math.max(1,response.page_size)))}`,`page_size: ${response.page_size}`,`total: ${response.total}`,...response.items.map(item=>[item.asset.asset_id,item.asset.title,`mime=${item.asset.mime_type}`,`folder=${item.folder?.path??"/"}`,item.tags.length>0?`tags=${item.tags.map(tag=>tag.label).join(",")}`:"tags=-"].join(" ")),""].join(`
2200
2199
  `))}async function runAssetFolder(args,deps){let action=args.rest[1];if(action==="list"){let response=await deps.sdk.listTenantAssetFolders().catch(error=>{throw formatAssetError(error,"folder list")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
@@ -2214,7 +2213,7 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2214
2213
  `);return}process.stdout.write(["\u7D20\u6750\u5143\u6570\u636E\u5DF2\u66F4\u65B0\u3002",`asset: ${response.asset.asset_id}`,`title: ${response.asset.title}`,`folder: ${response.folder?.path??"/"}`,`tags: ${response.tags.length>0?response.tags.map(item=>item.label).join(", "):"-"}`,`ai_summary: ${response.ai_card.ai_summary??"-"}`,""].join(`
2215
2214
  `))}async function runAssetAnalyze(args,deps){let assetId=args.rest[1]??readStringOption(args,"asset");if(!assetId)throw new Error("`platform asset analyze` \u9700\u8981 <asset-id>\u3002");let response=await deps.sdk.getTenantAsset(assetId).catch(error=>{throw formatAssetError(error,"analyze")}),recommendedSource=pickRecommendedAnalysisSource(response),updateTemplate=buildAnalyzeUpdateTemplate(response.asset.asset_id),updateOneLine=flattenShellContinuation(updateTemplate),steps=[`\u67E5\u770B\u5F53\u524D\u7D20\u6750\u8BE6\u60C5\uFF1Aplatform asset get ${response.asset.asset_id}`,recommendedSource.kind==="original"?`\u4E0B\u8F7D\u539F\u59CB\u6587\u4EF6\u8FDB\u884C\u5206\u6790\uFF1Aplatform asset open ${response.asset.asset_id}`:`\u4F18\u5148\u4E0B\u8F7D ${recommendedSource.kind} \u53D8\u4F53\u8FDB\u884C\u5206\u6790\uFF1Aplatform asset download ${response.asset.asset_id} --variant ${recommendedSource.kind}`,"\u7ED3\u5408\u56FE\u7247\u5185\u5BB9\u8865\u9F50 summary / caption / scene / objects / tags\u3002",`\u4F7F\u7528 update \u4E00\u6B21\u6027\u56DE\u586B\u5143\u6570\u636E\uFF1A${updateOneLine}`];if(args.options.json===!0){process.stdout.write(`${JSON.stringify({intent:"workflow_playbook",note:"\u975E\u81EA\u52A8\u8BC6\u56FE\uFF1B\u8BF7\u4E0B\u8F7D recommended_source \u5BF9\u5E94\u6587\u4EF6\u540E\u4EBA\u5DE5\u6216\u501F\u52A9\u52A9\u624B\u586B\u5199\u5360\u4F4D\u7B26\uFF0C\u518D\u6267\u884C update\u3002",asset_id:response.asset.asset_id,title:response.asset.title,media_type:response.asset.media_type,mime_type:response.asset.mime_type,folder:response.folder?.path??"/",original_url:response.original_url,variant_urls:response.variant_urls,recommended_source:recommendedSource,steps,update_template:updateTemplate,update_command_one_line:updateOneLine},null,2)}
2216
2215
  `);return}process.stdout.write(["\u7D20\u6750\u5206\u6790\u5EFA\u8BAE",`asset: ${response.asset.asset_id}`,`title: ${response.asset.title}`,`media_type: ${response.asset.media_type}`,`mime_type: ${response.asset.mime_type}`,`folder: ${response.folder?.path??"/"}`,`recommended_source: ${recommendedSource.kind}`,`recommended_url: ${recommendedSource.url}`,"","\u63A8\u8350\u6B65\u9AA4\uFF1A",...steps.map((step,index)=>`${index+1}. ${step}`),"","\u53EF\u76F4\u63A5\u4FEE\u6539\u7684 update \u6A21\u677F\uFF08\u591A\u884C\uFF0C\u4FBF\u4E8E\u7C98\u8D34\u5230 shell\uFF09\uFF1A",updateTemplate,"","\u5355\u884C\uFF08\u4FBF\u4E8E\u590D\u5236\uFF09\uFF1A",updateOneLine,""].join(`
2217
- `))}async function runAssetOpen(args,deps){let assetId=args.rest[1]??readStringOption(args,"asset");if(!assetId)throw new Error("`platform asset open` \u9700\u8981 <asset-id>\u3002");let detail=await deps.sdk.getTenantAsset(assetId).catch(error=>{throw formatAssetError(error,"get")}),content=await deps.sdk.downloadTenantAssetOriginal(assetId).catch(error=>{throw formatAssetError(error,"open")}),outputPath=resolveOutputPath(readStringOption(args,"output"),detail.original_file.file_name);writeFileSync(outputPath,Buffer.from(content));let opened=readStringOption(args,"output")?!1:tryOpenLocalFile(outputPath);process.stdout.write(["\u7D20\u6750\u539F\u59CB\u6587\u4EF6\u5DF2\u51C6\u5907\u5C31\u7EEA\u3002",`asset: ${detail.asset.asset_id}`,`title: ${detail.asset.title}`,`file: ${detail.original_file.file_name}`,`saved_to: ${outputPath}`,opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u7A0B\u5E8F\u4E2D\u6253\u5F00\u3002":"\u672A\u81EA\u52A8\u6253\u5F00\uFF1B\u5982\u9700\u67E5\u770B\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\u4FDD\u5B58\u8DEF\u5F84\u3002",""].join(`
2216
+ `))}async function runAssetOpen(args,deps){let assetId=args.rest[1]??readStringOption(args,"asset");if(!assetId)throw new Error("`platform asset open` \u9700\u8981 <asset-id>\u3002");let detail=await deps.sdk.getTenantAsset(assetId).catch(error=>{throw formatAssetError(error,"get")}),content=await deps.sdk.downloadTenantAssetOriginal(assetId).catch(error=>{throw formatAssetError(error,"open")}),outputPath=resolveOutputPath(readStringOption(args,"output"),detail.original_file.file_name);writeFileSync(outputPath,Buffer.from(content));let opened=readStringOption(args,"output")?!1:(await openExternal(outputPath)).opened;process.stdout.write(["\u7D20\u6750\u539F\u59CB\u6587\u4EF6\u5DF2\u51C6\u5907\u5C31\u7EEA\u3002",`asset: ${detail.asset.asset_id}`,`title: ${detail.asset.title}`,`file: ${detail.original_file.file_name}`,`saved_to: ${outputPath}`,opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u7A0B\u5E8F\u4E2D\u6253\u5F00\u3002":"\u672A\u81EA\u52A8\u6253\u5F00\uFF1B\u5982\u9700\u67E5\u770B\uFF0C\u8BF7\u624B\u52A8\u6253\u5F00\u4FDD\u5B58\u8DEF\u5F84\u3002",""].join(`
2218
2217
  `))}async function runAssetDownload(args,deps){let assetId=args.rest[1]??readStringOption(args,"asset");if(!assetId)throw new Error("`platform asset download` \u9700\u8981 <asset-id>\u3002");let variantKind=readVariantKindOption(args);if(!variantKind)throw new Error("`platform asset download` \u9700\u8981 `--variant thumbnail|sm|md|lg|cover`\u3002");let detail=await deps.sdk.getTenantAsset(assetId).catch(error=>{throw formatAssetError(error,"get")}),content=await deps.sdk.downloadTenantAssetVariant(assetId,variantKind).catch(error=>{throw formatAssetError(error,"download")}),outputPath=resolveOutputPath(readStringOption(args,"output"),buildVariantFileName(detail.original_file.file_name,detail.variants,variantKind));writeFileSync(outputPath,Buffer.from(content)),process.stdout.write(["\u7D20\u6750\u53D8\u4F53\u5DF2\u4E0B\u8F7D\u3002",`asset: ${detail.asset.asset_id}`,`title: ${detail.asset.title}`,`variant: ${variantKind}`,`saved_to: ${outputPath}`,""].join(`
2219
2218
  `))}async function runAssetTag(args,deps){let action=args.rest[1];if(action==="list"){let response=await deps.sdk.listTenantAssetTags({assetId:readStringOption(args,"asset")}).catch(error=>{throw formatAssetError(error,"tag list")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
2220
2219
  `);return}process.stdout.write([`tenant: ${deps.tenantId}`,`tags: ${response.items.length}`,...response.items.map(item=>`${item.tag_id} ${item.label}`)].join(`
@@ -2222,11 +2221,12 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2222
2221
  `);return}if(action==="add"||action==="remove"){let assetId=args.rest[2],label=args.rest[3];if(!assetId||!label)throw new Error(`\`platform asset tag ${action}\` \u9700\u8981 <asset-id> <label>\u3002`);let response=action==="add"?await deps.sdk.addTenantAssetTag(assetId,{label}).catch(error=>{throw formatAssetError(error,"tag add")}):await deps.sdk.removeTenantAssetTag(assetId,label).catch(error=>{throw formatAssetError(error,"tag remove")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
2223
2222
  `);return}process.stdout.write([action==="add"?"\u7D20\u6750\u6807\u7B7E\u5DF2\u6DFB\u52A0\u3002":"\u7D20\u6750\u6807\u7B7E\u5DF2\u79FB\u9664\u3002",`asset: ${response.asset.asset_id}`,`tags: ${response.tags.length>0?response.tags.map(item=>item.label).join(", "):"-"}`,""].join(`
2224
2223
  `));return}throw new Error("`platform asset tag` \u4EC5\u652F\u6301 `list`\u3001`add <asset-id> <label>`\u3001`remove <asset-id> <label>`\u3002")}function readStringOption(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function hasOption(args,key){return Object.prototype.hasOwnProperty.call(args.options,key)}function readCsvOption(args,key){return(readStringOption(args,key)??"").split(",").map(item=>item.trim()).filter(Boolean)}function readBooleanOption(args,key){let value=readStringOption(args,key);if(value!==void 0){if(value==="true")return!0;if(value==="false")return!1;throw new Error(`\`--${key}\` \u4EC5\u652F\u6301 true \u6216 false\u3002`)}}function readNumberOption(args,key){let value=readStringOption(args,key);if(value===void 0)return;let parsed=Number(value);if(!Number.isFinite(parsed))throw new Error(`\`--${key}\` \u9700\u8981\u6570\u5B57\u3002`);return Math.trunc(parsed)}function readMediaTypeOption(args){let value=readStringOption(args,"media-type");if(value){if(value==="image"||value==="video")return value;throw new Error("`--media-type` \u4EC5\u652F\u6301 image \u6216 video\u3002")}}function readOrientationOption(args){let value=readStringOption(args,"orientation");if(value){if(value==="landscape"||value==="portrait"||value==="square")return value;throw new Error("`--orientation` \u4EC5\u652F\u6301 landscape\u3001portrait\u3001square\u3002")}}function readVariantKindOption(args){let value=readStringOption(args,"variant");if(value){if(value==="thumbnail"||value==="sm"||value==="md"||value==="lg"||value==="cover")return value;throw new Error("`--variant` \u4EC5\u652F\u6301 thumbnail\u3001sm\u3001md\u3001lg\u3001cover\u3002")}}function pickRecommendedAnalysisSource(detail){let mdUrl=detail.variant_urls.md;if(mdUrl)return{kind:"md",url:mdUrl};let smUrl=detail.variant_urls.sm;if(smUrl)return{kind:"sm",url:smUrl};let thumbnailUrl=detail.variant_urls.thumbnail;return thumbnailUrl?{kind:"thumbnail",url:thumbnailUrl}:{kind:"original",url:detail.original_url}}function hasHelpFlag(args){return args.options.help===!0||args.options.h===!0}function inferMimeType(fileName){switch(extname(fileName).toLowerCase()){case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".webp":return"image/webp";case".gif":return"image/gif";case".svg":return"image/svg+xml";case".mp4":return"video/mp4";case".mov":return"video/quicktime";case".webm":return"video/webm";default:throw new Error(`\u5F53\u524D\u4EC5\u652F\u6301\u5E38\u89C1\u56FE\u7247\u4E0E\u89C6\u9891\u6269\u5C55\u540D\uFF0C\u65E0\u6CD5\u8BC6\u522B\u6587\u4EF6\u7C7B\u578B: ${fileName}`)}}function formatVariantLines(variantUrls){let lines=Object.entries(variantUrls).filter(entry=>typeof entry[1]=="string"&&entry[1].length>0).map(([kind,url])=>`variant.${kind}: ${url}`);return lines.length>0?lines:["variant: -"]}function normalizeNullableCliText(value){let normalized=value?.trim()??"";return normalized||null}function buildAnalyzeUpdateTemplate(assetId){return[`platform asset update ${assetId} \\`,' --summary "..." \\',' --caption "..." \\',' --scene "..." \\',' --objects "..." \\',' --tags "..."'].join(`
2225
- `)}function flattenShellContinuation(template){return template.replace(/\s*\\\s*\n\s*/g," ").replace(/\s{2,}/g," ").trim()}function buildVariantFileName(originalFileName,variants,variantKind){let variant=variants.find(item=>item.variant_kind===variantKind),extension=variant?inferExtensionFromMimeType(variant.mime_type):extname(originalFileName)||".bin";return`${basename(originalFileName,extname(originalFileName))}.${variantKind}${extension}`}function inferExtensionFromMimeType(mimeType){switch(mimeType){case"image/jpeg":return".jpg";case"image/png":return".png";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";case"video/mp4":return".mp4";case"video/webm":return".webm";default:return".bin"}}function resolveOutputPath(explicitOutputPath,fileName){if(explicitOutputPath)return resolve2(explicitOutputPath);let directory=mkdtempSync(join(tmpdir(),"platform-asset-"));return join(directory,fileName)}function tryOpenLocalFile(path){try{return process.platform==="darwin"?(spawn("open",[path],{stdio:"ignore",detached:!0}).unref(),!0):process.platform==="win32"?(spawn("cmd",["/c","start","",path],{stdio:"ignore",detached:!0}).unref(),!0):(spawn("xdg-open",[path],{stdio:"ignore",detached:!0}).unref(),!0)}catch{return!1}}function formatAssetError(error,action){return error instanceof PlatformApiError?new Error([`\u7D20\u6750 ${action} \u5931\u8D25\u3002`,`\u72B6\u6001\u7801: ${error.status}`,`\u9519\u8BEF\u7801: ${error.code??"-"}`,error.message].join(`
2226
- `)):error instanceof Error?error:new Error(`\u7D20\u6750 ${action} \u5931\u8D25\u3002`)}import{existsSync as existsSync9,mkdirSync as mkdirSync4,readdirSync as readdirSync3,readFileSync as readFileSync9,writeFileSync as writeFileSync5}from"node:fs";import{dirname as dirname6,join as join5,resolve as resolve6}from"node:path";import{spawn as spawn2}from"node:child_process";import YAML2 from"yaml";import{createServer}from"node:http";import{createHash as createHash3,randomBytes}from"node:crypto";import{chmodSync,existsSync as existsSync7,mkdirSync as mkdirSync2,readFileSync as readFileSync7,writeFileSync as writeFileSync3}from"node:fs";import{existsSync as existsSync6,mkdirSync,writeFileSync as writeFileSync2}from"node:fs";import{homedir}from"node:os";import{dirname as dirname4,join as join3,resolve as resolve4}from"node:path";import{fileURLToPath as fileURLToPath4}from"node:url";import{existsSync as existsSync4,readFileSync as readFileSync5}from"node:fs";import{dirname as dirname2,join as join2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";var AUTH_CLI_CLIENT_ID_KEYS=["AUTH_CLI_CLIENT_ID","LOGTO_CLI_APP_ID"],AUTH_CLI_REDIRECT_URI_KEYS=["AUTH_CLI_REDIRECT_URI","LOGTO_CLI_REDIRECT_URI"],AUTH_TENANT_CLIENT_ID_KEYS=["AUTH_TENANT_CLIENT_ID","LOGTO_TENANT_APP_ID","LOGTO_APP_ID"],AUTH_TENANT_REDIRECT_URI_KEYS=["AUTH_TENANT_REDIRECT_URI","LOGTO_TENANT_REDIRECT_URI"];function readTrimmedConfigValue(source,key){let value=source?.[key]?.trim();if(!(!value||/^<.+>$/.test(value)))return value}function readAuthConfigValue(keys,env=process.env){for(let key of keys){let fromEnv=readTrimmedConfigValue(env,key);if(fromEnv)return fromEnv}let defaults=getDistributionProfile().defaults??{};for(let key of keys){let fromDefaults=readTrimmedConfigValue(defaults,key);if(fromDefaults)return fromDefaults}}var defaultDeveloperProfile={name:"developer",defaults:{CONTROL_API_BASE_URL:"http://localhost:7001",PUBLIC_API_BASE_URL:"http://localhost:7007",RUNTIME_API_BASE_URL:"http://127.0.0.1.nip.io",OIDC_ISSUER:"http://localhost:3001/oidc",OIDC_AUDIENCE:"platform",LOGTO_CLI_REDIRECT_URI:"http://localhost:7300/callback",LOGTO_TENANT_REDIRECT_URI:"http://localhost:7102/callback"}},cachedProfile=null;function getDistributionProfile(){if(cachedProfile)return cachedProfile;let packageJsonPath=resolvePackageJsonPath();if(!packageJsonPath)return cachedProfile=defaultDeveloperProfile,cachedProfile;try{let packageJson=JSON.parse(readFileSync5(packageJsonPath,"utf8"));return cachedProfile=normalizeDistributionProfile(packageJson.platformDistributionProfile),cachedProfile}catch{return cachedProfile=defaultDeveloperProfile,cachedProfile}}function applyDistributionProfileDefaults(env=process.env){let profile=getDistributionProfile();for(let[key,value]of Object.entries(profile.defaults??{}))typeof value!="string"||value.trim().length===0||typeof env[key]=="string"&&env[key].trim().length>0||(env[key]=value);return profile}function getCliPackageVersion(){let packageJsonPath=resolvePackageJsonPath();if(!packageJsonPath)return"0.0.0";try{let packageJson=JSON.parse(readFileSync5(packageJsonPath,"utf8"));return typeof packageJson.version=="string"&&packageJson.version.trim().length>0?packageJson.version.trim():"0.0.0"}catch{return"0.0.0"}}function normalizeDistributionProfile(input){if(!input||input.name!=="developer"&&input.name!=="test-only"&&input.name!=="sandbox"&&input.name!=="nonprod"&&input.name!=="prod")return defaultDeveloperProfile;let defaults=input.name==="developer"?{...defaultDeveloperProfile.defaults}:{};for(let[key,value]of Object.entries(input.defaults??{}))typeof value=="string"&&value.trim().length>0&&(defaults[key]=value.trim());return{name:input.name,defaults}}function resolvePackageJsonPath(){let distDir=dirname2(fileURLToPath2(import.meta.url)),candidates=[join2(distDir,"..","package.json"),join2(distDir,"..","..","package.json")];for(let candidate of candidates)if(existsSync4(candidate))return candidate;return null}import{existsSync as existsSync5,readFileSync as readFileSync6,statSync as statSync2}from"node:fs";import{dirname as dirname3,resolve as resolve3}from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";function stripQuotes(value){return value.startsWith('"')&&value.endsWith('"')||value.startsWith("'")&&value.endsWith("'")?value.slice(1,-1):value}function hasWorkspaceMarker(directory){return existsSync5(resolve3(directory,"pnpm-workspace.yaml"))}function getInvocationCwd(){let candidates=[process.env.PLATFORM_INVOCATION_CWD,process.env.INIT_CWD,process.env.PWD,process.cwd()];for(let candidate of candidates){if(!candidate||candidate.trim().length===0)continue;let resolved=resolve3(candidate);if(existsSync5(resolved))try{if(statSync2(resolved).isDirectory())return resolved}catch{continue}}return resolve3(process.cwd())}function tryFindWorkspaceRoot(startDir=getInvocationCwd()){let current=resolve3(startDir);for(;;){if(hasWorkspaceMarker(current))return current;let parent=dirname3(current);if(parent===current)return null;current=parent}}function findWorkspaceRoot(startDir=getInvocationCwd()){return tryFindWorkspaceRoot(startDir)??resolve3(startDir)}function loadDotenvFiles(startDir=getInvocationCwd()){let workspaceRoot=findWorkspaceRoot(startDir),appRoot=resolve3(startDir),cliModuleRoot=resolve3(dirname3(fileURLToPath3(import.meta.url)),".."),cliWorkspaceRoot=findWorkspaceRoot(cliModuleRoot),developerLocalEnvFile=getDistributionProfile().name==="developer"?resolve3(process.env.PLATFORM_LOCAL_CLI_ENV_FILE?.trim()||resolve3(workspaceRoot,"TMP","local-cli.env")):null,candidates=[resolve3(workspaceRoot,".env"),resolve3(workspaceRoot,".env.local"),...developerLocalEnvFile?[developerLocalEnvFile]:[],resolve3(appRoot,".env"),resolve3(appRoot,".env.local"),resolve3(cliWorkspaceRoot,".env"),resolve3(cliWorkspaceRoot,".env.local"),resolve3(cliModuleRoot,".env"),resolve3(cliModuleRoot,".env.local")],visited=new Set;for(let filePath of candidates){if(visited.has(filePath)||(visited.add(filePath),!existsSync5(filePath)))continue;let lines=readFileSync6(filePath,"utf8").split(/\r?\n/u);for(let line of lines){let trimmed=line.trim();if(trimmed.length===0||trimmed.startsWith("#"))continue;let separatorIndex=trimmed.indexOf("=");if(separatorIndex<=0)continue;let key=trimmed.slice(0,separatorIndex).trim(),value=stripQuotes(trimmed.slice(separatorIndex+1).trim());process.env[key]||(process.env[key]=value)}}}var DEFAULT_STATE_DIR_NAME=".platform",LOCAL_DEVELOPER_STATE_DIR=join3("TMP","local-cli-state"),WORKSPACE_FALLBACK_STATE_DIR=join3("TMP","local-cli-state-fallback"),WORKSPACE_FALLBACK_MARKER=".state-fallback-active",activeFallbackStateDir=null,emittedFallbackWarnings=new Set,CliStateAccessError=class extends Error{operation;path;cause;constructor(operation,path,cause){super([`\u65E0\u6CD5${operation} CLI \u672C\u5730\u72B6\u6001\u6587\u4EF6\uFF1A${path}`,"\u8FD9\u901A\u5E38\u662F\u56E0\u4E3A\u5F53\u524D HOME / PLATFORM_STATE_DIR \u5BF9\u5E94\u76EE\u5F55\u4E0D\u53EF\u5199\uFF0C\u6216\u8FD0\u884C\u5728\u53D7\u9650\u6C99\u7BB1\u73AF\u5883\u4E2D\u3002","\u53EF\u5C1D\u8BD5\uFF1A","1. \u91CD\u65B0\u6267\u884C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u5BF9\u8BE5\u76EE\u5F55\u6709\u5199\u6743\u9650","2. \u663E\u5F0F\u8BBE\u7F6E `PLATFORM_STATE_DIR` \u6307\u5411\u4E00\u4E2A\u53EF\u5199\u76EE\u5F55","3. \u82E5\u5728\u9694\u79BB\u73AF\u5883\u4E2D\u8FD0\u884C\uFF0C\u53EF\u4E3A\u8BE5\u73AF\u5883\u5355\u72EC\u914D\u7F6E `HOME` \u6216 `PLATFORM_STATE_DIR`"].join(`
2227
- `)),this.operation=operation,this.path=path,this.cause=cause,this.name="CliStateAccessError"}};function resolveDeveloperStateDir(){let cliModuleRoot=resolve4(dirname4(fileURLToPath4(import.meta.url)),".."),workspaceRoot=findWorkspaceRoot(cliModuleRoot);return resolve4(workspaceRoot,LOCAL_DEVELOPER_STATE_DIR)}function resolveWorkspaceFallbackStateDir(startDir=getInvocationCwd()){let workspaceRoot=tryFindWorkspaceRoot(startDir);return workspaceRoot?resolve4(workspaceRoot,WORKSPACE_FALLBACK_STATE_DIR):null}function resolveCliStateLocation(options={}){let configured=options.configuredStateDir??process.env.PLATFORM_STATE_DIR?.trim()??"";if(configured)return{dir:resolve4(configured),source:"configured"};if(activeFallbackStateDir)return{dir:activeFallbackStateDir,source:"workspace-fallback"};if((options.distributionProfileName??getDistributionProfile().name)==="developer")return{dir:resolveDeveloperStateDir(),source:"developer"};let fallbackDir=resolveWorkspaceFallbackStateDir(options.startDir);return fallbackDir&&existsSync6(resolve4(fallbackDir,WORKSPACE_FALLBACK_MARKER))?{dir:fallbackDir,source:"workspace-fallback"}:{dir:join3(options.homeDir??homedir(),DEFAULT_STATE_DIR_NAME),source:"home"}}function isCliStateAccessFailure(error){return error instanceof Error&&"code"in error&&typeof error.code=="string"&&["EACCES","EPERM","EROFS"].includes(error.code??"")}function activateWorkspaceFallback(startDir=getInvocationCwd()){let fallbackDir=resolveWorkspaceFallbackStateDir(startDir);return fallbackDir?(mkdirSync(fallbackDir,{recursive:!0}),writeFileSync2(resolve4(fallbackDir,WORKSPACE_FALLBACK_MARKER),`active
2224
+ `)}function flattenShellContinuation(template){return template.replace(/\s*\\\s*\n\s*/g," ").replace(/\s{2,}/g," ").trim()}function buildVariantFileName(originalFileName,variants,variantKind){let variant=variants.find(item=>item.variant_kind===variantKind),extension=variant?inferExtensionFromMimeType(variant.mime_type):extname(originalFileName)||".bin";return`${basename(originalFileName,extname(originalFileName))}.${variantKind}${extension}`}function inferExtensionFromMimeType(mimeType){switch(mimeType){case"image/jpeg":return".jpg";case"image/png":return".png";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";case"video/mp4":return".mp4";case"video/webm":return".webm";default:return".bin"}}function resolveOutputPath(explicitOutputPath,fileName){if(explicitOutputPath)return resolve2(explicitOutputPath);let directory=mkdtempSync(join(tmpdir(),"platform-asset-"));return join(directory,fileName)}function formatAssetError(error,action){return error instanceof PlatformApiError?new Error([`\u7D20\u6750 ${action} \u5931\u8D25\u3002`,`\u72B6\u6001\u7801: ${error.status}`,`\u9519\u8BEF\u7801: ${error.code??"-"}`,error.message].join(`
2225
+ `)):error instanceof Error?error:new Error(`\u7D20\u6750 ${action} \u5931\u8D25\u3002`)}function formatAppCreateCheckoutError(input){let causeMessage=input.cause instanceof Error?input.cause.message:String(input.cause),retryCommand=["platform app checkout","--tenant",quoteCliArgument(input.tenantId),"--app",quoteCliArgument(input.appId),...input.targetDir?["--dir",quoteCliArgument(input.targetDir)]:[]].join(" ");return new Error(["\u4E91\u7AEF\u5E94\u7528\u5DF2\u7ECF\u521B\u5EFA\uFF0C\u4F46\u672C\u5730 checkout \u5931\u8D25\uFF1B\u4E91\u7AEF\u5E94\u7528\u672A\u56DE\u6EDA\u3002",`tenant_id: ${input.tenantId}`,`app_id: ${input.appId}`,`\u672C\u5730\u9519\u8BEF: ${causeMessage}`,"\u53EF\u4FEE\u590D\u672C\u5730\u76EE\u5F55\u95EE\u9898\u540E\u91CD\u8BD5\uFF1A",` ${retryCommand}`].join(`
2226
+ `))}function quoteCliArgument(value){return/^[A-Za-z0-9._:/-]+$/u.test(value)?value:JSON.stringify(value)}import{existsSync as existsSync9,mkdirSync as mkdirSync4,readdirSync as readdirSync3,readFileSync as readFileSync9,writeFileSync as writeFileSync5}from"node:fs";import{dirname as dirname6,join as join5,resolve as resolve6}from"node:path";import YAML2 from"yaml";import{createServer}from"node:http";import{createHash as createHash3,randomBytes}from"node:crypto";import{chmodSync,existsSync as existsSync7,mkdirSync as mkdirSync2,readFileSync as readFileSync7,writeFileSync as writeFileSync3}from"node:fs";import{existsSync as existsSync6,mkdirSync,writeFileSync as writeFileSync2}from"node:fs";import{homedir}from"node:os";import{dirname as dirname4,join as join3,resolve as resolve4}from"node:path";import{fileURLToPath as fileURLToPath4}from"node:url";import{existsSync as existsSync4,readFileSync as readFileSync5}from"node:fs";import{dirname as dirname2,join as join2}from"node:path";import{fileURLToPath as fileURLToPath2}from"node:url";var AUTH_CLI_CLIENT_ID_KEYS=["AUTH_CLI_CLIENT_ID","LOGTO_CLI_APP_ID"],AUTH_CLI_REDIRECT_URI_KEYS=["AUTH_CLI_REDIRECT_URI","LOGTO_CLI_REDIRECT_URI"],AUTH_TENANT_CLIENT_ID_KEYS=["AUTH_TENANT_CLIENT_ID","LOGTO_TENANT_APP_ID","LOGTO_APP_ID"],AUTH_TENANT_REDIRECT_URI_KEYS=["AUTH_TENANT_REDIRECT_URI","LOGTO_TENANT_REDIRECT_URI"];function readTrimmedConfigValue(source,key){let value=source?.[key]?.trim();if(!(!value||/^<.+>$/.test(value)))return value}function readAuthConfigValue(keys,env=process.env){for(let key of keys){let fromEnv=readTrimmedConfigValue(env,key);if(fromEnv)return fromEnv}let defaults=getDistributionProfile().defaults??{};for(let key of keys){let fromDefaults=readTrimmedConfigValue(defaults,key);if(fromDefaults)return fromDefaults}}var defaultDeveloperProfile={name:"developer",defaults:{CONTROL_API_BASE_URL:"http://localhost:7001",PUBLIC_API_BASE_URL:"http://localhost:7007",RUNTIME_API_BASE_URL:"http://127.0.0.1.nip.io",OIDC_ISSUER:"http://localhost:3001/oidc",OIDC_AUDIENCE:"platform",LOGTO_CLI_REDIRECT_URI:"http://localhost:7300/callback",LOGTO_TENANT_REDIRECT_URI:"http://localhost:7102/callback"}},cachedProfile=null;function getDistributionProfile(){if(cachedProfile)return cachedProfile;let packageJsonPath=resolvePackageJsonPath();if(!packageJsonPath)return cachedProfile=defaultDeveloperProfile,cachedProfile;try{let packageJson=JSON.parse(readFileSync5(packageJsonPath,"utf8"));return cachedProfile=normalizeDistributionProfile(packageJson.platformDistributionProfile),cachedProfile}catch{return cachedProfile=defaultDeveloperProfile,cachedProfile}}function applyDistributionProfileDefaults(env=process.env){let profile=getDistributionProfile();for(let[key,value]of Object.entries(profile.defaults??{}))typeof value!="string"||value.trim().length===0||typeof env[key]=="string"&&env[key].trim().length>0||(env[key]=value);return profile}function getCliPackageVersion(){let packageJsonPath=resolvePackageJsonPath();if(!packageJsonPath)return"0.0.0";try{let packageJson=JSON.parse(readFileSync5(packageJsonPath,"utf8"));return typeof packageJson.version=="string"&&packageJson.version.trim().length>0?packageJson.version.trim():"0.0.0"}catch{return"0.0.0"}}function normalizeDistributionProfile(input){if(!input||input.name!=="developer"&&input.name!=="test-only"&&input.name!=="sandbox"&&input.name!=="nonprod"&&input.name!=="prod")return defaultDeveloperProfile;let defaults=input.name==="developer"?{...defaultDeveloperProfile.defaults}:{};for(let[key,value]of Object.entries(input.defaults??{}))typeof value=="string"&&value.trim().length>0&&(defaults[key]=value.trim());return{name:input.name,defaults}}function resolvePackageJsonPath(){let distDir=dirname2(fileURLToPath2(import.meta.url)),candidates=[join2(distDir,"..","package.json"),join2(distDir,"..","..","package.json")];for(let candidate of candidates)if(existsSync4(candidate))return candidate;return null}import{existsSync as existsSync5,readFileSync as readFileSync6,statSync as statSync2}from"node:fs";import{dirname as dirname3,resolve as resolve3}from"node:path";import{fileURLToPath as fileURLToPath3}from"node:url";function stripQuotes(value){return value.startsWith('"')&&value.endsWith('"')||value.startsWith("'")&&value.endsWith("'")?value.slice(1,-1):value}function hasWorkspaceMarker(directory){return existsSync5(resolve3(directory,"pnpm-workspace.yaml"))}function getInvocationCwd(){let candidates=[process.env.PLATFORM_INVOCATION_CWD,process.env.INIT_CWD,process.env.PWD,process.cwd()];for(let candidate of candidates){if(!candidate||candidate.trim().length===0)continue;let resolved=resolve3(candidate);if(existsSync5(resolved))try{if(statSync2(resolved).isDirectory())return resolved}catch{continue}}return resolve3(process.cwd())}function tryFindWorkspaceRoot(startDir=getInvocationCwd()){let current=resolve3(startDir);for(;;){if(hasWorkspaceMarker(current))return current;let parent=dirname3(current);if(parent===current)return null;current=parent}}function findWorkspaceRoot(startDir=getInvocationCwd()){return tryFindWorkspaceRoot(startDir)??resolve3(startDir)}function loadDotenvFiles(startDir=getInvocationCwd()){let workspaceRoot=findWorkspaceRoot(startDir),appRoot=resolve3(startDir),cliModuleRoot=resolve3(dirname3(fileURLToPath3(import.meta.url)),".."),cliWorkspaceRoot=findWorkspaceRoot(cliModuleRoot),developerLocalEnvFile=getDistributionProfile().name==="developer"?resolve3(process.env.PLATFORM_LOCAL_CLI_ENV_FILE?.trim()||resolve3(workspaceRoot,"TMP","local-cli.env")):null,candidates=[resolve3(workspaceRoot,".env"),resolve3(workspaceRoot,".env.local"),...developerLocalEnvFile?[developerLocalEnvFile]:[],resolve3(appRoot,".env"),resolve3(appRoot,".env.local"),resolve3(cliWorkspaceRoot,".env"),resolve3(cliWorkspaceRoot,".env.local"),resolve3(cliModuleRoot,".env"),resolve3(cliModuleRoot,".env.local")],visited=new Set;for(let filePath of candidates){if(visited.has(filePath)||(visited.add(filePath),!existsSync5(filePath)))continue;let lines=readFileSync6(filePath,"utf8").split(/\r?\n/u);for(let line of lines){let trimmed=line.trim();if(trimmed.length===0||trimmed.startsWith("#"))continue;let separatorIndex=trimmed.indexOf("=");if(separatorIndex<=0)continue;let key=trimmed.slice(0,separatorIndex).trim(),value=stripQuotes(trimmed.slice(separatorIndex+1).trim());process.env[key]||(process.env[key]=value)}}}var DEFAULT_STATE_DIR_NAME=".platform",LOCAL_DEVELOPER_STATE_DIR=join3("TMP","local-cli-state"),WORKSPACE_FALLBACK_STATE_DIR=join3("TMP","local-cli-state-fallback"),WORKSPACE_FALLBACK_MARKER=".state-fallback-active",activeFallbackStateDir=null,emittedFallbackWarnings=new Set,CliStateAccessError=class extends Error{operation;path;cause;constructor(operation,path2,cause){super([`\u65E0\u6CD5${operation} CLI \u672C\u5730\u72B6\u6001\u6587\u4EF6\uFF1A${path2}`,"\u8FD9\u901A\u5E38\u662F\u56E0\u4E3A\u5F53\u524D HOME / PLATFORM_STATE_DIR \u5BF9\u5E94\u76EE\u5F55\u4E0D\u53EF\u5199\uFF0C\u6216\u8FD0\u884C\u5728\u53D7\u9650\u6C99\u7BB1\u73AF\u5883\u4E2D\u3002","\u53EF\u5C1D\u8BD5\uFF1A","1. \u91CD\u65B0\u6267\u884C\u5E76\u786E\u8BA4\u5F53\u524D\u8D26\u53F7\u5BF9\u8BE5\u76EE\u5F55\u6709\u5199\u6743\u9650","2. \u663E\u5F0F\u8BBE\u7F6E `PLATFORM_STATE_DIR` \u6307\u5411\u4E00\u4E2A\u53EF\u5199\u76EE\u5F55","3. \u82E5\u5728\u9694\u79BB\u73AF\u5883\u4E2D\u8FD0\u884C\uFF0C\u53EF\u4E3A\u8BE5\u73AF\u5883\u5355\u72EC\u914D\u7F6E `HOME` \u6216 `PLATFORM_STATE_DIR`"].join(`
2227
+ `)),this.operation=operation,this.path=path2,this.cause=cause,this.name="CliStateAccessError"}};function resolveDeveloperStateDir(){let cliModuleRoot=resolve4(dirname4(fileURLToPath4(import.meta.url)),".."),workspaceRoot=findWorkspaceRoot(cliModuleRoot);return resolve4(workspaceRoot,LOCAL_DEVELOPER_STATE_DIR)}function resolveWorkspaceFallbackStateDir(startDir=getInvocationCwd()){let workspaceRoot=tryFindWorkspaceRoot(startDir);return workspaceRoot?resolve4(workspaceRoot,WORKSPACE_FALLBACK_STATE_DIR):null}function resolveCliStateLocation(options={}){let configured=options.configuredStateDir??process.env.PLATFORM_STATE_DIR?.trim()??"";if(configured)return{dir:resolve4(configured),source:"configured"};if(activeFallbackStateDir)return{dir:activeFallbackStateDir,source:"workspace-fallback"};if((options.distributionProfileName??getDistributionProfile().name)==="developer")return{dir:resolveDeveloperStateDir(),source:"developer"};let fallbackDir=resolveWorkspaceFallbackStateDir(options.startDir);return fallbackDir&&existsSync6(resolve4(fallbackDir,WORKSPACE_FALLBACK_MARKER))?{dir:fallbackDir,source:"workspace-fallback"}:{dir:join3(options.homeDir??homedir(),DEFAULT_STATE_DIR_NAME),source:"home"}}function isCliStateAccessFailure(error){return error instanceof Error&&"code"in error&&typeof error.code=="string"&&["EACCES","EPERM","EROFS"].includes(error.code??"")}function activateWorkspaceFallback(startDir=getInvocationCwd()){let fallbackDir=resolveWorkspaceFallbackStateDir(startDir);return fallbackDir?(mkdirSync(fallbackDir,{recursive:!0}),writeFileSync2(resolve4(fallbackDir,WORKSPACE_FALLBACK_MARKER),`active
2228
2228
  `,"utf8"),activeFallbackStateDir=fallbackDir,fallbackDir):null}function emitFallbackWarning(originalPath,fallbackDir){emittedFallbackWarnings.has(fallbackDir)||(emittedFallbackWarnings.add(fallbackDir),console.warn([`\u68C0\u6D4B\u5230 CLI state \u9ED8\u8BA4\u76EE\u5F55\u4E0D\u53EF\u5199\uFF1A${originalPath}`,`\u5DF2\u81EA\u52A8\u5207\u6362\u5230\u4ED3\u5E93\u5185\u672C\u5730\u72B6\u6001\u76EE\u5F55\uFF1A${fallbackDir}`,"\u5982\u9700\u56FA\u5B9A\u8BE5\u884C\u4E3A\uFF0C\u53EF\u663E\u5F0F\u8BBE\u7F6E `PLATFORM_STATE_DIR`\u3002"].join(`
2229
- `)))}function withCliStateFileWriteFallback(args){let primary=resolveCliStateLocation(args.resolution),primaryPath=join3(primary.dir,args.fileName);try{return args.write({filePath:primaryPath,stateDir:primary.dir})}catch(error){if(!isCliStateAccessFailure(error))throw error;let configuredStateDir=args.resolution?.configuredStateDir??process.env.PLATFORM_STATE_DIR?.trim();if(primary.source!=="home"||configuredStateDir?.trim())throw new CliStateAccessError(args.operation,primaryPath,error);try{let fallbackDir=activateWorkspaceFallback(args.resolution?.startDir);if(!fallbackDir)throw new CliStateAccessError(args.operation,primaryPath,error);emitFallbackWarning(primaryPath,fallbackDir);let fallbackPath=join3(fallbackDir,args.fileName);try{return args.write({filePath:fallbackPath,stateDir:fallbackDir})}catch(fallbackError){throw isCliStateAccessFailure(fallbackError)?new CliStateAccessError(args.operation,fallbackPath,fallbackError):fallbackError}}catch(fallbackError){throw fallbackError instanceof CliStateAccessError?fallbackError:isCliStateAccessFailure(fallbackError)?new CliStateAccessError(args.operation,primaryPath,fallbackError):fallbackError}}}function resolveCliStateDir(options={}){return resolveCliStateLocation(options).dir}function resolveCliStateFilePath(fileName){return join3(resolveCliStateDir(),fileName)}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,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(resolve16=>{setTimeout(resolve16,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>
2229
+ `)))}function withCliStateFileWriteFallback(args){let primary=resolveCliStateLocation(args.resolution),primaryPath=join3(primary.dir,args.fileName);try{return args.write({filePath:primaryPath,stateDir:primary.dir})}catch(error){if(!isCliStateAccessFailure(error))throw error;let configuredStateDir=args.resolution?.configuredStateDir??process.env.PLATFORM_STATE_DIR?.trim();if(primary.source!=="home"||configuredStateDir?.trim())throw new CliStateAccessError(args.operation,primaryPath,error);try{let fallbackDir=activateWorkspaceFallback(args.resolution?.startDir);if(!fallbackDir)throw new CliStateAccessError(args.operation,primaryPath,error);emitFallbackWarning(primaryPath,fallbackDir);let fallbackPath=join3(fallbackDir,args.fileName);try{return args.write({filePath:fallbackPath,stateDir:fallbackDir})}catch(fallbackError){throw isCliStateAccessFailure(fallbackError)?new CliStateAccessError(args.operation,fallbackPath,fallbackError):fallbackError}}catch(fallbackError){throw fallbackError instanceof CliStateAccessError?fallbackError:isCliStateAccessFailure(fallbackError)?new CliStateAccessError(args.operation,primaryPath,fallbackError):fallbackError}}}function resolveCliStateDir(options={}){return resolveCliStateLocation(options).dir}function resolveCliStateFilePath(fileName){return join3(resolveCliStateDir(),fileName)}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,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(resolve17=>{setTimeout(resolve17,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>
2230
2230
  <html lang="zh-CN">
2231
2231
  <head>
2232
2232
  <meta charset="utf-8" />
@@ -2362,9 +2362,10 @@ function inferUpstreamPath(pathname: string, routeBasePath: string): string {
2362
2362
  </body>
2363
2363
  </html>`}function escapeHtml(s){return s.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;")}async function discoverOidcEndpoints(issuer){let discoveryUrl=`${issuer.endsWith("/")?issuer.slice(0,-1):issuer}/.well-known/openid-configuration`,response=await fetch(discoveryUrl);if(!response.ok)throw new Error(`\u83B7\u53D6 OIDC discovery \u5931\u8D25: ${response.status}`);let document=await response.json();if(!document.authorization_endpoint||!document.token_endpoint)throw new Error("OIDC discovery \u7F3A\u5C11\u6388\u6743\u6216 token \u7AEF\u70B9");return{authorization_endpoint:document.authorization_endpoint,device_authorization_endpoint:document.device_authorization_endpoint,token_endpoint:document.token_endpoint}}function getCredentialPath(){return resolveCliStateFilePath("credentials.json")}function getCliContextPath(){return resolveCliStateFilePath("context.json")}function loadStoredCredentials(){let credentialsPath=getCredentialPath();return existsSync7(credentialsPath)?JSON.parse(readFileSync7(credentialsPath,"utf8")):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 existsSync7(cliContextPath)?JSON.parse(readFileSync7(cliContextPath,"utf8")):null}function persistCredentials(credentials){withCliStateFileWriteFallback({fileName:"credentials.json",operation:"\u5199\u5165",write:({filePath,stateDir})=>{mkdirSync2(stateDir,{recursive:!0}),writeFileSync3(filePath,`${JSON.stringify(credentials,null,2)}
2364
2364
  `,"utf8"),chmodSync(filePath,384)}})}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){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 persistCredentials(nextCredentials),nextCredentials}async function exchangePatCredentials(credentials){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 persistCredentials(nextCredentials),nextCredentials}async function loadStoredCredentialsEnsuringFresh(options={}){let credentials=loadStoredCredentials();if(!credentials)return null;let expired=isCredentialExpired(credentials);if(!options.forceRefresh&&!expired)return credentials;if(credentials.refresh_token)try{return refreshCredentials(credentials)}catch(error){maybeWrapCredentialRefreshError(error)}if(canUsePatExchange(credentials))try{return exchangePatCredentials(credentials)}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})=>{mkdirSync2(stateDir,{recursive:!0}),writeFileSync3(filePath,`${JSON.stringify({...context,updated_at:new Date().toISOString()},null,2)}
2365
- `,"utf8"),chmodSync(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");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=randomBytes(16).toString("base64url"),nonce=randomBytes(16).toString("base64url"),codeVerifier=randomBytes(32).toString("base64url"),codeChallenge=createHash3("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((resolve16,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(()=>{}),resolve16({code:code2})});server.on("error",error=>{clearTimeout(timeout),reject(error)}),server.listen(Number(redirectUrl.port||80),redirectUrl.hostname,()=>{config2.onPrompt?.({authorizationUrl:authorizationUrl.toString(),redirectUri:config2.redirectUri})})}),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 existsSync8,mkdirSync as mkdirSync3,readdirSync as readdirSync2,readFileSync as readFileSync8,statSync as statSync3,writeFileSync as writeFileSync4}from"node:fs";import{createServer as createNetServer}from"node:net";import{dirname as dirname5,join as join4,relative,resolve as resolve5}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=join4(PLATFORM_DIRECTORY,"config.json"),SOURCE_CONTEXT_FILE=join4(PLATFORM_DIRECTORY,"source-context.json"),PLATFORM_BLOCKS_LOCKFILE=join4(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){mkdirSync3(directory,{recursive:!0})}function writeFileIfMissing(path,content){if(existsSync8(path))throw new Error(`\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${path}`);ensureDirectory(dirname5(path)),writeFileSync4(path,content,"utf8")}function listFilesRecursively(root,current=root){if(!existsSync8(current)||!statSync3(current).isDirectory())return[];let files=[];for(let entry of readdirSync2(current,{withFileTypes:!0})){let absolutePath=join4(current,entry.name);if(entry.isDirectory()){files.push(...listFilesRecursively(root,absolutePath));continue}entry.isFile()&&files.push(relative(root,absolutePath))}return files.sort((left,right)=>left.localeCompare(right))}function seedRuntimeSdkVendor(targetDir){let workspaceRoot=findWorkspaceRoot(),runtimeSdkDistDir=join4(workspaceRoot,"packages","runtime-sdk","dist");if(!existsSync8(runtimeSdkDistDir)||!statSync3(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=join4(runtimeSdkDistDir,relativePath),outputPath=join4(targetDir,"vendor","runtime-sdk",relativePath);writeFileIfMissing(outputPath,readFileSync8(sourcePath,"utf8")),created.push(relative(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=resolve5(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=join4(absoluteTargetDir,file.path);writeFileIfMissing(outputPath,file.content),createdFiles.push(relative(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=join4(appRoot,"src","app.js");if(!existsSync8(appJsPath))throw new Error(`\u672A\u627E\u5230\u5E94\u7528\u5165\u53E3\u6587\u4EF6: ${appJsPath}`);let spec=getAppDebugScaffoldSpec(scaffold),createdFiles=[],updatedFiles=[],targetFilePath=join4(appRoot,spec.filePath);existsSync8(targetFilePath)||(ensureDirectory(dirname5(targetFilePath)),writeFileSync4(targetFilePath,spec.source,"utf8"),createdFiles.push(relative(appRoot,targetFilePath).replace(/\\/g,"/")));let appSource=readFileSync8(appJsPath,"utf8"),nextSource=injectDebugRouteIntoAppSource(appSource,spec);return nextSource!==appSource&&(writeFileSync4(appJsPath,nextSource,"utf8"),updatedFiles.push(relative(appRoot,appJsPath).replace(/\\/g,"/"))),{appRoot,createdFiles,updatedFiles,routePath:spec.routePath}}function readAppManifest(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),manifestPath=join4(appRoot,APP_MANIFEST_FILE),raw=readFileSync8(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=join4(appRoot,LEGACY_BINDING_FILE);if(!existsSync8(bindingPath))return null;let raw=JSON.parse(readFileSync8(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=join4(appRoot,SOURCE_CONTEXT_FILE);if(!existsSync8(sourceContextPath))return null;let raw=JSON.parse(readFileSync8(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),path=join4(appRoot,SOURCE_CONTEXT_FILE);return ensureDirectory(dirname5(path)),writeFileSync4(path,`${JSON.stringify({schema_version:1,...sourceContext,updated_at:new Date().toISOString()},null,2)}
2366
- `,"utf8"),{appRoot,path}}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,binding){let absoluteTargetDir=resolve5(getInvocationCwd(),targetDir);if(existsSync8(absoluteTargetDir)){if(readdirSync2(absoluteTargetDir).length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u975E\u7A7A\uFF0C\u62D2\u7EDD\u8986\u76D6: ${absoluteTargetDir}`)}else ensureDirectory(absoluteTargetDir);let writtenFiles=[];for(let file of files){let normalizedPath=file.path.replace(/^\/+/g,"");if(normalizedPath.length===0||normalizedPath.startsWith("..")||normalizedPath.includes("../")||normalizedPath.includes("..\\"))throw new Error(`\u4E91\u7AEF\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5: ${file.path}`);let outputPath=join4(absoluteTargetDir,normalizedPath);writeFileIfMissing(outputPath,file.content),writtenFiles.push(relative(getInvocationCwd(),outputPath))}return writeBinding(absoluteTargetDir,binding),writtenFiles}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(`
2367
- `));return stats}function detectPathBaseRuntimeViolations(files){let violations=[],textFilePattern=/\.(?:[cm]?[jt]sx?|html?|css)$/i,patterns=[{kind:"root_relative_fetch",regex:/\bfetch\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_http_client",regex:/\baxios(?:\.(?:get|post|put|patch|delete|head|options))?\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_href",regex:/\bhref\s*=\s*['"]\/(?!\/)/g},{kind:"root_relative_src",regex:/\bsrc\s*=\s*['"]\/(?!\/)/g}];for(let file of files){if(!textFilePattern.test(file.path)||/^README\.md$/i.test(file.path)||isPlatformDevSupportFile(file.path))continue;let lines=file.content.split(/\r?\n/);for(let index=0;index<lines.length;index+=1){let line=lines[index];for(let pattern of patterns)pattern.regex.lastIndex=0,pattern.regex.test(line)&&violations.push({path:file.path,line:index+1,kind:pattern.kind,snippet:line.trim().slice(0,180)})}}return violations}function isPlatformDevSupportFile(path){return path.startsWith("src/platform/dev/")||path.startsWith("src/web/platform/dev/")||path.startsWith("src/server/platform/dev/")}function scanSourceWorkspaceUploadPolicy(appRoot,currentDir){let entries=readdirSync2(currentDir,{withFileTypes:!0}),sourceBytes=0,assetHits=[];for(let entry of entries){let absolutePath=join4(currentDir,entry.name),relativePath=relative(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,entry.isDirectory())){if(entry.isDirectory()){let nested=scanSourceWorkspaceUploadPolicy(appRoot,absolutePath);sourceBytes+=nested.sourceBytes,assetHits.push(...nested.assetHits);continue}entry.isFile()&&(sourceBytes+=statSync3(absolutePath).size,isSourceWorkspaceAssetPath(relativePath)&&assetHits.push(relativePath))}}return{sourceBytes,assetHits}}function shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(!normalized)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")?!0:new Set([".git",".platform","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)}function isSourceWorkspaceAssetPath(relativePath){let lower=relativePath.toLowerCase(),dotIndex=lower.lastIndexOf(".");return dotIndex<0?!1:SOURCE_WORKSPACE_ASSET_EXTENSIONS.has(lower.slice(dotIndex))}function walkSourceWorkspace(appRoot,currentDir){let entries=readdirSync2(currentDir,{withFileTypes:!0}),files=[];for(let entry of entries){let absolutePath=join4(currentDir,entry.name),relativePath=relative(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspacePath(relativePath,entry.isDirectory())){if(entry.isDirectory()){files.push(...walkSourceWorkspace(appRoot,absolutePath));continue}entry.isFile()&&files.push({path:relativePath,content:readFileSync8(absolutePath,"utf8")})}}return files.sort((left,right)=>left.path.localeCompare(right.path))}function shouldIgnoreSourceWorkspacePath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(normalized.length===0)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")&&topLevel!==".platform"||new Set([".git","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)?!0:topLevel===".platform"?isDirectory?normalized===".platform/platform-blocks.history":normalized!==PLATFORM_BLOCKS_LOCKFILE:!!(!isDirectory&&new Set([".DS_Store",".env",".env.local",".env.dev",".env.ci"]).has(normalized))}function findAppRoot(startDir=getInvocationCwd()){let current=resolve5(getInvocationCwd(),startDir);for(;;){let manifestPath=join4(current,APP_MANIFEST_FILE);if(existsSync8(manifestPath)&&statSync3(manifestPath).isFile())return current;let parent=dirname5(current);if(parent===current)throw new Error("\u672A\u627E\u5230 app.yaml\u3002\u4F18\u5148\u5EFA\u8BAE\u5148\u6267\u884C `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u5F97\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u82E5\u4F60\u660E\u786E\u8981\u5728\u5F53\u524D\u7A7A\u76EE\u5F55\u521D\u59CB\u5316\uFF0C\u518D\u6267\u884C `platform init <project-name>`\u3002");current=parent}}function getAppDebugScaffoldSpec(scaffold){return scaffold==="auth-debug"?{kind:scaffold,routePath:"/debug/auth",filePath:"src/lib/debug-auth-page.js",importLine:'import { renderAuthDebugPage } from "./lib/debug-auth-page.js";',renderCall:"renderAuthDebugPage()",source:buildAuthDebugPageSource()}:scaffold==="cms-debug"?{kind:scaffold,routePath:"/debug/cms",filePath:"src/lib/debug-cms-page.js",importLine:'import { renderCmsDebugPage } from "./lib/debug-cms-page.js";',renderCall:"renderCmsDebugPage()",source:buildCmsDebugPageSource()}:scaffold==="db-debug"?{kind:scaffold,routePath:"/debug/db",filePath:"src/lib/debug-db-page.js",importLine:'import { renderDbDebugPage } from "./lib/debug-db-page.js";',renderCall:"renderDbDebugPage()",source:buildDbDebugPageSource(),extraRouteBlocks:[[' if (pathname === "/api/debug/db-context" && req.method === "GET") {'," sendJson(res, 200, {"," app_id: config.appId,"," tenant_id: config.tenantId || null,"," env: config.appEnv,"," request_id: requestId,"," database_ready: Boolean(config.databaseUrl),"," database_schema: config.databaseSchema || null,"," database_capability_version: process.env.DATABASE_CAPABILITY_VERSION || null,"," database_runtime_role: process.env.DATABASE_RUNTIME_ROLE || null,"," database_migrator_role: process.env.DATABASE_MIGRATOR_ROLE || null"," });"," return;"," }",""].join(`
2365
+ `,"utf8"),chmodSync(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=randomBytes(16).toString("base64url"),nonce=randomBytes(16).toString("base64url"),codeVerifier=randomBytes(32).toString("base64url"),codeChallenge=createHash3("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((resolve17,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(()=>{}),resolve17({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 existsSync8,mkdirSync as mkdirSync3,mkdtempSync as mkdtempSync2,readdirSync as readdirSync2,readFileSync as readFileSync8,renameSync,rmSync,statSync as statSync3,writeFileSync as writeFileSync4}from"node:fs";import{createServer as createNetServer}from"node:net";import{basename as basename2,dirname as dirname5,join as join4,relative,resolve as resolve5}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=join4(PLATFORM_DIRECTORY,"config.json"),SOURCE_CONTEXT_FILE=join4(PLATFORM_DIRECTORY,"source-context.json"),PLATFORM_BLOCKS_LOCKFILE=join4(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){mkdirSync3(directory,{recursive:!0})}function writeFileIfMissing(path2,content){if(existsSync8(path2))throw new Error(`\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${path2}`);ensureDirectory(dirname5(path2)),writeFileSync4(path2,content,"utf8")}function listFilesRecursively(root,current=root){if(!existsSync8(current)||!statSync3(current).isDirectory())return[];let files=[];for(let entry of readdirSync2(current,{withFileTypes:!0})){let absolutePath=join4(current,entry.name);if(entry.isDirectory()){files.push(...listFilesRecursively(root,absolutePath));continue}entry.isFile()&&files.push(relative(root,absolutePath))}return files.sort((left,right)=>left.localeCompare(right))}function seedRuntimeSdkVendor(targetDir){let workspaceRoot=findWorkspaceRoot(),runtimeSdkDistDir=join4(workspaceRoot,"packages","runtime-sdk","dist");if(!existsSync8(runtimeSdkDistDir)||!statSync3(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=join4(runtimeSdkDistDir,relativePath),outputPath=join4(targetDir,"vendor","runtime-sdk",relativePath);writeFileIfMissing(outputPath,readFileSync8(sourcePath,"utf8")),created.push(relative(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=resolve5(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=join4(absoluteTargetDir,file.path);writeFileIfMissing(outputPath,file.content),createdFiles.push(relative(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=join4(appRoot,"src","app.js");if(!existsSync8(appJsPath))throw new Error(`\u672A\u627E\u5230\u5E94\u7528\u5165\u53E3\u6587\u4EF6: ${appJsPath}`);let spec=getAppDebugScaffoldSpec(scaffold),createdFiles=[],updatedFiles=[],targetFilePath=join4(appRoot,spec.filePath);existsSync8(targetFilePath)||(ensureDirectory(dirname5(targetFilePath)),writeFileSync4(targetFilePath,spec.source,"utf8"),createdFiles.push(relative(appRoot,targetFilePath).replace(/\\/g,"/")));let appSource=readFileSync8(appJsPath,"utf8"),nextSource=injectDebugRouteIntoAppSource(appSource,spec);return nextSource!==appSource&&(writeFileSync4(appJsPath,nextSource,"utf8"),updatedFiles.push(relative(appRoot,appJsPath).replace(/\\/g,"/"))),{appRoot,createdFiles,updatedFiles,routePath:spec.routePath}}function readAppManifest(startDir=getInvocationCwd()){let appRoot=findAppRoot(startDir),manifestPath=join4(appRoot,APP_MANIFEST_FILE),raw=readFileSync8(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=join4(appRoot,LEGACY_BINDING_FILE);if(!existsSync8(bindingPath))return null;let raw=JSON.parse(readFileSync8(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=join4(appRoot,SOURCE_CONTEXT_FILE);if(!existsSync8(sourceContextPath))return null;let raw=JSON.parse(readFileSync8(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),path2=join4(appRoot,SOURCE_CONTEXT_FILE);return ensureDirectory(dirname5(path2)),writeFileSync4(path2,`${JSON.stringify({schema_version:1,...sourceContext,updated_at:new Date().toISOString()},null,2)}
2366
+ `,"utf8"),{appRoot,path:path2}}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=resolve5(getInvocationCwd(),targetDir);if(validatePortableWorkspacePaths(files),existsSync8(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=dirname5(absoluteTargetDir);ensureDirectory(parentDir);let stagingDir=mkdtempSync2(join4(parentDir,`.${basename2(absoluteTargetDir)}.platform-checkout-`));try{for(let file of files){let normalizedPath=normalizePortableWorkspacePath(file.path);writeFileIfMissing(join4(stagingDir,normalizedPath),file.content)}let now=new Date().toISOString();if(writeFileIfMissing(join4(stagingDir,SOURCE_CONTEXT_FILE),`${JSON.stringify({schema_version:1,...sourceContext,linked_at:sourceContext.linked_at??now,updated_at:now},null,2)}
2367
+ `),existsSync8(absoluteTargetDir))throw new Error(`\u76EE\u6807\u76EE\u5F55\u5728\u68C0\u51FA\u8FC7\u7A0B\u4E2D\u88AB\u521B\u5EFA\uFF0C\u62D2\u7EDD\u8986\u76D6: ${absoluteTargetDir}`);renameSync(stagingDir,absoluteTargetDir)}catch(error){throw rmSync(stagingDir,{recursive:!0,force:!0}),error}return files.map(file=>relative(getInvocationCwd(),join4(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(`
2368
+ `));return stats}function detectPathBaseRuntimeViolations(files){let violations=[],textFilePattern=/\.(?:[cm]?[jt]sx?|html?|css)$/i,patterns=[{kind:"root_relative_fetch",regex:/\bfetch\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_http_client",regex:/\baxios(?:\.(?:get|post|put|patch|delete|head|options))?\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_href",regex:/\bhref\s*=\s*['"]\/(?!\/)/g},{kind:"root_relative_src",regex:/\bsrc\s*=\s*['"]\/(?!\/)/g}];for(let file of files){if(!textFilePattern.test(file.path)||/^README\.md$/i.test(file.path)||isPlatformDevSupportFile(file.path))continue;let lines=file.content.split(/\r?\n/);for(let index=0;index<lines.length;index+=1){let line=lines[index];for(let pattern of patterns)pattern.regex.lastIndex=0,pattern.regex.test(line)&&violations.push({path:file.path,line:index+1,kind:pattern.kind,snippet:line.trim().slice(0,180)})}}return violations}function isPlatformDevSupportFile(path2){return path2.startsWith("src/platform/dev/")||path2.startsWith("src/web/platform/dev/")||path2.startsWith("src/server/platform/dev/")}function scanSourceWorkspaceUploadPolicy(appRoot,currentDir){let entries=readdirSync2(currentDir,{withFileTypes:!0}),sourceBytes=0,assetHits=[];for(let entry of entries){let absolutePath=join4(currentDir,entry.name),relativePath=relative(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,entry.isDirectory())){if(entry.isDirectory()){let nested=scanSourceWorkspaceUploadPolicy(appRoot,absolutePath);sourceBytes+=nested.sourceBytes,assetHits.push(...nested.assetHits);continue}entry.isFile()&&(sourceBytes+=statSync3(absolutePath).size,isSourceWorkspaceAssetPath(relativePath)&&assetHits.push(relativePath))}}return{sourceBytes,assetHits}}function shouldIgnoreSourceWorkspaceUploadPolicyPath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(!normalized)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")?!0:new Set([".git",".platform","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)}function isSourceWorkspaceAssetPath(relativePath){let lower=relativePath.toLowerCase(),dotIndex=lower.lastIndexOf(".");return dotIndex<0?!1:SOURCE_WORKSPACE_ASSET_EXTENSIONS.has(lower.slice(dotIndex))}function walkSourceWorkspace(appRoot,currentDir){let entries=readdirSync2(currentDir,{withFileTypes:!0}),files=[];for(let entry of entries){let absolutePath=join4(currentDir,entry.name),relativePath=relative(appRoot,absolutePath).replace(/\\/g,"/");if(!shouldIgnoreSourceWorkspacePath(relativePath,entry.isDirectory())){if(entry.isDirectory()){files.push(...walkSourceWorkspace(appRoot,absolutePath));continue}entry.isFile()&&files.push({path:relativePath,content:readFileSync8(absolutePath,"utf8")})}}return files.sort((left,right)=>left.path.localeCompare(right.path))}function shouldIgnoreSourceWorkspacePath(relativePath,isDirectory){let normalized=relativePath.replace(/^\.\/+/g,"");if(normalized.length===0)return!1;let topLevel=normalized.split("/")[0];return isDirectory&&topLevel.startsWith(".")&&topLevel!==".platform"||new Set([".git","node_modules","dist","coverage","evidence","Log","TMP"]).has(topLevel)?!0:topLevel===".platform"?isDirectory?normalized===".platform/platform-blocks.history":normalized!==PLATFORM_BLOCKS_LOCKFILE:!!(!isDirectory&&new Set([".DS_Store",".env",".env.local",".env.dev",".env.ci"]).has(normalized))}function findAppRoot(startDir=getInvocationCwd()){let current=resolve5(getInvocationCwd(),startDir);for(;;){let manifestPath=join4(current,APP_MANIFEST_FILE);if(existsSync8(manifestPath)&&statSync3(manifestPath).isFile())return current;let parent=dirname5(current);if(parent===current)throw new Error("\u672A\u627E\u5230 app.yaml\u3002\u4F18\u5148\u5EFA\u8BAE\u5148\u6267\u884C `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u5F97\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u82E5\u4F60\u660E\u786E\u8981\u5728\u5F53\u524D\u7A7A\u76EE\u5F55\u521D\u59CB\u5316\uFF0C\u518D\u6267\u884C `platform init <project-name>`\u3002");current=parent}}function getAppDebugScaffoldSpec(scaffold){return scaffold==="auth-debug"?{kind:scaffold,routePath:"/debug/auth",filePath:"src/lib/debug-auth-page.js",importLine:'import { renderAuthDebugPage } from "./lib/debug-auth-page.js";',renderCall:"renderAuthDebugPage()",source:buildAuthDebugPageSource()}:scaffold==="cms-debug"?{kind:scaffold,routePath:"/debug/cms",filePath:"src/lib/debug-cms-page.js",importLine:'import { renderCmsDebugPage } from "./lib/debug-cms-page.js";',renderCall:"renderCmsDebugPage()",source:buildCmsDebugPageSource()}:scaffold==="db-debug"?{kind:scaffold,routePath:"/debug/db",filePath:"src/lib/debug-db-page.js",importLine:'import { renderDbDebugPage } from "./lib/debug-db-page.js";',renderCall:"renderDbDebugPage()",source:buildDbDebugPageSource(),extraRouteBlocks:[[' if (pathname === "/api/debug/db-context" && req.method === "GET") {'," sendJson(res, 200, {"," app_id: config.appId,"," tenant_id: config.tenantId || null,"," env: config.appEnv,"," request_id: requestId,"," database_ready: Boolean(config.databaseUrl),"," database_schema: config.databaseSchema || null,"," database_capability_version: process.env.DATABASE_CAPABILITY_VERSION || null,"," database_runtime_role: process.env.DATABASE_RUNTIME_ROLE || null,"," database_migrator_role: process.env.DATABASE_MIGRATOR_ROLE || null"," });"," return;"," }",""].join(`
2368
2369
  `)]}:{kind:scaffold,routePath:"/debug/workflow",filePath:"src/lib/debug-workflow-page.js",importLine:'import { renderWorkflowDebugPage } from "./lib/debug-workflow-page.js";',renderCall:"renderWorkflowDebugPage()",source:buildWorkflowDebugPageSource()}}function injectDebugRouteIntoAppSource(source,spec){let next=source;if(!next.includes(spec.importLine)){let importMarker='import { readRuntimeAsset } from "./lib/runtime-assets.js";';if(!next.includes(importMarker))throw new Error("\u65E0\u6CD5\u5728 src/app.js \u4E2D\u627E\u5230 runtime-assets import\uFF0C\u6682\u65F6\u65E0\u6CD5\u81EA\u52A8\u6CE8\u5165 debug scaffold \u8DEF\u7531\u3002");next=next.replace(importMarker,`${spec.importLine}
2369
2370
  ${importMarker}`)}if(!next.includes(`pathname === "${spec.routePath}"`)){let routeMarker=' sendJsonError(res, requestId, 404, "not_found", "Route not found");';if(!next.includes(routeMarker))throw new Error("\u65E0\u6CD5\u5728 src/app.js \u4E2D\u627E\u5230 404 \u8DEF\u7531\u843D\u70B9\uFF0C\u6682\u65F6\u65E0\u6CD5\u81EA\u52A8\u6CE8\u5165 debug scaffold \u8DEF\u7531\u3002");let routeBlock=[` if (pathname === "${spec.routePath}" && req.method === "GET") {`,' res.setHeader("content-type", "text/html; charset=utf-8");'," res.writeHead(200);",` res.end(${spec.renderCall});`," return;"," }",""].join(`
2370
2371
  `);next=next.replace(routeMarker,`${routeBlock}
@@ -2375,21 +2376,21 @@ ${routeMarker}`)}return next}function buildAuthDebugPageSource(){return["export
2375
2376
  `)}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(`
2376
2377
  `)}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=join4(appDir,"package.json"),nodeModulesPath=join4(appDir,"node_modules");if(!existsSync8(packageJsonPath)||existsSync8(nodeModulesPath))return null;let npmCommand=process.platform==="win32"?"npm.cmd":"npm",corepackCommand=process.platform==="win32"?"corepack.cmd":"corepack",yarnCommand=process.platform==="win32"?"yarn.cmd":"yarn";return existsSync8(join4(appDir,"package-lock.json"))?{command:npmCommand,args:["install"],lockfile:"package-lock.json"}:existsSync8(join4(appDir,"pnpm-lock.yaml"))?{command:corepackCommand,args:["pnpm","install","--frozen-lockfile"],lockfile:"pnpm-lock.yaml"}:existsSync8(join4(appDir,"yarn.lock"))?{command:yarnCommand,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=join4(appRoot,"resources","db","migrations");if(!existsSync8(migrationsDir)||!statSync3(migrationsDir).isDirectory())return!1;for(let entry of readdirSync2(migrationsDir,{withFileTypes:!0})){if(!entry.isFile())continue;if(readFileSync8(join4(migrationsDir,entry.name),"utf8").split(`
2377
2378
  `).map(line=>line.replace(/--.*$/,"").trim()).filter(Boolean).join(`
2378
- `).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(resolve16=>{let server=createNetServer(),finish=available=>{server.removeAllListeners(),resolve16(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((resolve16,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}resolve16(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=join4(directory,SOURCE_CONTEXT_FILE);throw new Error(existsSync8(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=join4(cwd,"package.json");if(!existsSync8(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(readFileSync8(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(`
2379
- `))}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 path=args.rest[3]?.trim()||readStringOption2(args,"path");if(!path)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,path).catch(error=>{throw formatAppLibraryError(error,"source(read)")});if(args.options.json===!0){writeJsonOrText(!0,response,[]);return}process.stdout.write(`# ${response.file.path}
2379
+ `).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(resolve17=>{let server=createNetServer(),finish=available=>{server.removeAllListeners(),resolve17(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((resolve17,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}resolve17(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=join4(directory,SOURCE_CONTEXT_FILE);throw new Error(existsSync8(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=join4(cwd,"package.json");if(!existsSync8(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(readFileSync8(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(`
2380
+ `))}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 path2=args.rest[3]?.trim()||readStringOption2(args,"path");if(!path2)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,path2).catch(error=>{throw formatAppLibraryError(error,"source(read)")});if(args.options.json===!0){writeJsonOrText(!0,response,[]);return}process.stdout.write(`# ${response.file.path}
2380
2381
 
2381
2382
  `),process.stdout.write(`${response.file.content}${response.file.content.endsWith(`
2382
2383
  `)?"":`
2383
- `}`)}async function runSourceSearch(args,sdk){let entryId=resolvePositionalOrConfigEntryId(args,2);if(!entryId)throw new Error("`platform app-library source search` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let query=args.rest[3]?.trim()||readStringOption2(args,"query");if(!query)throw new Error("`platform app-library source search` \u9700\u8981 <query>\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--query`\u3002");let response=await sdk.searchLightAppLibraryEntrySource(entryId,query).catch(error=>{throw formatAppLibraryError(error,"source(search)")});writeJsonOrText(args.options.json===!0,response,[`entry_id: ${entryId}`,`snapshot_id: ${response.snapshot_id}`,`query: ${query}`,`items: ${response.items.length}`,...response.items.map(item=>`- ${item.path}${item.excerpt?` :: ${item.excerpt}`:""}`)])}async function runCreate(args,sdk){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),payload=buildCreatePayload(args,config2);if(!payload.name?.trim())throw new Error("`platform app-library create` \u9700\u8981\u540D\u79F0\u3002\u8BF7\u5728 `app-library.yaml` \u4E2D\u8BBE\u7F6E `name`\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--name`\u3002");let response=await sdk.createLightAppLibraryEntry(payload).catch(error=>{throw formatAppLibraryError(error,"create")});maybeWriteConfig(configPath,config2,response,args),writeJsonOrText(args.options.json===!0,response,["\u8F7B\u5E94\u7528\u8D44\u4EA7\u8349\u7A3F\u5DF2\u521B\u5EFA\u3002",`entry_id: ${response.entry_id}`,`name: ${response.name}`,`status: ${response.status}`])}async function runUpdate(args,sdk){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),entryId=resolveEntryId(args,config2);if(!entryId)throw new Error("`platform app-library update` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let response=await sdk.updateLightAppLibraryEntry(entryId,buildUpdatePayload(args,config2)).catch(error=>{throw formatAppLibraryError(error,"update")});maybeWriteConfig(configPath,config2,response,args),writeJsonOrText(args.options.json===!0,response,["\u8F7B\u5E94\u7528\u8D44\u4EA7\u5DF2\u66F4\u65B0\u3002",`entry_id: ${response.entry_id}`,`name: ${response.name}`,`status: ${response.status}`])}async function runSubmit(args,sdk,deps){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),entryId=resolveEntryId(args,config2);if(!entryId)throw new Error("`platform app-library submit` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");if(config2){let updatedEntry=await sdk.updateLightAppLibraryEntry(entryId,buildUpdatePayload(args,config2)).catch(error=>{throw formatAppLibraryError(error,"submit(update-metadata)")});maybeWriteConfig(configPath,config2,updatedEntry,args)}let{files,appRoot}=(deps.collectWorkspaceFiles??collectSourceWorkspaceFiles)(process.cwd()),response=await sdk.submitLightAppLibraryEntrySnapshot(entryId,{files}).catch(error=>{throw formatAppLibraryError(error,"submit")});writeJsonOrText(args.options.json===!0,{snapshot:response,app_root:appRoot},["\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u5FEB\u7167\u5DF2\u63D0\u4EA4\u3002",`entry_id: ${entryId}`,`snapshot_id: ${response.snapshot_id}`,`files: ${response.files_count}`,`bytes: ${response.content_bytes}`,`app_root: ${appRoot}`])}async function runStateAction(args,sdk,action){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error(`\`platform app-library ${action}\` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 \`app-library.yaml\` \u4E2D\u63D0\u4F9B \`entry_id\`\u3002`);let response=action==="publish"?await sdk.publishLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"publish")}):action==="unpublish"?await sdk.unpublishLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"unpublish")}):await sdk.archiveLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"archive")});writeJsonOrText(args.options.json===!0,response,[`entry_id: ${response.entry_id}`,`status: ${response.status}`])}async function runDelete(args,sdk){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library delete` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let response=await sdk.deleteLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"delete")});writeJsonOrText(args.options.json===!0,response,[`\u5DF2\u5220\u9664\u6761\u76EE ${response.entry_id}`])}async function runCheckout(args,sdk){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library checkout` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let entry=await sdk.getLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"checkout(entry)")}),source=await sdk.getLightAppLibraryEntrySource(entryId).catch(error=>{throw formatAppLibraryError(error,"checkout(source)")}),targetDir=readStringOption2(args,"dir")??sanitizeDirectoryName(entry.name||entry.entry_id),absoluteTargetDir=resolve6(process.cwd(),targetDir);ensureEmptyDirectory(absoluteTargetDir);let sourceIncludesConfig=!1;for(let file of source.files){file.path==="app-library.yaml"&&(sourceIncludesConfig=!0);let payload=await sdk.readLightAppLibraryEntrySourceFile(entryId,file.path).catch(error=>{throw formatAppLibraryError(error,`checkout(file:${file.path})`)});writeWorkspaceFile(absoluteTargetDir,payload.file.path,payload.file.content)}let generatedConfigPath=join5(absoluteTargetDir,"app-library.yaml");args.options["no-config"]!==!0&&(args.options["write-config"]===!0||!sourceIncludesConfig)&&saveAppLibraryConfig(generatedConfigPath,materializeConfig(null,entry)),writeJsonOrText(args.options.json===!0,{entry_id:entryId,dir:absoluteTargetDir,files:source.files.length},["\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u5DF2 checkout \u5230\u672C\u5730\u76EE\u5F55\u3002",`entry_id: ${entryId}`,`dir: ${absoluteTargetDir}`,`files: ${source.files.length}`,...args.options["no-config"]===!0?[]:args.options["write-config"]===!0||!sourceIncludesConfig?[`config: ${generatedConfigPath}`]:[]])}async function runOpen(args,deps){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library open` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let url=`http://127.0.0.1:${process.env.TENANT_WORKBENCH_PORT?.trim()||"7102"}/#app-library/${encodeURIComponent(entryId)}`,opened=args.options["no-browser"]===!0?!1:(deps.openBrowser??tryOpenBrowser)(url);process.stdout.write(`${url}
2384
+ `}`)}async function runSourceSearch(args,sdk){let entryId=resolvePositionalOrConfigEntryId(args,2);if(!entryId)throw new Error("`platform app-library source search` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let query=args.rest[3]?.trim()||readStringOption2(args,"query");if(!query)throw new Error("`platform app-library source search` \u9700\u8981 <query>\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--query`\u3002");let response=await sdk.searchLightAppLibraryEntrySource(entryId,query).catch(error=>{throw formatAppLibraryError(error,"source(search)")});writeJsonOrText(args.options.json===!0,response,[`entry_id: ${entryId}`,`snapshot_id: ${response.snapshot_id}`,`query: ${query}`,`items: ${response.items.length}`,...response.items.map(item=>`- ${item.path}${item.excerpt?` :: ${item.excerpt}`:""}`)])}async function runCreate(args,sdk){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),payload=buildCreatePayload(args,config2);if(!payload.name?.trim())throw new Error("`platform app-library create` \u9700\u8981\u540D\u79F0\u3002\u8BF7\u5728 `app-library.yaml` \u4E2D\u8BBE\u7F6E `name`\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--name`\u3002");let response=await sdk.createLightAppLibraryEntry(payload).catch(error=>{throw formatAppLibraryError(error,"create")});maybeWriteConfig(configPath,config2,response,args),writeJsonOrText(args.options.json===!0,response,["\u8F7B\u5E94\u7528\u8D44\u4EA7\u8349\u7A3F\u5DF2\u521B\u5EFA\u3002",`entry_id: ${response.entry_id}`,`name: ${response.name}`,`status: ${response.status}`])}async function runUpdate(args,sdk){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),entryId=resolveEntryId(args,config2);if(!entryId)throw new Error("`platform app-library update` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let response=await sdk.updateLightAppLibraryEntry(entryId,buildUpdatePayload(args,config2)).catch(error=>{throw formatAppLibraryError(error,"update")});maybeWriteConfig(configPath,config2,response,args),writeJsonOrText(args.options.json===!0,response,["\u8F7B\u5E94\u7528\u8D44\u4EA7\u5DF2\u66F4\u65B0\u3002",`entry_id: ${response.entry_id}`,`name: ${response.name}`,`status: ${response.status}`])}async function runSubmit(args,sdk,deps){let configPath=resolveAppLibraryConfigPath(readStringOption2(args,"file")),config2=loadAppLibraryConfigOptional(readStringOption2(args,"file")),entryId=resolveEntryId(args,config2);if(!entryId)throw new Error("`platform app-library submit` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");if(config2){let updatedEntry=await sdk.updateLightAppLibraryEntry(entryId,buildUpdatePayload(args,config2)).catch(error=>{throw formatAppLibraryError(error,"submit(update-metadata)")});maybeWriteConfig(configPath,config2,updatedEntry,args)}let{files,appRoot}=(deps.collectWorkspaceFiles??collectSourceWorkspaceFiles)(process.cwd()),response=await sdk.submitLightAppLibraryEntrySnapshot(entryId,{files}).catch(error=>{throw formatAppLibraryError(error,"submit")});writeJsonOrText(args.options.json===!0,{snapshot:response,app_root:appRoot},["\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u5FEB\u7167\u5DF2\u63D0\u4EA4\u3002",`entry_id: ${entryId}`,`snapshot_id: ${response.snapshot_id}`,`files: ${response.files_count}`,`bytes: ${response.content_bytes}`,`app_root: ${appRoot}`])}async function runStateAction(args,sdk,action){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error(`\`platform app-library ${action}\` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 \`app-library.yaml\` \u4E2D\u63D0\u4F9B \`entry_id\`\u3002`);let response=action==="publish"?await sdk.publishLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"publish")}):action==="unpublish"?await sdk.unpublishLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"unpublish")}):await sdk.archiveLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"archive")});writeJsonOrText(args.options.json===!0,response,[`entry_id: ${response.entry_id}`,`status: ${response.status}`])}async function runDelete(args,sdk){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library delete` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let response=await sdk.deleteLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"delete")});writeJsonOrText(args.options.json===!0,response,[`\u5DF2\u5220\u9664\u6761\u76EE ${response.entry_id}`])}async function runCheckout(args,sdk){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library checkout` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let entry=await sdk.getLightAppLibraryEntry(entryId).catch(error=>{throw formatAppLibraryError(error,"checkout(entry)")}),source=await sdk.getLightAppLibraryEntrySource(entryId).catch(error=>{throw formatAppLibraryError(error,"checkout(source)")}),targetDir=readStringOption2(args,"dir")??sanitizeDirectoryName(entry.name||entry.entry_id),absoluteTargetDir=resolve6(process.cwd(),targetDir);ensureEmptyDirectory(absoluteTargetDir);let sourceIncludesConfig=!1;for(let file of source.files){file.path==="app-library.yaml"&&(sourceIncludesConfig=!0);let payload=await sdk.readLightAppLibraryEntrySourceFile(entryId,file.path).catch(error=>{throw formatAppLibraryError(error,`checkout(file:${file.path})`)});writeWorkspaceFile(absoluteTargetDir,payload.file.path,payload.file.content)}let generatedConfigPath=join5(absoluteTargetDir,"app-library.yaml");args.options["no-config"]!==!0&&(args.options["write-config"]===!0||!sourceIncludesConfig)&&saveAppLibraryConfig(generatedConfigPath,materializeConfig(null,entry)),writeJsonOrText(args.options.json===!0,{entry_id:entryId,dir:absoluteTargetDir,files:source.files.length},["\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u5DF2 checkout \u5230\u672C\u5730\u76EE\u5F55\u3002",`entry_id: ${entryId}`,`dir: ${absoluteTargetDir}`,`files: ${source.files.length}`,...args.options["no-config"]===!0?[]:args.options["write-config"]===!0||!sourceIncludesConfig?[`config: ${generatedConfigPath}`]:[]])}async function runOpen(args,deps){let entryId=resolveEntryId(args,loadAppLibraryConfigOptional());if(!entryId)throw new Error("`platform app-library open` \u9700\u8981 <entry-id>\uFF0C\u6216\u5728 `app-library.yaml` \u4E2D\u63D0\u4F9B `entry_id`\u3002");let url=`http://127.0.0.1:${process.env.TENANT_WORKBENCH_PORT?.trim()||"7102"}/#app-library/${encodeURIComponent(entryId)}`,opened=args.options["no-browser"]===!0?!1:await(deps.openBrowser??tryOpenBrowser)(url);process.stdout.write(`${url}
2384
2385
  `),!opened&&args.options["no-browser"]!==!0&&process.stdout.write(`\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u8BBF\u95EE\u4E0A\u9762\u7684 URL\u3002
2385
2386
  `),process.stdout.write(`inspect: platform app-library inspect ${entryId}
2386
2387
  `),process.stdout.write(`checkout: platform app-library checkout ${entryId} --dir ./${sanitizeDirectoryName(entryId)}
2387
- `)}function resolveTenantId(args){let binding=tryReadBinding(),context=loadStoredCliContext();return readStringOption2(args,"tenant")??binding?.tenant_id??context?.selected_app_tenant_id??context?.active_tenant_id}function resolveEntryId(args,config2){return args.rest[1]?.trim()||readStringOption2(args,"entry")||config2?.entry_id?.trim()}function resolvePositionalOrConfigEntryId(args,positionalIndex){return args.rest[positionalIndex]?.trim()||readStringOption2(args,"entry")||loadAppLibraryConfigOptional()?.entry_id?.trim()}function loadAppLibraryConfigOptional(filePath){let resolvedPath=resolveAppLibraryConfigPath(filePath);if(!resolvedPath||!existsSync9(resolvedPath))return null;let parsed=YAML2.parse(readFileSync9(resolvedPath,"utf8"));return parsed&&typeof parsed=="object"?parsed:null}function resolveAppLibraryConfigPath(filePath){if(filePath?.trim())return resolve6(process.cwd(),filePath.trim());try{return join5(findAppRoot(process.cwd()),"app-library.yaml")}catch{return null}}function resolveWritableAppLibraryConfigPath(filePath){return filePath?.trim()?resolve6(process.cwd(),filePath.trim()):resolveAppLibraryConfigPath()??join5(process.cwd(),"app-library.yaml")}function buildCreatePayload(args,config2){return{name:readStringOption2(args,"name")??config2?.name??"",...readStringOption2(args,"summary")??config2?.summary?{summary:readStringOption2(args,"summary")??config2?.summary}:{},...readTagsOption(args,config2)?.length?{tags:readTagsOption(args,config2)}:{},...readStringOption2(args,"readme")??config2?.readme?{readme:readStringOption2(args,"readme")??config2?.readme}:{},...readStringOption2(args,"template-key")??config2?.template_key?{template_key:readStringOption2(args,"template-key")??config2?.template_key}:{},...config2?.capability_dependencies?.length?{capability_dependencies:config2.capability_dependencies}:{},...readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id?{screenshot_asset_id:readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id}:{},...readStringOption2(args,"source-app-id")??config2?.source_app_id?{source_app_id:readStringOption2(args,"source-app-id")??config2?.source_app_id}:{},...readStringOption2(args,"source-version-id")??config2?.source_version_id?{source_version_id:readStringOption2(args,"source-version-id")??config2?.source_version_id}:{},...readStringOption2(args,"created-from")??config2?.created_from?{created_from:readStringOption2(args,"created-from")??config2?.created_from}:{}}}function buildUpdatePayload(args,config2){return{...readStringOption2(args,"name")??config2?.name?{name:readStringOption2(args,"name")??config2?.name}:{},...hasOption2(args,"summary")||config2?.summary!==void 0?{summary:readStringOption2(args,"summary")??config2?.summary??null}:{},...hasOption2(args,"tags")||config2?.tags?{tags:readTagsOption(args,config2)??[]}:{},...hasOption2(args,"readme")||config2?.readme!==void 0?{readme:readStringOption2(args,"readme")??config2?.readme??null}:{},...hasOption2(args,"template-key")||config2?.template_key!==void 0?{template_key:readStringOption2(args,"template-key")??config2?.template_key??null}:{},...config2?.capability_dependencies?{capability_dependencies:config2.capability_dependencies}:{},...hasOption2(args,"screenshot-asset-id")||config2?.screenshot_asset_id!==void 0?{screenshot_asset_id:readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id??null}:{},...hasOption2(args,"source-app-id")||config2?.source_app_id!==void 0?{source_app_id:readStringOption2(args,"source-app-id")??config2?.source_app_id??null}:{},...hasOption2(args,"source-version-id")||config2?.source_version_id!==void 0?{source_version_id:readStringOption2(args,"source-version-id")??config2?.source_version_id??null}:{},...hasOption2(args,"created-from")||config2?.created_from!==void 0?{created_from:readStringOption2(args,"created-from")??config2?.created_from??null}:{}}}function readTagsOption(args,config2){let explicit=readCsvOption2(args,"tags");return explicit.length>0?explicit:config2?.tags}function readStringOption2(args,key){let value=args.options[key];return typeof value=="string"&&value.trim()||void 0}function readCsvOption2(args,key){let value=readStringOption2(args,key);return value?value.split(",").map(item=>item.trim()).filter(Boolean):[]}function readStatusOption(args,key){let value=readStringOption2(args,key);return value==="draft"||value==="published"||value==="unpublished"||value==="archived"?value:void 0}function readVisibilityOption(args,key){let value=readStringOption2(args,key);return value==="private"||value==="public"?value:void 0}function hasOption2(args,key){return Object.prototype.hasOwnProperty.call(args.options,key)}function hasHelpFlag2(args){return args.options.help===!0||args.options.h===!0}function tryReadBinding(){try{return readBinding(process.cwd())?.binding}catch{return null}}function ensureEmptyDirectory(directory){if(existsSync9(directory)){if(readdirSync3(directory).length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u975E\u7A7A\uFF0C\u62D2\u7EDD\u8986\u76D6: ${directory}`);return}mkdirSync4(directory,{recursive:!0})}function writeWorkspaceFile(root,relativePath,content){let normalizedPath=relativePath.replace(/^\/+/g,"");if(!normalizedPath||normalizedPath.startsWith("..")||normalizedPath.includes("../")||normalizedPath.includes("..\\"))throw new Error(`\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5: ${relativePath}`);let outputPath=join5(root,normalizedPath);mkdirSync4(dirname6(outputPath),{recursive:!0}),writeFileSync5(outputPath,content,"utf8")}function sanitizeDirectoryName(value){return value.trim().toLowerCase().replace(/[^\p{L}\p{N}._-]+/gu,"-").replace(/^-+|-+$/g,"")||"light-app-library-entry"}function maybeWriteConfig(configPath,currentConfig,entry,args){configPath&&(!currentConfig&&args.options["write-config"]!==!0||saveAppLibraryConfig(configPath,materializeConfig(currentConfig,entry)))}function saveAppLibraryConfig(path,config2){mkdirSync4(dirname6(path),{recursive:!0}),writeFileSync5(path,YAML2.stringify(config2),"utf8")}function runConfigInit(args){let configPath=resolveWritableAppLibraryConfigPath(readStringOption2(args,"file"));if(existsSync9(configPath)&&args.options.force!==!0)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${configPath}\u3002\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u5165 --force\u3002`);saveAppLibraryConfig(configPath,{name:"",summary:"",tags:[],readme:"",capability_dependencies:[]}),writeJsonOrText(args.options.json===!0,{path:configPath,created:!0},["\u5DF2\u751F\u6210\u8F7B\u5E94\u7528\u8D44\u6E90\u5E93\u914D\u7F6E\u6A21\u677F\u3002",`path: ${configPath}`,"next: \u7F16\u8F91 app-library.yaml \u540E\uFF0C\u53EF\u6267\u884C `platform app-library config validate` \u6216 `platform app-library create`\u3002"])}function runConfigValidate(args){let configPath=resolveWritableAppLibraryConfigPath(readStringOption2(args,"file"));if(!existsSync9(configPath))throw new Error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);let raw=loadAppLibraryConfigOptional(configPath);if(!raw)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u5185\u5BB9\u4E3A\u7A7A\u6216\u683C\u5F0F\u975E\u6CD5: ${configPath}`);let normalized=validateAppLibraryConfig(raw,configPath);writeJsonOrText(args.options.json===!0,{path:configPath,config:normalized,valid:!0},["app-library.yaml \u6821\u9A8C\u901A\u8FC7\u3002",`path: ${configPath}`,`name: ${normalized.name}`,`tags: ${normalized.tags?.length??0}`,`capability_dependencies: ${normalized.capability_dependencies?.length??0}`])}function validateAppLibraryConfig(config2,configPath){let fail=message=>{throw new Error(`app-library.yaml \u6821\u9A8C\u5931\u8D25: ${message} (${configPath})`)},rawName=config2.name,normalizedName=typeof rawName=="string"?rawName.trim():"";return normalizedName||fail("`name` \u5FC5\u586B\u4E14\u5FC5\u987B\u4E3A\u975E\u7A7A\u5B57\u7B26\u4E32"),config2.summary!==void 0&&typeof config2.summary!="string"&&fail("`summary` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.readme!==void 0&&typeof config2.readme!="string"&&fail("`readme` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.template_key!==void 0&&typeof config2.template_key!="string"&&fail("`template_key` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.entry_id!==void 0&&typeof config2.entry_id!="string"&&fail("`entry_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.screenshot_asset_id!==void 0&&typeof config2.screenshot_asset_id!="string"&&fail("`screenshot_asset_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.source_app_id!==void 0&&typeof config2.source_app_id!="string"&&fail("`source_app_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.source_version_id!==void 0&&typeof config2.source_version_id!="string"&&fail("`source_version_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.created_from!==void 0&&typeof config2.created_from!="string"&&fail("`created_from` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.tags!==void 0&&!Array.isArray(config2.tags)&&fail("`tags` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4"),config2.tags?.some(item=>typeof item!="string"||!item.trim())&&fail("`tags` \u4E2D\u6BCF\u4E00\u9879\u90FD\u5FC5\u987B\u4E3A\u975E\u7A7A\u5B57\u7B26\u4E32"),config2.capability_dependencies!==void 0&&!Array.isArray(config2.capability_dependencies)&&fail("`capability_dependencies` \u5FC5\u987B\u4E3A\u6570\u7EC4"),config2.capability_dependencies?.some(item=>!item||typeof item!="object"||typeof item.capability!="string"||!item.capability.trim())&&fail("`capability_dependencies` \u4E2D\u6BCF\u4E00\u9879\u90FD\u5FC5\u987B\u5305\u542B\u975E\u7A7A\u5B57\u7B26\u4E32 `capability`"),config2.capability_dependencies?.some(item=>item.minVersion!==void 0&&typeof item.minVersion!="string")&&fail("`capability_dependencies[].minVersion` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),{entry_id:config2.entry_id?.trim()||void 0,name:normalizedName,summary:config2.summary??"",tags:config2.tags?.map(item=>item.trim()).filter(Boolean)??[],readme:config2.readme??"",template_key:config2.template_key?.trim()||void 0,capability_dependencies:config2.capability_dependencies?.map(item=>({capability:item.capability.trim(),...item.minVersion?.trim()?{minVersion:item.minVersion.trim()}:{}}))??[],screenshot_asset_id:config2.screenshot_asset_id?.trim()||void 0,source_app_id:config2.source_app_id?.trim()||void 0,source_version_id:config2.source_version_id?.trim()||void 0,created_from:config2.created_from?.trim()||void 0}}function materializeConfig(currentConfig,entry){return{...currentConfig,entry_id:entry.entry_id,name:entry.name,summary:entry.summary??"",tags:entry.tags??[],readme:entry.readme??"",template_key:entry.template_key??void 0,screenshot_asset_id:entry.screenshot_asset_id??void 0,source_app_id:entry.source_app_id??void 0,source_version_id:entry.source_version_id??void 0,created_from:entry.created_from??void 0,capability_dependencies:entry.capability_dependencies??[]}}function writeJsonOrText(json,payload,lines){if(json){process.stdout.write(`${JSON.stringify(payload,null,2)}
2388
+ `)}function resolveTenantId(args){let binding=tryReadBinding(),context=loadStoredCliContext();return readStringOption2(args,"tenant")??binding?.tenant_id??context?.selected_app_tenant_id??context?.active_tenant_id}function resolveEntryId(args,config2){return args.rest[1]?.trim()||readStringOption2(args,"entry")||config2?.entry_id?.trim()}function resolvePositionalOrConfigEntryId(args,positionalIndex){return args.rest[positionalIndex]?.trim()||readStringOption2(args,"entry")||loadAppLibraryConfigOptional()?.entry_id?.trim()}function loadAppLibraryConfigOptional(filePath){let resolvedPath=resolveAppLibraryConfigPath(filePath);if(!resolvedPath||!existsSync9(resolvedPath))return null;let parsed=YAML2.parse(readFileSync9(resolvedPath,"utf8"));return parsed&&typeof parsed=="object"?parsed:null}function resolveAppLibraryConfigPath(filePath){if(filePath?.trim())return resolve6(process.cwd(),filePath.trim());try{return join5(findAppRoot(process.cwd()),"app-library.yaml")}catch{return null}}function resolveWritableAppLibraryConfigPath(filePath){return filePath?.trim()?resolve6(process.cwd(),filePath.trim()):resolveAppLibraryConfigPath()??join5(process.cwd(),"app-library.yaml")}function buildCreatePayload(args,config2){return{name:readStringOption2(args,"name")??config2?.name??"",...readStringOption2(args,"summary")??config2?.summary?{summary:readStringOption2(args,"summary")??config2?.summary}:{},...readTagsOption(args,config2)?.length?{tags:readTagsOption(args,config2)}:{},...readStringOption2(args,"readme")??config2?.readme?{readme:readStringOption2(args,"readme")??config2?.readme}:{},...readStringOption2(args,"template-key")??config2?.template_key?{template_key:readStringOption2(args,"template-key")??config2?.template_key}:{},...config2?.capability_dependencies?.length?{capability_dependencies:config2.capability_dependencies}:{},...readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id?{screenshot_asset_id:readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id}:{},...readStringOption2(args,"source-app-id")??config2?.source_app_id?{source_app_id:readStringOption2(args,"source-app-id")??config2?.source_app_id}:{},...readStringOption2(args,"source-version-id")??config2?.source_version_id?{source_version_id:readStringOption2(args,"source-version-id")??config2?.source_version_id}:{},...readStringOption2(args,"created-from")??config2?.created_from?{created_from:readStringOption2(args,"created-from")??config2?.created_from}:{}}}function buildUpdatePayload(args,config2){return{...readStringOption2(args,"name")??config2?.name?{name:readStringOption2(args,"name")??config2?.name}:{},...hasOption2(args,"summary")||config2?.summary!==void 0?{summary:readStringOption2(args,"summary")??config2?.summary??null}:{},...hasOption2(args,"tags")||config2?.tags?{tags:readTagsOption(args,config2)??[]}:{},...hasOption2(args,"readme")||config2?.readme!==void 0?{readme:readStringOption2(args,"readme")??config2?.readme??null}:{},...hasOption2(args,"template-key")||config2?.template_key!==void 0?{template_key:readStringOption2(args,"template-key")??config2?.template_key??null}:{},...config2?.capability_dependencies?{capability_dependencies:config2.capability_dependencies}:{},...hasOption2(args,"screenshot-asset-id")||config2?.screenshot_asset_id!==void 0?{screenshot_asset_id:readStringOption2(args,"screenshot-asset-id")??config2?.screenshot_asset_id??null}:{},...hasOption2(args,"source-app-id")||config2?.source_app_id!==void 0?{source_app_id:readStringOption2(args,"source-app-id")??config2?.source_app_id??null}:{},...hasOption2(args,"source-version-id")||config2?.source_version_id!==void 0?{source_version_id:readStringOption2(args,"source-version-id")??config2?.source_version_id??null}:{},...hasOption2(args,"created-from")||config2?.created_from!==void 0?{created_from:readStringOption2(args,"created-from")??config2?.created_from??null}:{}}}function readTagsOption(args,config2){let explicit=readCsvOption2(args,"tags");return explicit.length>0?explicit:config2?.tags}function readStringOption2(args,key){let value=args.options[key];return typeof value=="string"&&value.trim()||void 0}function readCsvOption2(args,key){let value=readStringOption2(args,key);return value?value.split(",").map(item=>item.trim()).filter(Boolean):[]}function readStatusOption(args,key){let value=readStringOption2(args,key);return value==="draft"||value==="published"||value==="unpublished"||value==="archived"?value:void 0}function readVisibilityOption(args,key){let value=readStringOption2(args,key);return value==="private"||value==="public"?value:void 0}function hasOption2(args,key){return Object.prototype.hasOwnProperty.call(args.options,key)}function hasHelpFlag2(args){return args.options.help===!0||args.options.h===!0}function tryReadBinding(){try{return readBinding(process.cwd())?.binding}catch{return null}}function ensureEmptyDirectory(directory){if(existsSync9(directory)){if(readdirSync3(directory).length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u975E\u7A7A\uFF0C\u62D2\u7EDD\u8986\u76D6: ${directory}`);return}mkdirSync4(directory,{recursive:!0})}function writeWorkspaceFile(root,relativePath,content){let normalizedPath=relativePath.replace(/^\/+/g,"");if(!normalizedPath||normalizedPath.startsWith("..")||normalizedPath.includes("../")||normalizedPath.includes("..\\"))throw new Error(`\u8F7B\u5E94\u7528\u8D44\u4EA7\u6E90\u7801\u6587\u4EF6\u8DEF\u5F84\u975E\u6CD5: ${relativePath}`);let outputPath=join5(root,normalizedPath);mkdirSync4(dirname6(outputPath),{recursive:!0}),writeFileSync5(outputPath,content,"utf8")}function sanitizeDirectoryName(value){return value.trim().toLowerCase().replace(/[^\p{L}\p{N}._-]+/gu,"-").replace(/^-+|-+$/g,"")||"light-app-library-entry"}function maybeWriteConfig(configPath,currentConfig,entry,args){configPath&&(!currentConfig&&args.options["write-config"]!==!0||saveAppLibraryConfig(configPath,materializeConfig(currentConfig,entry)))}function saveAppLibraryConfig(path2,config2){mkdirSync4(dirname6(path2),{recursive:!0}),writeFileSync5(path2,YAML2.stringify(config2),"utf8")}function runConfigInit(args){let configPath=resolveWritableAppLibraryConfigPath(readStringOption2(args,"file"));if(existsSync9(configPath)&&args.options.force!==!0)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u5DF2\u5B58\u5728\uFF0C\u62D2\u7EDD\u8986\u76D6: ${configPath}\u3002\u5982\u9700\u8986\u76D6\u8BF7\u4F20\u5165 --force\u3002`);saveAppLibraryConfig(configPath,{name:"",summary:"",tags:[],readme:"",capability_dependencies:[]}),writeJsonOrText(args.options.json===!0,{path:configPath,created:!0},["\u5DF2\u751F\u6210\u8F7B\u5E94\u7528\u8D44\u6E90\u5E93\u914D\u7F6E\u6A21\u677F\u3002",`path: ${configPath}`,"next: \u7F16\u8F91 app-library.yaml \u540E\uFF0C\u53EF\u6267\u884C `platform app-library config validate` \u6216 `platform app-library create`\u3002"])}function runConfigValidate(args){let configPath=resolveWritableAppLibraryConfigPath(readStringOption2(args,"file"));if(!existsSync9(configPath))throw new Error(`\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6: ${configPath}`);let raw=loadAppLibraryConfigOptional(configPath);if(!raw)throw new Error(`\u914D\u7F6E\u6587\u4EF6\u5185\u5BB9\u4E3A\u7A7A\u6216\u683C\u5F0F\u975E\u6CD5: ${configPath}`);let normalized=validateAppLibraryConfig(raw,configPath);writeJsonOrText(args.options.json===!0,{path:configPath,config:normalized,valid:!0},["app-library.yaml \u6821\u9A8C\u901A\u8FC7\u3002",`path: ${configPath}`,`name: ${normalized.name}`,`tags: ${normalized.tags?.length??0}`,`capability_dependencies: ${normalized.capability_dependencies?.length??0}`])}function validateAppLibraryConfig(config2,configPath){let fail=message=>{throw new Error(`app-library.yaml \u6821\u9A8C\u5931\u8D25: ${message} (${configPath})`)},rawName=config2.name,normalizedName=typeof rawName=="string"?rawName.trim():"";return normalizedName||fail("`name` \u5FC5\u586B\u4E14\u5FC5\u987B\u4E3A\u975E\u7A7A\u5B57\u7B26\u4E32"),config2.summary!==void 0&&typeof config2.summary!="string"&&fail("`summary` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.readme!==void 0&&typeof config2.readme!="string"&&fail("`readme` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.template_key!==void 0&&typeof config2.template_key!="string"&&fail("`template_key` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.entry_id!==void 0&&typeof config2.entry_id!="string"&&fail("`entry_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.screenshot_asset_id!==void 0&&typeof config2.screenshot_asset_id!="string"&&fail("`screenshot_asset_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.source_app_id!==void 0&&typeof config2.source_app_id!="string"&&fail("`source_app_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.source_version_id!==void 0&&typeof config2.source_version_id!="string"&&fail("`source_version_id` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.created_from!==void 0&&typeof config2.created_from!="string"&&fail("`created_from` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),config2.tags!==void 0&&!Array.isArray(config2.tags)&&fail("`tags` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32\u6570\u7EC4"),config2.tags?.some(item=>typeof item!="string"||!item.trim())&&fail("`tags` \u4E2D\u6BCF\u4E00\u9879\u90FD\u5FC5\u987B\u4E3A\u975E\u7A7A\u5B57\u7B26\u4E32"),config2.capability_dependencies!==void 0&&!Array.isArray(config2.capability_dependencies)&&fail("`capability_dependencies` \u5FC5\u987B\u4E3A\u6570\u7EC4"),config2.capability_dependencies?.some(item=>!item||typeof item!="object"||typeof item.capability!="string"||!item.capability.trim())&&fail("`capability_dependencies` \u4E2D\u6BCF\u4E00\u9879\u90FD\u5FC5\u987B\u5305\u542B\u975E\u7A7A\u5B57\u7B26\u4E32 `capability`"),config2.capability_dependencies?.some(item=>item.minVersion!==void 0&&typeof item.minVersion!="string")&&fail("`capability_dependencies[].minVersion` \u5FC5\u987B\u4E3A\u5B57\u7B26\u4E32"),{entry_id:config2.entry_id?.trim()||void 0,name:normalizedName,summary:config2.summary??"",tags:config2.tags?.map(item=>item.trim()).filter(Boolean)??[],readme:config2.readme??"",template_key:config2.template_key?.trim()||void 0,capability_dependencies:config2.capability_dependencies?.map(item=>({capability:item.capability.trim(),...item.minVersion?.trim()?{minVersion:item.minVersion.trim()}:{}}))??[],screenshot_asset_id:config2.screenshot_asset_id?.trim()||void 0,source_app_id:config2.source_app_id?.trim()||void 0,source_version_id:config2.source_version_id?.trim()||void 0,created_from:config2.created_from?.trim()||void 0}}function materializeConfig(currentConfig,entry){return{...currentConfig,entry_id:entry.entry_id,name:entry.name,summary:entry.summary??"",tags:entry.tags??[],readme:entry.readme??"",template_key:entry.template_key??void 0,screenshot_asset_id:entry.screenshot_asset_id??void 0,source_app_id:entry.source_app_id??void 0,source_version_id:entry.source_version_id??void 0,created_from:entry.created_from??void 0,capability_dependencies:entry.capability_dependencies??[]}}function writeJsonOrText(json,payload,lines){if(json){process.stdout.write(`${JSON.stringify(payload,null,2)}
2388
2389
  `);return}process.stdout.write(`${lines.join(`
2389
2390
  `)}
2390
- `)}function formatEntrySummary(item,index,full){let typeLabel=item.type==="example_app"?"example-app":item.type,tenantLabel=item.library?.tenant_id??"-",tags=item.tags.length?item.tags.slice(0,3).join(", "):"-",capabilities=item.capability_dependencies?.length?item.capability_dependencies.slice(0,3).map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability).join(", "):"-";if(!full)return[`[${index}] ${item.name} (${item.entry_id})`,` ${item.status} \xB7 ${typeLabel} \xB7 ${item.template_key??"-"} \xB7 tenant=${tenantLabel}`,` summary: ${item.summary?.trim()||"-"}`,` tags: ${tags}`,` capabilities: ${capabilities}`];let fullCapabilities=item.capability_dependencies?.length?item.capability_dependencies.map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability).join(", "):"-";return[`[${index}] ${item.name} (${item.entry_id})`,` status: ${item.status} type: ${typeLabel}`,` summary: ${item.summary?.trim()||"-"}`,` tags: ${item.tags.length?item.tags.join(", "):"-"}`,` template: ${item.template_key??"-"} snapshot: ${item.current_snapshot_id??"-"}`,` capabilities: ${fullCapabilities}`]}function toEntryListBriefPayload(response){return{items:response.items.map(item=>({entry_id:item.entry_id,name:item.name,summary:item.summary??"",status:item.status,type:item.type,template_key:item.template_key??null,tags:Array.isArray(item.tags)?item.tags.slice(0,3):[],capability_dependencies:Array.isArray(item.capability_dependencies)?item.capability_dependencies.slice(0,3).map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability):[],library:item.library?{tenant_id:item.library.tenant_id,visibility:item.library.visibility}:void 0}))}}function formatAppLibraryError(error,stage){return error instanceof PlatformApiError?new Error(`app-library ${stage} failed: ${error.message}${error.code?` (${error.code})`:""}`):error instanceof Error?error:new Error(`app-library ${stage} failed`)}function tryOpenBrowser(url){try{return process.platform==="darwin"?(spawn2("open",[url],{stdio:"ignore",detached:!0}).unref(),!0):process.platform==="win32"?(spawn2("cmd",["/c","start","",url],{stdio:"ignore",detached:!0}).unref(),!0):(spawn2("xdg-open",[url],{stdio:"ignore",detached:!0}).unref(),!0)}catch{return!1}}import{execFileSync}from"node:child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync7,readFileSync as readFileSync13,writeFileSync as writeFileSync8}from"node:fs";import{dirname as dirname9,join as join9}from"node:path";import{createHash as createHash4}from"node:crypto";import{existsSync as existsSync10,readFileSync as readFileSync10}from"node:fs";import{join as join6}from"node:path";function inspectPlatformBlocksAdoptability(appRoot,manifest){let files=manifest.managed_files.map(file=>{let current=readCurrentSha(appRoot,file.path);return current?current===file.content_sha256?{path:file.path,status:"match"}:{path:file.path,status:"drift"}:{path:file.path,status:"missing"}});return{adoptable:files.every(file=>file.status==="match"),files}}function computePlatformBlocksDiff(appRoot,manifest,lockfile){let lockFiles=new Map(lockfile.managed_files.map(file=>[file.path,file]));return manifest.managed_files.map(file=>{let current_sha256=readCurrentSha(appRoot,file.path),lock_sha256=lockFiles.get(file.path)?.applied_sha256??null;return current_sha256===file.content_sha256?{path:file.path,status:lock_sha256===file.content_sha256?"noop":"lock_refresh",current_sha256,lock_sha256,target_sha256:file.content_sha256}:current_sha256===null||current_sha256===lock_sha256?{path:file.path,status:"safe_update",current_sha256,lock_sha256,target_sha256:file.content_sha256}:{path:file.path,status:"conflict",current_sha256,lock_sha256,target_sha256:file.content_sha256}})}function determinePlatformBlocksApplyOutcome(diff){return diff.some(file=>file.status==="conflict")?"conflict":diff.some(file=>file.status==="safe_update")?"updated":diff.some(file=>file.status==="lock_refresh")?"lock_refreshed":"noop"}function checksumContent(content){return`sha256-${createHash4("sha256").update(content).digest("hex")}`}function readCurrentSha(appRoot,relativePath){let absolutePath=join6(appRoot,relativePath);return existsSync10(absolutePath)?checksumContent(readFileSync10(absolutePath,"utf8")):null}import{existsSync as existsSync12,mkdirSync as mkdirSync6,readFileSync as readFileSync12,readdirSync as readdirSync4,rmSync,writeFileSync as writeFileSync7}from"node:fs";import{dirname as dirname8,join as join8,relative as relative2}from"node:path";import{dirname as dirname7,join as join7}from"node:path";import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync11,writeFileSync as writeFileSync6}from"node:fs";var PLATFORM_BLOCKS_LOCKFILE_RELATIVE_PATH=".platform/platform-blocks.lock.json";function getPlatformBlocksLockfilePath(appRoot){return join7(appRoot,PLATFORM_BLOCKS_LOCKFILE_RELATIVE_PATH)}function readPlatformBlocksLockfile(startDir){let{directory:appRoot}=readAppManifest(startDir),path=getPlatformBlocksLockfilePath(appRoot);if(!existsSync11(path))return null;let raw=readFileSync11(path,"utf8"),lockfile=JSON.parse(raw);return{appRoot,path,lockfile,raw}}function writePlatformBlocksLockfile(appRoot,content){let path=getPlatformBlocksLockfilePath(appRoot);mkdirSync5(dirname7(path),{recursive:!0});let serialized=typeof content=="string"?content:`${JSON.stringify(content,null,2)}
2391
- `;return writeFileSync6(path,serialized,"utf8"),path}function resolvePlatformBlocksTemplateKey(startDir){let{directory:appRoot}=readAppManifest(startDir),sourceContextTemplateKey=normalizeAppTemplateKey(readSourceContext(appRoot)?.sourceContext.template_key);if(sourceContextTemplateKey)return sourceContextTemplateKey;let lockfileTemplateKey=normalizeAppTemplateKey(readPlatformBlocksLockfile(appRoot)?.lockfile.template_key);if(lockfileTemplateKey)return lockfileTemplateKey;throw new Error("\u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u7684\u6A21\u677F\u3002\u8BF7\u5148\u901A\u8FC7 checkout/\u7ED1\u5B9A\u4E0A\u4E0B\u6587\u8FDB\u5165\u53D7\u652F\u6301\u7684 frontend/backend app \u5DE5\u7A0B\u3002")}var HISTORY_LAST_RELATIVE_DIR=".platform/platform-blocks.history/last";function getPlatformBlocksHistoryLastDir(appRoot){return join8(appRoot,HISTORY_LAST_RELATIVE_DIR)}function writeLastPlatformBlocksHistory(appRoot,args){let historyDir=getPlatformBlocksHistoryLastDir(appRoot);rmSync(historyDir,{recursive:!0,force:!0}),mkdirSync6(join8(historyDir,"files"),{recursive:!0});for(let file of args.files){if(!file.existed_before||typeof file.content!="string")continue;let snapshotPath=join8(historyDir,"files",file.path);mkdirSync6(dirname8(snapshotPath),{recursive:!0}),writeFileSync7(snapshotPath,file.content,"utf8")}writeFileSync7(join8(historyDir,"lockfile.before.json"),args.lockfileBefore,"utf8"),writeFileSync7(join8(historyDir,"lockfile.after.json"),args.lockfileAfter,"utf8");let metadata={template_key:args.templateKey,platform_blocks_revision_before:args.revisionBefore,platform_blocks_revision_after:args.revisionAfter,managed_files_overwritten:args.files.map(file=>({path:file.path,existed_before:file.existed_before})),lockfile_before_path:"lockfile.before.json",lockfile_after_path:"lockfile.after.json",created_at:new Date().toISOString()};return writeFileSync7(join8(historyDir,"metadata.json"),`${JSON.stringify(metadata,null,2)}
2392
- `,"utf8"),historyDir}function restoreLastPlatformBlocksHistory(appRoot){let historyDir=getPlatformBlocksHistoryLastDir(appRoot),metadataPath=join8(historyDir,"metadata.json");if(!existsSync12(metadataPath))throw new Error("\u65E0\u53EF\u56DE\u9000\u7684\u6700\u8FD1\u4E00\u6B21 apply\u3002");let metadata=JSON.parse(readFileSync12(metadataPath,"utf8")),restoredFiles=[],removedFiles=[];for(let file of metadata.managed_files_overwritten){let targetPath=join8(appRoot,file.path);if(!file.existed_before){rmSync(targetPath,{force:!0}),removedFiles.push(file.path);continue}let snapshotPath=join8(historyDir,"files",file.path),content=readFileSync12(snapshotPath,"utf8");mkdirSync6(dirname8(targetPath),{recursive:!0}),writeFileSync7(targetPath,content,"utf8"),restoredFiles.push(file.path)}let lockfilePath=getPlatformBlocksLockfilePath(appRoot);return mkdirSync6(dirname8(lockfilePath),{recursive:!0}),writeFileSync7(lockfilePath,readFileSync12(join8(historyDir,metadata.lockfile_before_path),"utf8"),"utf8"),{restoredFiles,removedFiles,lockfilePath:relative2(appRoot,lockfilePath).replace(/\\/g,"/")}}function hasLastPlatformBlocksHistory(appRoot){return existsSync12(join8(getPlatformBlocksHistoryLastDir(appRoot),"metadata.json"))}var CLI_TOOL_VERSION=`@voobase/cli@${getCliPackageVersion()}`;function runAppSyncPlatformBlocksCommand(args){let{directory:appRoot}=readAppManifest(args.cwd);if(args.rollbackLast){let restored=restoreLastPlatformBlocksHistory(appRoot);return{mode:"rollback",appRoot,restoredFiles:restored.restoredFiles,removedFiles:restored.removedFiles,lockfilePath:restored.lockfilePath}}let templateKey=resolvePlatformBlocksTemplateKey(appRoot),manifest=getPlatformBlocksManifest(templateKey),templateFiles=buildTemplateFileMap(templateKey),lockRecord=readPlatformBlocksLockfile(appRoot);if(args.adopt){if(lockRecord)return{mode:"adopt",appRoot,templateKey,status:"already_managed",targetRevision:manifest.platform_blocks_revision,lockfilePath:lockRecord.path};let adopt=inspectPlatformBlocksAdoptability(appRoot,manifest);if(!adopt.adoptable){let problems=adopt.files.filter(file=>file.status!=="match").map(file=>`${file.path}=${file.status}`).join(", ");throw new Error(`\u5F53\u524D\u5DE5\u7A0B\u5C1A\u672A\u8FBE\u5230 adopt \u6761\u4EF6\uFF1A${problems}`)}let nextLockfile=buildPlatformBlocksLockfile(manifest,{mode:"adopt",toolVersion:CLI_TOOL_VERSION}),lockfilePath=writePlatformBlocksLockfile(appRoot,stringifyPlatformBlocksLockfile(nextLockfile));return{mode:"adopt",appRoot,templateKey,status:"adopted",targetRevision:manifest.platform_blocks_revision,lockfilePath}}if(args.apply){if(!lockRecord)throw new Error("\u7F3A\u5C11 `.platform/platform-blocks.lock.json`\uFF0C\u8BF7\u5148\u6267\u884C `platform app sync-platform-blocks --adopt`\u3002");let diff2=computePlatformBlocksDiff(appRoot,manifest,lockRecord.lockfile),outcome=determinePlatformBlocksApplyOutcome(diff2);if(outcome==="conflict"){let conflictList=diff2.filter(file=>file.status==="conflict").map(file=>file.path).join(", ");throw new Error(`\u68C0\u6D4B\u5230\u5E73\u53F0\u5757\u51B2\u7A81\uFF0C\u5DF2\u62D2\u7EDD apply\uFF1A${conflictList}`)}let nextLockfile=buildPlatformBlocksLockfile(manifest,{mode:outcome==="lock_refreshed"?"lock_refreshed":"apply",toolVersion:CLI_TOOL_VERSION}),nextLockfileRaw=stringifyPlatformBlocksLockfile(nextLockfile);if(outcome==="updated"){let snapshots=diff2.filter(file=>file.status==="safe_update").map(file=>buildHistorySnapshot(appRoot,file.path));for(let file of diff2.filter(item=>item.status==="safe_update")){let target=templateFiles.get(file.path);if(typeof target!="string")throw new Error(`\u6A21\u677F\u7F3A\u5C11\u76EE\u6807\u6587\u4EF6\uFF1A${file.path}`);writeManagedFile(appRoot,file.path,target)}writePlatformBlocksLockfile(appRoot,nextLockfileRaw),writeLastPlatformBlocksHistory(appRoot,{templateKey,revisionBefore:lockRecord.lockfile.platform_blocks_revision,revisionAfter:manifest.platform_blocks_revision,files:snapshots,lockfileBefore:lockRecord.raw,lockfileAfter:nextLockfileRaw});let verify2=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:outcome,targetRevision:manifest.platform_blocks_revision,updatedFiles:diff2.filter(file=>file.status==="safe_update").map(file=>file.path),lockfilePath:lockRecord.path,historyUpdated:!0,verify:verify2}}if(outcome==="lock_refreshed"){writePlatformBlocksLockfile(appRoot,nextLockfileRaw);let verify2=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:outcome,targetRevision:manifest.platform_blocks_revision,updatedFiles:[],lockfilePath:lockRecord.path,historyUpdated:!1,verify:verify2}}let verify=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:"noop",targetRevision:manifest.platform_blocks_revision,updatedFiles:[],lockfilePath:lockRecord.path,historyUpdated:!1,verify}}if(!lockRecord){let adopt=inspectPlatformBlocksAdoptability(appRoot,manifest);return{mode:"dry-run",appRoot,templateKey,targetRevision:manifest.platform_blocks_revision,managedFiles:manifest.managed_files.length,lockfilePresent:!1,adoptable:adopt.adoptable}}let diff=computePlatformBlocksDiff(appRoot,manifest,lockRecord.lockfile);return{mode:"dry-run",appRoot,templateKey,targetRevision:manifest.platform_blocks_revision,managedFiles:manifest.managed_files.length,lockfilePresent:!0,safeUpdates:diff.filter(file=>file.status==="safe_update").length,lockRefreshes:diff.filter(file=>file.status==="lock_refresh").length,conflicts:diff.filter(file=>file.status==="conflict").length,noopFiles:diff.filter(file=>file.status==="noop").length}}function formatAppSyncPlatformBlocksResult(result){return result.mode==="rollback"?["\u5E73\u53F0\u5757\u5DF2\u56DE\u9000\u5230\u6700\u8FD1\u4E00\u6B21\u5FEB\u7167\u3002",`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,result.restoredFiles.length>0?`\u6062\u590D\u6587\u4EF6:
2391
+ `)}function formatEntrySummary(item,index,full){let typeLabel=item.type==="example_app"?"example-app":item.type,tenantLabel=item.library?.tenant_id??"-",tags=item.tags.length?item.tags.slice(0,3).join(", "):"-",capabilities=item.capability_dependencies?.length?item.capability_dependencies.slice(0,3).map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability).join(", "):"-";if(!full)return[`[${index}] ${item.name} (${item.entry_id})`,` ${item.status} \xB7 ${typeLabel} \xB7 ${item.template_key??"-"} \xB7 tenant=${tenantLabel}`,` summary: ${item.summary?.trim()||"-"}`,` tags: ${tags}`,` capabilities: ${capabilities}`];let fullCapabilities=item.capability_dependencies?.length?item.capability_dependencies.map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability).join(", "):"-";return[`[${index}] ${item.name} (${item.entry_id})`,` status: ${item.status} type: ${typeLabel}`,` summary: ${item.summary?.trim()||"-"}`,` tags: ${item.tags.length?item.tags.join(", "):"-"}`,` template: ${item.template_key??"-"} snapshot: ${item.current_snapshot_id??"-"}`,` capabilities: ${fullCapabilities}`]}function toEntryListBriefPayload(response){return{items:response.items.map(item=>({entry_id:item.entry_id,name:item.name,summary:item.summary??"",status:item.status,type:item.type,template_key:item.template_key??null,tags:Array.isArray(item.tags)?item.tags.slice(0,3):[],capability_dependencies:Array.isArray(item.capability_dependencies)?item.capability_dependencies.slice(0,3).map(dependency=>dependency.minVersion?`${dependency.capability}@${dependency.minVersion}`:dependency.capability):[],library:item.library?{tenant_id:item.library.tenant_id,visibility:item.library.visibility}:void 0}))}}function formatAppLibraryError(error,stage){return error instanceof PlatformApiError?new Error(`app-library ${stage} failed: ${error.message}${error.code?` (${error.code})`:""}`):error instanceof Error?error:new Error(`app-library ${stage} failed`)}async function tryOpenBrowser(url){return(await openExternal(url)).opened}import{execFileSync}from"node:child_process";import{existsSync as existsSync13,mkdirSync as mkdirSync7,readFileSync as readFileSync13,unlinkSync,writeFileSync as writeFileSync8}from"node:fs";import{dirname as dirname9,isAbsolute,join as join9,resolve as resolve7,sep}from"node:path";import{createHash as createHash4}from"node:crypto";import{existsSync as existsSync10,readFileSync as readFileSync10}from"node:fs";import{join as join6}from"node:path";function inspectPlatformBlocksAdoptability(appRoot,manifest){let files=manifest.managed_files.map(file=>{let current=readCurrentSha(appRoot,file.path);return current?current===file.content_sha256?{path:file.path,status:"match"}:{path:file.path,status:"drift"}:{path:file.path,status:"missing"}});return{adoptable:files.every(file=>file.status==="match"),files}}function computePlatformBlocksDiff(appRoot,manifest,lockfile){let lockFiles=new Map(lockfile.managed_files.map(file=>[file.path,file])),targetFiles=new Map(manifest.managed_files.map(file=>[file.path,file])),targetDiff=manifest.managed_files.map(file=>{let current_sha256=readCurrentSha(appRoot,file.path),lock_sha256=lockFiles.get(file.path)?.applied_sha256??null;return current_sha256===file.content_sha256?{path:file.path,status:lock_sha256===file.content_sha256?"noop":"lock_refresh",current_sha256,lock_sha256,target_sha256:file.content_sha256}:current_sha256===null||current_sha256===lock_sha256?{path:file.path,status:"safe_update",current_sha256,lock_sha256,target_sha256:file.content_sha256}:{path:file.path,status:"conflict",current_sha256,lock_sha256,target_sha256:file.content_sha256}}),removedDiff=lockfile.managed_files.filter(file=>!targetFiles.has(file.path)).map(file=>{let current_sha256=readCurrentSha(appRoot,file.path);return current_sha256===null?{path:file.path,status:"lock_refresh",current_sha256,lock_sha256:file.applied_sha256,target_sha256:null}:{path:file.path,status:current_sha256===file.applied_sha256?"safe_remove":"conflict",current_sha256,lock_sha256:file.applied_sha256,target_sha256:null}});return[...targetDiff,...removedDiff]}function determinePlatformBlocksApplyOutcome(diff){return diff.some(file=>file.status==="conflict")?"conflict":diff.some(file=>file.status==="safe_update"||file.status==="safe_remove")?"updated":diff.some(file=>file.status==="lock_refresh")?"lock_refreshed":"noop"}function checksumContent(content){return`sha256-${createHash4("sha256").update(content).digest("hex")}`}function readCurrentSha(appRoot,relativePath){let absolutePath=join6(appRoot,relativePath);return existsSync10(absolutePath)?checksumContent(readFileSync10(absolutePath,"utf8")):null}import{existsSync as existsSync12,mkdirSync as mkdirSync6,readFileSync as readFileSync12,readdirSync as readdirSync4,rmSync as rmSync2,writeFileSync as writeFileSync7}from"node:fs";import{dirname as dirname8,join as join8,relative as relative2}from"node:path";import{dirname as dirname7,join as join7}from"node:path";import{existsSync as existsSync11,mkdirSync as mkdirSync5,readFileSync as readFileSync11,writeFileSync as writeFileSync6}from"node:fs";var PLATFORM_BLOCKS_LOCKFILE_RELATIVE_PATH=".platform/platform-blocks.lock.json";function getPlatformBlocksLockfilePath(appRoot){return join7(appRoot,PLATFORM_BLOCKS_LOCKFILE_RELATIVE_PATH)}function readPlatformBlocksLockfile(startDir){let{directory:appRoot}=readAppManifest(startDir),path2=getPlatformBlocksLockfilePath(appRoot);if(!existsSync11(path2))return null;let raw=readFileSync11(path2,"utf8"),lockfile=JSON.parse(raw);return{appRoot,path:path2,lockfile,raw}}function writePlatformBlocksLockfile(appRoot,content){let path2=getPlatformBlocksLockfilePath(appRoot);mkdirSync5(dirname7(path2),{recursive:!0});let serialized=typeof content=="string"?content:`${JSON.stringify(content,null,2)}
2392
+ `;return writeFileSync6(path2,serialized,"utf8"),path2}function resolvePlatformBlocksTemplateKey(startDir){let{directory:appRoot}=readAppManifest(startDir),sourceContextTemplateKey=normalizeAppTemplateKey(readSourceContext(appRoot)?.sourceContext.template_key);if(sourceContextTemplateKey)return sourceContextTemplateKey;let lockfileTemplateKey=normalizeAppTemplateKey(readPlatformBlocksLockfile(appRoot)?.lockfile.template_key);if(lockfileTemplateKey)return lockfileTemplateKey;throw new Error("\u65E0\u6CD5\u8BC6\u522B\u5F53\u524D\u5DE5\u7A0B\u7684\u6A21\u677F\u3002\u8BF7\u5148\u901A\u8FC7 checkout/\u7ED1\u5B9A\u4E0A\u4E0B\u6587\u8FDB\u5165\u53D7\u652F\u6301\u7684 frontend/backend app \u5DE5\u7A0B\u3002")}var HISTORY_LAST_RELATIVE_DIR=".platform/platform-blocks.history/last";function getPlatformBlocksHistoryLastDir(appRoot){return join8(appRoot,HISTORY_LAST_RELATIVE_DIR)}function writeLastPlatformBlocksHistory(appRoot,args){let historyDir=getPlatformBlocksHistoryLastDir(appRoot);rmSync2(historyDir,{recursive:!0,force:!0}),mkdirSync6(join8(historyDir,"files"),{recursive:!0});for(let file of args.files){if(!file.existed_before||typeof file.content!="string")continue;let snapshotPath=join8(historyDir,"files",file.path);mkdirSync6(dirname8(snapshotPath),{recursive:!0}),writeFileSync7(snapshotPath,file.content,"utf8")}writeFileSync7(join8(historyDir,"lockfile.before.json"),args.lockfileBefore,"utf8"),writeFileSync7(join8(historyDir,"lockfile.after.json"),args.lockfileAfter,"utf8");let metadata={template_key:args.templateKey,platform_blocks_revision_before:args.revisionBefore,platform_blocks_revision_after:args.revisionAfter,managed_files_overwritten:args.files.map(file=>({path:file.path,existed_before:file.existed_before})),lockfile_before_path:"lockfile.before.json",lockfile_after_path:"lockfile.after.json",created_at:new Date().toISOString()};return writeFileSync7(join8(historyDir,"metadata.json"),`${JSON.stringify(metadata,null,2)}
2393
+ `,"utf8"),historyDir}function restoreLastPlatformBlocksHistory(appRoot){let historyDir=getPlatformBlocksHistoryLastDir(appRoot),metadataPath=join8(historyDir,"metadata.json");if(!existsSync12(metadataPath))throw new Error("\u65E0\u53EF\u56DE\u9000\u7684\u6700\u8FD1\u4E00\u6B21 apply\u3002");let metadata=JSON.parse(readFileSync12(metadataPath,"utf8")),restoredFiles=[],removedFiles=[];for(let file of metadata.managed_files_overwritten){let targetPath=join8(appRoot,file.path);if(!file.existed_before){rmSync2(targetPath,{force:!0}),removedFiles.push(file.path);continue}let snapshotPath=join8(historyDir,"files",file.path),content=readFileSync12(snapshotPath,"utf8");mkdirSync6(dirname8(targetPath),{recursive:!0}),writeFileSync7(targetPath,content,"utf8"),restoredFiles.push(file.path)}let lockfilePath=getPlatformBlocksLockfilePath(appRoot);return mkdirSync6(dirname8(lockfilePath),{recursive:!0}),writeFileSync7(lockfilePath,readFileSync12(join8(historyDir,metadata.lockfile_before_path),"utf8"),"utf8"),{restoredFiles,removedFiles,lockfilePath:relative2(appRoot,lockfilePath).replace(/\\/g,"/")}}function hasLastPlatformBlocksHistory(appRoot){return existsSync12(join8(getPlatformBlocksHistoryLastDir(appRoot),"metadata.json"))}var CLI_TOOL_VERSION=`@voobase/cli@${getCliPackageVersion()}`;function runAppSyncPlatformBlocksCommand(args){let{directory:appRoot}=readAppManifest(args.cwd);if(args.rollbackLast){let restored=restoreLastPlatformBlocksHistory(appRoot);return{mode:"rollback",appRoot,restoredFiles:restored.restoredFiles,removedFiles:restored.removedFiles,lockfilePath:restored.lockfilePath}}let templateKey=resolvePlatformBlocksTemplateKey(appRoot),manifest=getPlatformBlocksManifest(templateKey),templateFiles=buildTemplateFileMap(templateKey),lockRecord=readPlatformBlocksLockfile(appRoot);if(args.adopt){if(lockRecord)return{mode:"adopt",appRoot,templateKey,status:"already_managed",targetRevision:manifest.platform_blocks_revision,lockfilePath:lockRecord.path};let adopt=inspectPlatformBlocksAdoptability(appRoot,manifest);if(!adopt.adoptable){let problems=adopt.files.filter(file=>file.status!=="match").map(file=>`${file.path}=${file.status}`).join(", ");throw new Error(`\u5F53\u524D\u5DE5\u7A0B\u5C1A\u672A\u8FBE\u5230 adopt \u6761\u4EF6\uFF1A${problems}`)}let nextLockfile=buildPlatformBlocksLockfile(manifest,{mode:"adopt",toolVersion:CLI_TOOL_VERSION}),lockfilePath=writePlatformBlocksLockfile(appRoot,stringifyPlatformBlocksLockfile(nextLockfile));return{mode:"adopt",appRoot,templateKey,status:"adopted",targetRevision:manifest.platform_blocks_revision,lockfilePath}}if(args.apply){if(!lockRecord)throw new Error("\u7F3A\u5C11 `.platform/platform-blocks.lock.json`\uFF0C\u8BF7\u5148\u6267\u884C `platform app sync-platform-blocks --adopt`\u3002");let diff2=computePlatformBlocksDiff(appRoot,manifest,lockRecord.lockfile),outcome=determinePlatformBlocksApplyOutcome(diff2);if(outcome==="conflict"){let conflictList=diff2.filter(file=>file.status==="conflict").map(file=>file.path).join(", ");throw new Error(`\u68C0\u6D4B\u5230\u5E73\u53F0\u5757\u51B2\u7A81\uFF0C\u5DF2\u62D2\u7EDD apply\uFF1A${conflictList}`)}let nextLockfile=buildPlatformBlocksLockfile(manifest,{mode:outcome==="lock_refreshed"?"lock_refreshed":"apply",toolVersion:CLI_TOOL_VERSION}),nextLockfileRaw=stringifyPlatformBlocksLockfile(nextLockfile);if(outcome==="updated"){for(let file of diff2.filter(item=>item.status==="safe_remove"))assertSafeManagedRemovalPath(appRoot,templateKey,file.path);let snapshots=diff2.filter(file=>file.status==="safe_update"||file.status==="safe_remove").map(file=>buildHistorySnapshot(appRoot,file.path));for(let file of diff2.filter(item=>item.status==="safe_update")){let target=templateFiles.get(file.path);if(typeof target!="string")throw new Error(`\u6A21\u677F\u7F3A\u5C11\u76EE\u6807\u6587\u4EF6\uFF1A${file.path}`);writeManagedFile(appRoot,file.path,target)}for(let file of diff2.filter(item=>item.status==="safe_remove"))removeManagedFile(appRoot,file.path);writePlatformBlocksLockfile(appRoot,nextLockfileRaw),writeLastPlatformBlocksHistory(appRoot,{templateKey,revisionBefore:lockRecord.lockfile.platform_blocks_revision,revisionAfter:manifest.platform_blocks_revision,files:snapshots,lockfileBefore:lockRecord.raw,lockfileAfter:nextLockfileRaw});let verify2=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:outcome,targetRevision:manifest.platform_blocks_revision,updatedFiles:diff2.filter(file=>file.status==="safe_update").map(file=>file.path),removedFiles:diff2.filter(file=>file.status==="safe_remove").map(file=>file.path),lockfilePath:lockRecord.path,historyUpdated:!0,verify:verify2}}if(outcome==="lock_refreshed"){writePlatformBlocksLockfile(appRoot,nextLockfileRaw);let verify2=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:outcome,targetRevision:manifest.platform_blocks_revision,updatedFiles:[],removedFiles:[],lockfilePath:lockRecord.path,historyUpdated:!1,verify:verify2}}let verify=args.verify?runPlatformBlocksVerify(appRoot):void 0;return{mode:"apply",appRoot,templateKey,status:"noop",targetRevision:manifest.platform_blocks_revision,updatedFiles:[],removedFiles:[],lockfilePath:lockRecord.path,historyUpdated:!1,verify}}if(!lockRecord){let adopt=inspectPlatformBlocksAdoptability(appRoot,manifest);return{mode:"dry-run",appRoot,templateKey,targetRevision:manifest.platform_blocks_revision,managedFiles:manifest.managed_files.length,lockfilePresent:!1,adoptable:adopt.adoptable}}let diff=computePlatformBlocksDiff(appRoot,manifest,lockRecord.lockfile);return{mode:"dry-run",appRoot,templateKey,targetRevision:manifest.platform_blocks_revision,managedFiles:manifest.managed_files.length,lockfilePresent:!0,safeUpdates:diff.filter(file=>file.status==="safe_update").length,safeRemovals:diff.filter(file=>file.status==="safe_remove").length,lockRefreshes:diff.filter(file=>file.status==="lock_refresh").length,conflicts:diff.filter(file=>file.status==="conflict").length,noopFiles:diff.filter(file=>file.status==="noop").length}}function formatAppSyncPlatformBlocksResult(result){return result.mode==="rollback"?["\u5E73\u53F0\u5757\u5DF2\u56DE\u9000\u5230\u6700\u8FD1\u4E00\u6B21\u5FEB\u7167\u3002",`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,result.restoredFiles.length>0?`\u6062\u590D\u6587\u4EF6:
2393
2394
  - ${result.restoredFiles.join(`
2394
2395
  - `)}`:"\u6062\u590D\u6587\u4EF6: -",result.removedFiles.length>0?`\u5220\u9664\u6587\u4EF6:
2395
2396
  - ${result.removedFiles.join(`
@@ -2397,35 +2398,39 @@ ${routeMarker}`)}return next}function buildAuthDebugPageSource(){return["export
2397
2398
  `):result.mode==="adopt"?[result.status==="adopted"?"\u5E73\u53F0\u5757\u5DF2\u7EB3\u7BA1\u3002":"\u5F53\u524D\u5DE5\u7A0B\u5DF2\u7EB3\u7BA1\uFF0C\u65E0\u9700\u91CD\u590D adopt\u3002",`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,`\u6A21\u677F: ${result.templateKey}`,`target revision: ${result.targetRevision}`,`lockfile: ${result.lockfilePath}`,""].join(`
2398
2399
  `):result.mode==="apply"?[`\u5E73\u53F0\u5757 apply \u7ED3\u679C: ${result.status}`,`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,`\u6A21\u677F: ${result.templateKey}`,`target revision: ${result.targetRevision}`,result.updatedFiles.length>0?`\u66F4\u65B0\u6587\u4EF6:
2399
2400
  - ${result.updatedFiles.join(`
2400
- - `)}`:"\u66F4\u65B0\u6587\u4EF6: -",`lockfile: ${result.lockfilePath}`,`history: ${result.historyUpdated?"updated":"unchanged"}`,result.verify?formatPlatformBlocksVerifySummary(result.verify.output):"",""].join(`
2401
- `):["\u5E73\u53F0\u5757 dry-run \u7ED3\u679C",`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,`\u6A21\u677F: ${result.templateKey}`,`target revision: ${result.targetRevision}`,`managed files: ${result.managedFiles}`,`lockfile: ${result.lockfilePresent?"present":"missing"}`,typeof result.adoptable=="boolean"?`adoptable: ${result.adoptable?"yes":"no"}`:"",typeof result.safeUpdates=="number"?`safe updates: ${result.safeUpdates}`:"",typeof result.lockRefreshes=="number"?`lock refreshes: ${result.lockRefreshes}`:"",typeof result.conflicts=="number"?`conflicts: ${result.conflicts}`:"",typeof result.noopFiles=="number"?`noop files: ${result.noopFiles}`:"",hasLastPlatformBlocksHistory(result.appRoot)?"rollback last: available":"rollback last: unavailable",""].filter(Boolean).join(`
2402
- `)}function buildTemplateFileMap(templateKey){let files=templateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();return new Map(files.map(file=>[file.path,file.content]))}function buildHistorySnapshot(appRoot,relativePath){let absolutePath=join9(appRoot,relativePath);return existsSync13(absolutePath)?{path:relativePath,existed_before:!0,content:readFileSync13(absolutePath,"utf8")}:{path:relativePath,existed_before:!1}}function writeManagedFile(appRoot,relativePath,content){let absolutePath=join9(appRoot,relativePath);mkdirSync7(dirname9(absolutePath),{recursive:!0}),writeFileSync8(absolutePath,content,"utf8")}function runPlatformBlocksVerify(appRoot){let workspaceRoot=findWorkspaceRoot(appRoot),scriptPath=process.env.PLATFORM_BLOCKS_VERIFY_SCRIPT?.trim()||join9(workspaceRoot,"scripts","validation","url","local-url-gate.sh");try{return{status:"passed",output:execFileSync("bash",[scriptPath,"--mode","inspect"],{cwd:workspaceRoot,encoding:"utf8",env:process.env,maxBuffer:4194304}).trim()}}catch(error){let detail=error instanceof Error?error.message:String(error);throw new Error(`\u5E73\u53F0\u5757 verify \u5931\u8D25\uFF1A${detail}`)}}function formatPlatformBlocksVerifySummary(output){try{let parsed=JSON.parse(output),checks=Array.isArray(parsed.checks)?parsed.checks:[],passed=checks.filter(check=>check.status==="passed").length;return`verify: ${parsed.status??"passed"} mode=${parsed.mode??"inspect"} checks=${passed}/${checks.length}`}catch{return"verify: passed"}}import{cpSync,existsSync as existsSync15,mkdirSync as mkdirSync8,readFileSync as readFileSync15,rmSync as rmSync2,statSync as statSync4,writeFileSync as writeFileSync9}from"node:fs";import{join as join11,resolve as resolve7}from"node:path";import{existsSync as existsSync14,readFileSync as readFileSync14}from"node:fs";import{join as join10}from"node:path";var SOURCE_CONTEXT_PATH=join10(".platform","source-context.json");function readJsonIfExists(filePath){return existsSync14(filePath)?JSON.parse(readFileSync14(filePath,"utf8")):null}function detectTemplateKeyFromWorkspace(workspaceDir){let sourceContext=readJsonIfExists(join10(workspaceDir,SOURCE_CONTEXT_PATH));if(sourceContext?.template_key){let normalized=normalizeAppTemplateKey(sourceContext.template_key);if(normalized==="frontend-app-vite"||normalized==="backend-app-node")return normalized}return existsSync14(join10(workspaceDir,"src","web","app.tsx"))||existsSync14(join10(workspaceDir,"src","server","entry.ts"))?"backend-app-node":(existsSync14(join10(workspaceDir,"src","app.tsx"))||existsSync14(join10(workspaceDir,"src","main.tsx")),"frontend-app-vite")}function resolveAppImportLayout(workspaceDir){let templateKey=detectTemplateKeyFromWorkspace(workspaceDir),frontendRoot=templateKey==="backend-app-node"?"src/web":"src",importedUpstreamRoot=join10(frontendRoot,"imported-upstream").replace(/\\/g,"/"),preservedWorkspaceFiles=["app.yaml","package.json","vite.config.ts","index.html",`${frontendRoot}/main.tsx`,`${frontendRoot}/app.tsx`,`${frontendRoot}/platform`,"public/auth/index.html","public/__app"];return templateKey==="backend-app-node"&&preservedWorkspaceFiles.push("Dockerfile","src/server"),{template_key:templateKey,frontend_root:frontendRoot,imported_upstream_root:importedUpstreamRoot,preserved_workspace_files:preservedWorkspaceFiles}}var REQUIRED_WORKSPACE_FILES=["app.yaml","package.json"],FRONTEND_MERGEABLE_SOURCE_DIRS=["pages","components","styles","lib","imports"];function printAppImportMergeUsage(){process.stdout.write(["platform app import merge","","\u7528\u6CD5\uFF1A"," platform app import merge [--workspace-dir <template-workspace-dir>] [--dry-run] [--json]","","\u4F5C\u7528\uFF1A"," \u5C06 `.design-import/upstream-clean-source/` \u7684\u53EF\u8FC1\u79FB\u76EE\u5F55\u5B89\u5168\u5E76\u5165\u6A21\u677F\u5DE5\u4F5C\u533A\u7684 imported-upstream \u843D\u70B9\uFF0C\u4FDD\u7559\u6A21\u677F\u5165\u53E3\u4E0E\u5E73\u53F0\u5951\u7EA6\u6587\u4EF6\u7531\u6A21\u677F\u4E3B\u5BFC\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002",""].join(`
2401
+ - `)}`:"\u66F4\u65B0\u6587\u4EF6: -",result.removedFiles.length>0?`\u5220\u9664\u6587\u4EF6:
2402
+ - ${result.removedFiles.join(`
2403
+ - `)}`:"\u5220\u9664\u6587\u4EF6: -",`lockfile: ${result.lockfilePath}`,`history: ${result.historyUpdated?"updated":"unchanged"}`,result.verify?formatPlatformBlocksVerifySummary(result.verify.output):"",""].join(`
2404
+ `):["\u5E73\u53F0\u5757 dry-run \u7ED3\u679C",`\u5E94\u7528\u76EE\u5F55: ${result.appRoot}`,`\u6A21\u677F: ${result.templateKey}`,`target revision: ${result.targetRevision}`,`managed files: ${result.managedFiles}`,`lockfile: ${result.lockfilePresent?"present":"missing"}`,typeof result.adoptable=="boolean"?`adoptable: ${result.adoptable?"yes":"no"}`:"",typeof result.safeUpdates=="number"?`safe updates: ${result.safeUpdates}`:"",typeof result.safeRemovals=="number"?`safe removals: ${result.safeRemovals}`:"",typeof result.lockRefreshes=="number"?`lock refreshes: ${result.lockRefreshes}`:"",typeof result.conflicts=="number"?`conflicts: ${result.conflicts}`:"",typeof result.noopFiles=="number"?`noop files: ${result.noopFiles}`:"",hasLastPlatformBlocksHistory(result.appRoot)?"rollback last: available":"rollback last: unavailable",""].filter(Boolean).join(`
2405
+ `)}function buildTemplateFileMap(templateKey){let files=templateKey==="backend-app-node"?assembleBackendAppNodeTemplate():assembleFrontendAppViteTemplate();return new Map(files.map(file=>[file.path,file.content]))}function buildHistorySnapshot(appRoot,relativePath){let absolutePath=join9(appRoot,relativePath);return existsSync13(absolutePath)?{path:relativePath,existed_before:!0,content:readFileSync13(absolutePath,"utf8")}:{path:relativePath,existed_before:!1}}function writeManagedFile(appRoot,relativePath,content){let absolutePath=join9(appRoot,relativePath);mkdirSync7(dirname9(absolutePath),{recursive:!0}),writeFileSync8(absolutePath,content,"utf8")}function removeManagedFile(appRoot,relativePath){let absolutePath=resolve7(appRoot,relativePath);existsSync13(absolutePath)&&unlinkSync(absolutePath)}function assertSafeManagedRemovalPath(appRoot,templateKey,relativePath){let normalizedRoot=resolve7(appRoot),insideAppRoot=resolve7(normalizedRoot,relativePath).startsWith(`${normalizedRoot}${sep}`);if(isAbsolute(relativePath)||!insideAppRoot||!isManagedPlatformFilePath(templateKey,relativePath))throw new Error(`\u9501\u6587\u4EF6\u5305\u542B\u975E\u6CD5\u7684\u6258\u7BA1\u5220\u9664\u8DEF\u5F84\uFF0C\u5DF2\u62D2\u7EDD apply\uFF1A${relativePath}`)}function runPlatformBlocksVerify(appRoot){let workspaceRoot=findWorkspaceRoot(appRoot),scriptPath=process.env.PLATFORM_BLOCKS_VERIFY_SCRIPT?.trim()||join9(workspaceRoot,"scripts","validation","url","local-url-gate.sh");try{return{status:"passed",output:execFileSync("bash",[scriptPath,"--mode","inspect"],{cwd:workspaceRoot,encoding:"utf8",env:process.env,maxBuffer:4194304}).trim()}}catch(error){let detail=error instanceof Error?error.message:String(error);throw new Error(`\u5E73\u53F0\u5757 verify \u5931\u8D25\uFF1A${detail}`)}}function formatPlatformBlocksVerifySummary(output){try{let parsed=JSON.parse(output),checks=Array.isArray(parsed.checks)?parsed.checks:[],passed=checks.filter(check=>check.status==="passed").length;return`verify: ${parsed.status??"passed"} mode=${parsed.mode??"inspect"} checks=${passed}/${checks.length}`}catch{return"verify: passed"}}import{cpSync,existsSync as existsSync15,mkdirSync as mkdirSync8,readFileSync as readFileSync15,rmSync as rmSync3,statSync as statSync4,writeFileSync as writeFileSync9}from"node:fs";import{join as join11,resolve as resolve8}from"node:path";import{existsSync as existsSync14,readFileSync as readFileSync14}from"node:fs";import{join as join10}from"node:path";var SOURCE_CONTEXT_PATH=join10(".platform","source-context.json");function readJsonIfExists(filePath){return existsSync14(filePath)?JSON.parse(readFileSync14(filePath,"utf8")):null}function detectTemplateKeyFromWorkspace(workspaceDir){let sourceContext=readJsonIfExists(join10(workspaceDir,SOURCE_CONTEXT_PATH));if(sourceContext?.template_key){let normalized=normalizeAppTemplateKey(sourceContext.template_key);if(normalized==="frontend-app-vite"||normalized==="backend-app-node")return normalized}return existsSync14(join10(workspaceDir,"src","web","app.tsx"))||existsSync14(join10(workspaceDir,"src","server","entry.ts"))?"backend-app-node":(existsSync14(join10(workspaceDir,"src","app.tsx"))||existsSync14(join10(workspaceDir,"src","main.tsx")),"frontend-app-vite")}function resolveAppImportLayout(workspaceDir){let templateKey=detectTemplateKeyFromWorkspace(workspaceDir),frontendRoot=templateKey==="backend-app-node"?"src/web":"src",importedUpstreamRoot=join10(frontendRoot,"imported-upstream").replace(/\\/g,"/"),preservedWorkspaceFiles=["app.yaml","package.json","vite.config.ts","index.html",`${frontendRoot}/main.tsx`,`${frontendRoot}/app.tsx`,`${frontendRoot}/platform`,"public/auth/index.html","public/__app"];return templateKey==="backend-app-node"&&preservedWorkspaceFiles.push("Dockerfile","src/server"),{template_key:templateKey,frontend_root:frontendRoot,imported_upstream_root:importedUpstreamRoot,preserved_workspace_files:preservedWorkspaceFiles}}var REQUIRED_WORKSPACE_FILES=["app.yaml","package.json"],FRONTEND_MERGEABLE_SOURCE_DIRS=["pages","components","styles","lib","imports"];function printAppImportMergeUsage(){process.stdout.write(["platform app import merge","","\u7528\u6CD5\uFF1A"," platform app import merge [--workspace-dir <template-workspace-dir>] [--dry-run] [--json]","","\u4F5C\u7528\uFF1A"," \u5C06 `.design-import/upstream-clean-source/` \u7684\u53EF\u8FC1\u79FB\u76EE\u5F55\u5B89\u5168\u5E76\u5165\u6A21\u677F\u5DE5\u4F5C\u533A\u7684 imported-upstream \u843D\u70B9\uFF0C\u4FDD\u7559\u6A21\u677F\u5165\u53E3\u4E0E\u5E73\u53F0\u5951\u7EA6\u6587\u4EF6\u7531\u6A21\u677F\u4E3B\u5BFC\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002",""].join(`
2403
2406
  `))}function parseArgs(argv){let result={workspaceDir:"",dryRun:!1,json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--dry-run"){result.dryRun=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--workspace-dir"){result.workspaceDir=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function readJson(filePath){return JSON.parse(readFileSync15(filePath,"utf8"))}function writeJson(filePath,payload){writeFileSync9(filePath,`${JSON.stringify(payload,null,2)}
2404
- `,"utf8")}function assertDirectory(pathValue,label){let stats=statSync4(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function validateWorkspace(workspaceDir){assertDirectory(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=REQUIRED_WORKSPACE_FILES.filter(file=>!existsSync15(join11(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function buildMergeSummary(args,payload){let sourcePreprocessExecutionMode=payload.importSummary.source_preprocess_execution_mode||payload.importManifest.execution_mode||"unknown",warnings=[];return sourcePreprocessExecutionMode==="dry-run"&&warnings.push("\u5F53\u524D merge \u6765\u6E90\u4E8E dry-run \u9884\u5904\u7406\u4EA7\u7269\uFF1Bsrc/imported-upstream/ \u4E2D\u4ECD\u53EF\u80FD\u5305\u542B\u672A\u6E05\u7406\u7684\u672C\u5730\u7D20\u6750\u3002"),{tool:"merge-imported-upstream",version:1,mode:"merge-stage",execution_mode:args.dryRun?"dry-run":"apply",workspace_dir:payload.workspaceDir,import_summary:payload.importSummaryPath,source_preprocess_execution_mode:sourcePreprocessExecutionMode,target_template_key:payload.layout.template_key,frontend_root:payload.layout.frontend_root,upstream_clean_source_dir:payload.upstreamCleanSourceDir,merged_target_dir:payload.mergedTargetDir,merge_required:payload.mergeRequired,merged_paths:payload.mergedPaths,skipped_paths:payload.skippedPaths,preserved_workspace_files:payload.importSummary.preserved_workspace_files??[],warnings,next_steps:[`\u5728 ${payload.layout.imported_upstream_root}/ \u4E2D\u5BA1\u67E5\u4E0A\u6E38\u9875\u9762\u3001components\u3001styles\u3001lib\u3001imports`,payload.layout.template_key==="backend-app-node"?"\u4ECE src/web/app.tsx \u6216 src/web/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9\uFF0C\u4FDD\u6301 src/server/* \u4E0E src/web/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC":"\u4ECE src/app.tsx \u6216 src/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9\uFF0C\u4FDD\u6301 src/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC","\u9010\u6B65\u628A\u9700\u8981\u7684\u5E73\u53F0\u80FD\u529B\u63A5\u5165\u5230\u6A21\u677F\u4E3B\u5BFC\u7684\u8FD0\u884C\u5165\u53E3\u4E2D","\u5B8C\u6210\u63A5\u7EBF\u540E\uFF0C\u518D\u6267\u884C platform dev / verify / preview"]}}async function runAppImportMergeCli(argv){let args=parseArgs(argv);if(args.help){printAppImportMergeUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");let workspaceDir=resolve7(args.workspaceDir);validateWorkspace(workspaceDir);let designImportRoot=join11(workspaceDir,".design-import"),importSummaryPath=join11(designImportRoot,"import-summary.json"),importManifestPath=join11(designImportRoot,"reports","import-manifest.json"),upstreamCleanSourceDir=join11(designImportRoot,"upstream-clean-source");assertDirectory(designImportRoot,".design-import"),assertDirectory(upstreamCleanSourceDir,"upstream-clean-source");let importSummary=readJson(importSummaryPath),importManifest=existsSync15(importManifestPath)?readJson(importManifestPath):{},layout=resolveAppImportLayout(workspaceDir),mergedTargetDir=join11(workspaceDir,...layout.imported_upstream_root.split("/")),upstreamSrcDir=join11(upstreamCleanSourceDir,"src"),upstreamPublicDir=join11(upstreamCleanSourceDir,"public"),mergedPublicTargetDir=join11(workspaceDir,"public","imported-upstream"),mergeRequired=!0,upstreamSrcExists=!!statSync4(upstreamSrcDir,{throwIfNoEntry:!1})?.isDirectory(),upstreamPublicExists=!!statSync4(upstreamPublicDir,{throwIfNoEntry:!1})?.isDirectory();importSummary.source_detected_type==="frontend-app"&&assertDirectory(upstreamSrcDir,"upstream clean-source/src");let mergedPaths=[],skippedPaths=[];if(args.dryRun||(rmSync2(mergedTargetDir,{recursive:!0,force:!0}),rmSync2(mergedPublicTargetDir,{recursive:!0,force:!0}),mkdirSync8(mergedTargetDir,{recursive:!0})),importSummary.source_detected_type==="frontend-app"&&upstreamSrcExists)for(let name of FRONTEND_MERGEABLE_SOURCE_DIRS){let sourcePath=join11(upstreamSrcDir,name),sourceStats=statSync4(sourcePath,{throwIfNoEntry:!1});if(!sourceStats||!sourceStats.isDirectory()){skippedPaths.push(`src/${name}`);continue}let targetPath=join11(mergedTargetDir,name);mergedPaths.push({source:`src/${name}`,target:`${layout.imported_upstream_root}/${name}`}),args.dryRun||cpSync(sourcePath,targetPath,{recursive:!0})}else importSummary.source_detected_type==="frontend-app"?skippedPaths.push("src/: upstream clean-source does not contain mergeable frontend source"):skippedPaths.push("src/: static-site upstream does not require frontend source merge");upstreamPublicExists?(mergedPaths.push({source:"public",target:"public/imported-upstream"}),args.dryRun||(mkdirSync8(join11(workspaceDir,"public"),{recursive:!0}),cpSync(upstreamPublicDir,mergedPublicTargetDir,{recursive:!0}))):skippedPaths.push("public");let summary=buildMergeSummary(args,{workspaceDir,importSummaryPath,importSummary,importManifest,layout,upstreamCleanSourceDir,mergedTargetDir,mergeRequired,mergedPaths,skippedPaths});if(args.dryRun||writeJson(join11(designImportRoot,"merge-summary.json"),summary),args.json){process.stdout.write(`${JSON.stringify(summary,null,2)}
2407
+ `,"utf8")}function assertDirectory(pathValue,label){let stats=statSync4(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function validateWorkspace(workspaceDir){assertDirectory(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=REQUIRED_WORKSPACE_FILES.filter(file=>!existsSync15(join11(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function buildMergeSummary(args,payload){let sourcePreprocessExecutionMode=payload.importSummary.source_preprocess_execution_mode||payload.importManifest.execution_mode||"unknown",warnings=[];return sourcePreprocessExecutionMode==="dry-run"&&warnings.push("\u5F53\u524D merge \u6765\u6E90\u4E8E dry-run \u9884\u5904\u7406\u4EA7\u7269\uFF1Bsrc/imported-upstream/ \u4E2D\u4ECD\u53EF\u80FD\u5305\u542B\u672A\u6E05\u7406\u7684\u672C\u5730\u7D20\u6750\u3002"),{tool:"merge-imported-upstream",version:1,mode:"merge-stage",execution_mode:args.dryRun?"dry-run":"apply",workspace_dir:payload.workspaceDir,import_summary:payload.importSummaryPath,source_preprocess_execution_mode:sourcePreprocessExecutionMode,target_template_key:payload.layout.template_key,frontend_root:payload.layout.frontend_root,upstream_clean_source_dir:payload.upstreamCleanSourceDir,merged_target_dir:payload.mergedTargetDir,merge_required:payload.mergeRequired,merged_paths:payload.mergedPaths,skipped_paths:payload.skippedPaths,preserved_workspace_files:payload.importSummary.preserved_workspace_files??[],warnings,next_steps:[`\u5728 ${payload.layout.imported_upstream_root}/ \u4E2D\u5BA1\u67E5\u4E0A\u6E38\u9875\u9762\u3001components\u3001styles\u3001lib\u3001imports`,payload.layout.template_key==="backend-app-node"?"\u4ECE src/web/app.tsx \u6216 src/web/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9\uFF0C\u4FDD\u6301 src/server/* \u4E0E src/web/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC":"\u4ECE src/app.tsx \u6216 src/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9\uFF0C\u4FDD\u6301 src/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC","\u9010\u6B65\u628A\u9700\u8981\u7684\u5E73\u53F0\u80FD\u529B\u63A5\u5165\u5230\u6A21\u677F\u4E3B\u5BFC\u7684\u8FD0\u884C\u5165\u53E3\u4E2D","\u5B8C\u6210\u63A5\u7EBF\u540E\uFF0C\u518D\u6267\u884C platform dev / verify / preview"]}}async function runAppImportMergeCli(argv){let args=parseArgs(argv);if(args.help){printAppImportMergeUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");let workspaceDir=resolve8(args.workspaceDir);validateWorkspace(workspaceDir);let designImportRoot=join11(workspaceDir,".design-import"),importSummaryPath=join11(designImportRoot,"import-summary.json"),importManifestPath=join11(designImportRoot,"reports","import-manifest.json"),upstreamCleanSourceDir=join11(designImportRoot,"upstream-clean-source");assertDirectory(designImportRoot,".design-import"),assertDirectory(upstreamCleanSourceDir,"upstream-clean-source");let importSummary=readJson(importSummaryPath),importManifest=existsSync15(importManifestPath)?readJson(importManifestPath):{},layout=resolveAppImportLayout(workspaceDir),mergedTargetDir=join11(workspaceDir,...layout.imported_upstream_root.split("/")),upstreamSrcDir=join11(upstreamCleanSourceDir,"src"),upstreamPublicDir=join11(upstreamCleanSourceDir,"public"),mergedPublicTargetDir=join11(workspaceDir,"public","imported-upstream"),mergeRequired=!0,upstreamSrcExists=!!statSync4(upstreamSrcDir,{throwIfNoEntry:!1})?.isDirectory(),upstreamPublicExists=!!statSync4(upstreamPublicDir,{throwIfNoEntry:!1})?.isDirectory();importSummary.source_detected_type==="frontend-app"&&assertDirectory(upstreamSrcDir,"upstream clean-source/src");let mergedPaths=[],skippedPaths=[];if(args.dryRun||(rmSync3(mergedTargetDir,{recursive:!0,force:!0}),rmSync3(mergedPublicTargetDir,{recursive:!0,force:!0}),mkdirSync8(mergedTargetDir,{recursive:!0})),importSummary.source_detected_type==="frontend-app"&&upstreamSrcExists)for(let name of FRONTEND_MERGEABLE_SOURCE_DIRS){let sourcePath=join11(upstreamSrcDir,name),sourceStats=statSync4(sourcePath,{throwIfNoEntry:!1});if(!sourceStats||!sourceStats.isDirectory()){skippedPaths.push(`src/${name}`);continue}let targetPath=join11(mergedTargetDir,name);mergedPaths.push({source:`src/${name}`,target:`${layout.imported_upstream_root}/${name}`}),args.dryRun||cpSync(sourcePath,targetPath,{recursive:!0})}else importSummary.source_detected_type==="frontend-app"?skippedPaths.push("src/: upstream clean-source does not contain mergeable frontend source"):skippedPaths.push("src/: static-site upstream does not require frontend source merge");upstreamPublicExists?(mergedPaths.push({source:"public",target:"public/imported-upstream"}),args.dryRun||(mkdirSync8(join11(workspaceDir,"public"),{recursive:!0}),cpSync(upstreamPublicDir,mergedPublicTargetDir,{recursive:!0}))):skippedPaths.push("public");let summary=buildMergeSummary(args,{workspaceDir,importSummaryPath,importSummary,importManifest,layout,upstreamCleanSourceDir,mergedTargetDir,mergeRequired,mergedPaths,skippedPaths});if(args.dryRun||writeJson(join11(designImportRoot,"merge-summary.json"),summary),args.json){process.stdout.write(`${JSON.stringify(summary,null,2)}
2405
2408
  `);return}process.stdout.write(["third-party design merge stage completed",`execution_mode: ${summary.execution_mode}`,`workspace_dir: ${summary.workspace_dir}`,`merged_target_dir: ${summary.merged_target_dir}`,`merged_paths: ${summary.merged_paths.length}`,`skipped_paths: ${summary.skipped_paths.length}`,`warnings: ${summary.warnings.length}`].join(`
2406
2409
  `)+`
2407
- `)}import{createHash as createHash5}from"node:crypto";import{cpSync as cpSync2,existsSync as existsSync16,mkdtempSync as mkdtempSync2,mkdirSync as mkdirSync9,readFileSync as readFileSync16,readdirSync as readdirSync5,rmSync as rmSync3,statSync as statSync5,unlinkSync,writeFileSync as writeFileSync10}from"node:fs";import{spawn as spawn3,spawnSync}from"node:child_process";import{basename as basename2,dirname as dirname10,extname as extname2,join as join12,relative as relative3,resolve as resolve8}from"node:path";import{tmpdir as tmpdir2}from"node:os";var DEFAULT_INCLUDE_EXTENSIONS=new Set([".html",".css",".js",".jsx",".ts",".tsx",".vue",".svelte"]),DEFAULT_SKIP_DIRS=new Set([".git","node_modules","dist","build",".next",".nuxt","coverage",".platform",".sandbox",".design-preprocess",".third-party-design-reports"]),IMAGE_HOST_HINTS=["unsplash.com","images.unsplash.com","googleusercontent.com","lh3.googleusercontent.com"],IMAGE_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".avif",".bmp",".ico"]),VIDEO_EXTENSIONS=new Set([".mp4",".webm",".mov",".m4v",".avi",".mkv"]),HTTPS_FORCE_HOST_SUFFIXES=["21epub.com"],URL_PATTERN=/https?:\/\/[^\s"'`)>\]]+/giu,LOCAL_ASSET_REF_PATTERN=/["'`](\.{1,2}\/[^"'`]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))["'`]/giu,CSS_URL_PATTERN=/url\((['"]?)(\.{1,2}\/[^)'"]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))\1\)/giu,IMPORT_LOCAL_ASSET_PATTERN=/^(\s*)import\s+([A-Za-z_$][\w$]*)\s+from\s+(["'])(\.{1,2}\/[^"'`\n]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))\3;?(\s*)$/gmu,LOCAL_IMAGE_UPLOAD_MAX_WIDTH=2048,PREFLIGHT_LOCAL_ASSET_WARN_BYTES=5*1024*1024,CACHE_VERSION=1,REMOTE_IMAGE_CONCURRENCY=3;function logProgress(message){process.stderr.write(`[app import preprocess] ${message}
2410
+ `)}import{createHash as createHash5}from"node:crypto";import{cpSync as cpSync2,existsSync as existsSync16,mkdtempSync as mkdtempSync3,mkdirSync as mkdirSync9,readFileSync as readFileSync16,readdirSync as readdirSync5,rmSync as rmSync4,statSync as statSync5,unlinkSync as unlinkSync2,writeFileSync as writeFileSync10}from"node:fs";import{spawn,spawnSync}from"node:child_process";import{basename as basename3,dirname as dirname10,extname as extname2,join as join12,relative as relative3,resolve as resolve9}from"node:path";import{tmpdir as tmpdir2}from"node:os";var DEFAULT_INCLUDE_EXTENSIONS=new Set([".html",".css",".js",".jsx",".ts",".tsx",".vue",".svelte"]),DEFAULT_SKIP_DIRS=new Set([".git","node_modules","dist","build",".next",".nuxt","coverage",".platform",".sandbox",".design-preprocess",".third-party-design-reports"]),IMAGE_HOST_HINTS=["unsplash.com","images.unsplash.com","googleusercontent.com","lh3.googleusercontent.com"],IMAGE_EXTENSIONS=new Set([".png",".jpg",".jpeg",".gif",".webp",".svg",".avif",".bmp",".ico"]),VIDEO_EXTENSIONS=new Set([".mp4",".webm",".mov",".m4v",".avi",".mkv"]),HTTPS_FORCE_HOST_SUFFIXES=["21epub.com"],URL_PATTERN=/https?:\/\/[^\s"'`)>\]]+/giu,LOCAL_ASSET_REF_PATTERN=/["'`](\.{1,2}\/[^"'`]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))["'`]/giu,CSS_URL_PATTERN=/url\((['"]?)(\.{1,2}\/[^)'"]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))\1\)/giu,IMPORT_LOCAL_ASSET_PATTERN=/^(\s*)import\s+([A-Za-z_$][\w$]*)\s+from\s+(["'])(\.{1,2}\/[^"'`\n]+?\.(?:png|jpg|jpeg|gif|webp|svg|avif|bmp|ico))\3;?(\s*)$/gmu,LOCAL_IMAGE_UPLOAD_MAX_WIDTH=2048,PREFLIGHT_LOCAL_ASSET_WARN_BYTES=5*1024*1024,CACHE_VERSION=1,REMOTE_IMAGE_CONCURRENCY=3;function logProgress(message){process.stderr.write(`[app import preprocess] ${message}
2408
2411
  `)}async function runWithConcurrency(items,concurrency,worker){let limit=Math.max(1,concurrency),results=new Array(items.length),nextIndex=0;async function consume(){for(;;){let currentIndex=nextIndex;if(nextIndex+=1,currentIndex>=items.length)return;results[currentIndex]=await worker(items[currentIndex],currentIndex)}}let runners=Array.from({length:Math.min(limit,items.length)},()=>consume());return await Promise.all(runners),results}function printAppImportPreprocessUsage(){process.stdout.write(["platform app import preprocess","","\u7528\u6CD5\uFF1A"," platform app import preprocess [--dir <third-party-source-dir>] [--dry-run] [--json]"," platform app import preprocess --dir <third-party-source-dir> --folder-id <asset-folder-id>","","\u4F5C\u7528\uFF1A"," \u626B\u63CF\u7B2C\u4E09\u65B9\u8BBE\u8BA1\u6E90\u7801\u5305\uFF0C\u505A\u7D20\u6750\u4E0A\u4F20\u56DE\u5199\u3001clean-source \u751F\u6210\u3001path-base \u57FA\u7840\u4FEE\u6B63\u4E0E\u9884\u5904\u7406\u62A5\u544A\u8F93\u51FA\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u7B49\u4EF7\u4E8E\u5728\u5F53\u524D\u76EE\u5F55\u6267\u884C\u9884\u5904\u7406\uFF1B\u82E5\u672A\u4F20 `--dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002"," - \u9ED8\u8BA4\u4F1A\u590D\u7528 `.design-preprocess/cache/` \u4E2D\u5DF2\u6210\u529F\u4E0A\u4F20\u7684\u7D20\u6750\u6620\u5C04\uFF1B\u82E5\u9700\u5FFD\u7565\u7F13\u5B58\u91CD\u8DD1\uFF0C\u53EF\u663E\u5F0F\u4F20 `--reset-cache`\u3002",""].join(`
2409
- `))}function parseArgs2(argv){let result={dir:"",include:new Set(DEFAULT_INCLUDE_EXTENSIONS),folderId:"",type:"auto",dryRun:!1,resume:!0,resetCache:!1,cliCmd:process.env.PLATFORM_CLI_CMD?.trim()||"platform",localReport:"",json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--dry-run"){result.dryRun=!0;continue}if(arg==="--resume"){result.resume=!0;continue}if(arg==="--reset-cache"){result.resetCache=!0;continue}if(arg==="--dir"){result.dir=argv[index+1]??"",index+=1;continue}if(arg==="--include"){let raw=argv[index+1]??"";index+=1,result.include=normalizeInclude(raw);continue}if(arg==="--folder-id"){result.folderId=argv[index+1]??"",index+=1;continue}if(arg==="--type"){result.type=argv[index+1]??result.type,index+=1;continue}if(arg==="--cli-cmd"){result.cliCmd=argv[index+1]??result.cliCmd,index+=1;continue}if(arg==="--local-report"){result.localReport=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function normalizeInclude(raw){let values=raw.split(",").map(item=>item.trim().toLowerCase()).filter(Boolean).map(item=>item.startsWith(".")?item:`.${item}`);return values.length>0?new Set(values):new Set(DEFAULT_INCLUDE_EXTENSIONS)}function buildRemoteCacheKey(url){return`remote:${url}`}function buildLocalCacheKey(contentHash){return`local:${contentHash}`}function defaultAssetCache(sourceDir){return{version:CACHE_VERSION,source_dir:sourceDir,entries:{}}}function defaultLockState(){return{version:CACHE_VERSION,active_run_id:null,started_at:null,phase:null,in_progress_keys:[],last_interrupted_at:null}}function readJsonIfExists2(filePath,fallbackValue){if(!existsSync16(filePath))return fallbackValue;try{return JSON.parse(readFileSync16(filePath,"utf8"))}catch{return fallbackValue}}function loadAssetCache(cacheFile,sourceDir){let loaded=readJsonIfExists2(cacheFile,defaultAssetCache(sourceDir));return{version:CACHE_VERSION,source_dir:loaded.source_dir||sourceDir,entries:loaded.entries&&typeof loaded.entries=="object"?loaded.entries:{}}}function persistAssetCache(cacheFile,payload){ensureDir(dirname10(cacheFile)),writeJson2(cacheFile,payload)}function loadLockState(lockFile){let loaded=readJsonIfExists2(lockFile,defaultLockState());return{version:CACHE_VERSION,active_run_id:loaded.active_run_id??null,started_at:loaded.started_at??null,phase:loaded.phase??null,in_progress_keys:Array.isArray(loaded.in_progress_keys)?loaded.in_progress_keys:[],last_interrupted_at:loaded.last_interrupted_at??null}}function persistLockState(lockFile,payload){ensureDir(dirname10(lockFile)),writeJson2(lockFile,payload)}function beginLockRun(lockFile,previousLock){let interruptedItems=previousLock.active_run_id?previousLock.in_progress_keys.length:0,next={version:CACHE_VERSION,active_run_id:`preprocess-${Date.now()}`,started_at:new Date().toISOString(),phase:"scan",in_progress_keys:[],last_interrupted_at:previousLock.active_run_id?new Date().toISOString():previousLock.last_interrupted_at};return persistLockState(lockFile,next),{lock:next,interruptedItems}}function updateLockState(lockFile,currentLock,patch){let next={...currentLock,...patch};return persistLockState(lockFile,next),next}function completeLockRun(lockFile,currentLock){let next={...currentLock,active_run_id:null,phase:"completed",in_progress_keys:[]};return persistLockState(lockFile,next),next}function cacheEntryReusable(entry){return!!(entry&&typeof entry.final_url=="string"&&entry.final_url.trim()&&entry.asset_id&&entry.status!=="failed")}function updateCacheEntry(cache,cacheKey,patch){cache.entries[cacheKey]={...cache.entries[cacheKey]??{},...patch,updated_at:new Date().toISOString()}}function walkFiles(rootDir,includeExtensions){let files=[];function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;visit(fullPath);continue}if(!entry.isFile())continue;let extension=extname2(entry.name).toLowerCase();includeExtensions.has(extension)&&files.push(fullPath)}}return visit(rootDir),files.sort((left,right)=>left.localeCompare(right))}function walkAssetFiles(rootDir){let files=[];function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;visit(fullPath);continue}if(!entry.isFile())continue;let extension=extname2(entry.name).toLowerCase();IMAGE_EXTENSIONS.has(extension)&&files.push(fullPath)}}return visit(rootDir),files.sort((left,right)=>left.localeCompare(right))}function normalizeMatchedUrl(rawUrl){return rawUrl.replace(/[),.;]+$/u,"").replace(/^(&quot;?|&#34;?|&apos;?|&#39;?)+/iu,"").replace(/(&quot;?|&#34;?|&apos;?|&#39;?)+$/iu,"").replace(/&amp;/giu,"&")}function findLineNumber(text2,offset){let line=1;for(let index=0;index<offset;index+=1)text2.charCodeAt(index)===10&&(line+=1);return line}function inferExtensionFromUrl(url){try{let parsed=new URL(url);return extname2(parsed.pathname).toLowerCase()}catch{return extname2(url).toLowerCase()}}function classifyUrl(url,surroundingText){let lowerUrl=url.toLowerCase(),extension=inferExtensionFromUrl(lowerUrl),lowerContext=surroundingText.toLowerCase(),nonImageContext=lowerContext.includes("<script")||lowerContext.includes("script src")||lowerContext.includes('rel="stylesheet"')||lowerContext.includes("rel='stylesheet'")||lowerContext.includes("xmlns="),nonImageUrl=lowerUrl.includes("cdn.tailwindcss.com")||lowerUrl.includes("fonts.googleapis.com")||lowerUrl.includes("fonts.gstatic.com")||lowerUrl.includes("w3.org/2000/svg");return lowerContext.includes("poster")?"poster":VIDEO_EXTENSIONS.has(extension)?"video":nonImageContext||nonImageUrl||extension===".js"||extension===".mjs"||extension===".css"?"unknown_remote":IMAGE_EXTENSIONS.has(extension)||IMAGE_HOST_HINTS.some(item=>lowerUrl.includes(item))||lowerContext.includes("<img")||lowerContext.includes("background-image")||lowerContext.includes("url(")?"image":"unknown_remote"}function computeRewriteSupported(kind){return kind==="image"}function compactContext(value){return value.replace(/\s+/gu," ").trim().slice(0,200)}function kindPriority(kind){switch(kind){case"video":return 4;case"poster":return 3;case"image":return 2;default:return 1}}function collectRemoteCandidates(rootDir,files){let byUrl=new Map;for(let filePath of files){let raw=readFileSync16(filePath,"utf8");for(let match2 of raw.matchAll(URL_PATTERN)){let matched=match2[0],offset=match2.index??0,url=normalizeMatchedUrl(matched),line=findLineNumber(raw,offset),surroundingText=raw.slice(Math.max(0,offset-80),Math.min(raw.length,offset+url.length+80)),kind=classifyUrl(url,surroundingText),occurrence={file:relative3(rootDir,filePath),line,kind,context:compactContext(surroundingText)},existing=byUrl.get(url);if(existing){existing.occurrences.push(occurrence),kindPriority(kind)>kindPriority(existing.kind)&&(existing.kind=kind,existing.rewrite_supported=computeRewriteSupported(kind));continue}byUrl.set(url,{url,kind,rewrite_supported:computeRewriteSupported(kind),occurrences:[occurrence],notes:kind==="video"?["\u5F53\u524D\u7B2C\u4E00\u7248\u4EC5\u626B\u63CF\uFF0C\u4E0D\u81EA\u52A8\u56DE\u5199\u89C6\u9891\u3002"]:[]})}}return[...byUrl.values()].sort((left,right)=>left.url.localeCompare(right.url))}function buildReport(rootDir,files,candidates,reportDir=join12(rootDir,".third-party-design-reports")){let byKind=candidates.reduce((accumulator,item)=>(accumulator[item.kind]=(accumulator[item.kind]??0)+1,accumulator),{}),pendingManualItems=candidates.filter(item=>item.rewrite_supported!==!0);return{tool:"assetize-project-urls",version:1,mode:"scan",project_dir:rootDir,scanned_files:files.map(file=>relative3(rootDir,file)),summary:{scanned_file_count:files.length,unique_remote_candidates:candidates.length,image_count:byKind.image??0,video_count:byKind.video??0,poster_count:byKind.poster??0,unknown_remote_count:byKind.unknown_remote??0},remote_candidates:candidates,pending_videos:candidates.filter(item=>item.kind==="video"),pending_manual_items:pendingManualItems,report_dir:reportDir}}function hashFileContent(filePath){let content=readFileSync16(filePath);return createHash5("sha256").update(content).digest("hex")}function collectReferencedLocalAssetPaths(sourceFilePath,sourceText){let found=new Set;for(let match2 of sourceText.matchAll(LOCAL_ASSET_REF_PATTERN))found.add(resolve8(dirname10(sourceFilePath),match2[1]));for(let match2 of sourceText.matchAll(CSS_URL_PATTERN))found.add(resolve8(dirname10(sourceFilePath),match2[2]));return found}function collectLocalAssetCandidates(rootDir,sourceFiles,assetFiles){let assetPathSet=new Set(assetFiles.map(filePath=>resolve8(filePath))),byHash=new Map,referencedAssets=new Map;for(let sourceFilePath of sourceFiles){let raw=readFileSync16(sourceFilePath,"utf8"),refs=collectReferencedLocalAssetPaths(sourceFilePath,raw);for(let absoluteRef of refs){if(!assetPathSet.has(absoluteRef))continue;let existing=referencedAssets.get(absoluteRef);if(existing){existing.referenced_by.push(relative3(rootDir,sourceFilePath));continue}referencedAssets.set(absoluteRef,{absolute_path:absoluteRef,relative_path:relative3(rootDir,absoluteRef),referenced_by:[relative3(rootDir,sourceFilePath)]})}}for(let asset of referencedAssets.values()){let stats=statSync5(asset.absolute_path),contentHash=hashFileContent(asset.absolute_path),existing=byHash.get(contentHash);if(existing){existing.source_paths.push(asset.relative_path),existing.referenced_by.push(...asset.referenced_by);continue}byHash.set(contentHash,{hash:contentHash,path:asset.relative_path,source_paths:[asset.relative_path],file_name:basename2(asset.absolute_path),size_bytes:stats.size,kind:"local_image",upload_supported:!0,referenced_by:[...asset.referenced_by]})}return[...byHash.values()].sort((left,right)=>left.path.localeCompare(right.path))}function detectProjectType(rootDir,requestedType="auto"){return requestedType==="static-site"||requestedType==="frontend-app"?requestedType:existsSync16(join12(rootDir,"package.json"))?"frontend-app":"static-site"}function collectPathBaseViolations(rootDir,files){let violations=[],textFilePattern=/\.(?:[cm]?[jt]sx?|html?|css)$/i,patterns=[{kind:"root_relative_fetch",regex:/\bfetch\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_href",regex:/\bhref\s*=\s*['"]\/(?!\/)/g},{kind:"root_relative_src",regex:/\bsrc\s*=\s*['"]\/(?!\/)/g}];for(let filePath of files){let relativePath=relative3(rootDir,filePath);if(!textFilePattern.test(relativePath))continue;let lines=readFileSync16(filePath,"utf8").split(/\r?\n/u);for(let index=0;index<lines.length;index+=1){let line=lines[index];for(let pattern of patterns)pattern.regex.lastIndex=0,pattern.regex.test(line)&&violations.push({file:relativePath,line:index+1,kind:pattern.kind,snippet:line.trim().slice(0,180)})}}return violations}function toPosixPath(value){return value.replace(/\\/gu,"/")}function ensureDotRelativePath(value){return value===""||value==="."?"./":value.startsWith("./")||value.startsWith("../")?value:`./${value}`}function resolveRootRelativePathForFile(rootDir,filePath,rootRelativePath){let normalizedTarget=rootRelativePath.replace(/^\/+/u,""),targetPath=join12(rootDir,normalizedTarget),relativePath=relative3(dirname10(filePath),targetPath);return ensureDotRelativePath(toPosixPath(relativePath))}function rewritePathBaseRefsInContent(rootDir,filePath,content){let changed=!1,rewrites=[],patterns=[{regex:/\b(src|href)\s*=\s*(["'])\/(?!\/)([^"'`]+)\2/gu,buildReplacement(attrName,quote,rawPath){let nextPath=resolveRootRelativePathForFile(rootDir,filePath,rawPath);return rewrites.push({kind:"attribute",attr:attrName,from:`/${rawPath}`,to:nextPath}),`${attrName}=${quote}${nextPath}${quote}`}},{regex:/\bfetch\(\s*(["'])\/(?!\/)([^"'`]+)\1/gu,buildReplacement(quote,rawPath){let nextPath=resolveRootRelativePathForFile(rootDir,filePath,rawPath);return rewrites.push({kind:"fetch",from:`/${rawPath}`,to:nextPath}),`fetch(${quote}${nextPath}${quote}`}}],next=content;return next=next.replace(patterns[0].regex,(fullMatch,attrName,quote,rawPath)=>(changed=!0,patterns[0].buildReplacement(attrName,quote,rawPath))),next=next.replace(patterns[1].regex,(fullMatch,quote,rawPath)=>(changed=!0,patterns[1].buildReplacement(quote,rawPath))),{changed,content:next,rewrites}}async function runPathBaseRewrite(args,report,files){let rewrittenFiles=[],rewriteEntries=[],warnings=[];for(let absolutePath of files){let before=readFileSync16(absolutePath,"utf8"),rewritten=rewritePathBaseRefsInContent(report.project_dir,absolutePath,before);rewritten.changed&&(args.dryRun||writeFileSync10(absolutePath,rewritten.content,"utf8"),rewrittenFiles.push(relative3(report.project_dir,absolutePath)),rewriteEntries.push({file:relative3(report.project_dir,absolutePath),rewrites:rewritten.rewrites}))}return rewriteEntries.length>0&&warnings.push(`\u5DF2\u4FEE\u6B63 root-relative \u9759\u6001\u8D44\u6E90\u5F15\u7528: ${rewriteEntries.length} \u4E2A\u6587\u4EF6`),{rewritten_files:rewrittenFiles,rewrite_entries:rewriteEntries,warnings}}function collectSourcePackageBytes(rootDir){let total=0;function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){visit(fullPath);continue}entry.isFile()&&(total+=statSync5(fullPath).size)}}return visit(rootDir),total}function collectPreflightWarnings(rootDir,localAssetCandidates){let warnings=[];existsSync16(join12(rootDir,"pnpm-workspace.yaml"))&&warnings.push({kind:"workspace_like",file:"pnpm-workspace.yaml",message:"\u68C0\u6D4B\u5230 pnpm-workspace.yaml\uFF1B\u540E\u7EED\u6A21\u677F\u627F\u63A5\u6216\u4E91\u7AEF\u6784\u5EFA\u524D\u901A\u5E38\u9700\u8981\u5904\u7406 workspace-like \u7ED3\u6784\u3002"});for(let asset of localAssetCandidates)asset.size_bytes>=PREFLIGHT_LOCAL_ASSET_WARN_BYTES&&warnings.push({kind:"large_local_asset",file:asset.path,size_bytes:asset.size_bytes,message:"\u68C0\u6D4B\u5230\u5927\u4F53\u79EF\u672C\u5730\u56FE\u7247\uFF1B\u5EFA\u8BAE\u5728\u9884\u5904\u7406\u9636\u6BB5\u5B8C\u6210\u4E0A\u4F20\u3001\u56DE\u5199\u4E0E\u6E05\u7406\u3002"});return warnings}function inferExtensionFromMimeType2(mimeType){switch((mimeType||"").toLowerCase()){case"image/png":return".png";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";case"image/avif":return".avif";case"image/jpeg":case"image/jpg":return".jpg";default:return".jpg"}}function sanitizeFileStem(value){return value.toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,80)}function sanitizeFileName(value){let trimmed=value.trim(),extension=extname2(trimmed).toLowerCase(),stem=trimmed.slice(0,Math.max(0,trimmed.length-extension.length));return`${sanitizeFileStem(stem)||"remote-image"}${extension||".jpg"}`}function inferRemoteFileName(url,mimeType){let extension=inferExtensionFromUrl(url),fallbackExtension=inferExtensionFromMimeType2(mimeType);if(extension)try{let segment=new URL(url).pathname.split("/").filter(Boolean).at(-1);if(segment)return sanitizeFileName(decodeURIComponent(segment))}catch{}try{let parsed=new URL(url),rawSegment=parsed.pathname.split("/").filter(Boolean).at(-1)||parsed.hostname,sanitizedBase=sanitizeFileStem(decodeURIComponent(rawSegment).replace(/\.[a-z0-9]+$/iu,"").trim());if(sanitizedBase)return`${sanitizedBase}${fallbackExtension}`}catch{}switch((mimeType||"").toLowerCase()){case"image/png":return"remote-image.png";case"image/webp":return"remote-image.webp";case"image/gif":return"remote-image.gif";case"image/svg+xml":return"remote-image.svg";case"image/avif":return"remote-image.avif";default:return"remote-image.jpg"}}async function downloadRemoteImage(url){try{return await downloadRemoteImageViaFetch(url)}catch(error){if(!shouldRetryRemoteDownloadWithCurl(error)||!commandExists("curl"))throw error;return await downloadRemoteImageViaCurl(url)}}async function downloadRemoteImageViaFetch(url){let response=await fetch(url,{headers:{accept:"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"}});if(!response.ok)throw new Error(`\u4E0B\u8F7D\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`);let mimeType=String(response.headers.get("content-type")??"").split(";")[0].trim().toLowerCase();if(mimeType&&!mimeType.startsWith("image/"))throw new Error(`\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u56FE\u7247\uFF1A${mimeType}`);let content=Buffer.from(await response.arrayBuffer());if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");return{mimeType,content,fileName:inferRemoteFileName(url,mimeType)}}function shouldRetryRemoteDownloadWithCurl(error){let message=error instanceof Error?error.message:String(error);return/fetch failed|timed?out|econnreset|socket|network|tls|und_err/iu.test(message)}function extractLastContentType(headerText){let matches=[...headerText.matchAll(/^content-type:\s*([^\r\n;]+)/gimu)];return matches.length>0?String(matches[matches.length-1][1]).trim().toLowerCase():""}async function downloadRemoteImageViaCurl(url){let tempRoot=mkdtempSync2(join12(tmpdir2(),"platform-assetize-remote-")),outputPath=join12(tempRoot,"remote.bin"),headerPath=join12(tempRoot,"headers.txt");try{await new Promise((resolve16,reject)=>{let child=spawn3("curl",["-L","--fail","--silent","--show-error","-D",headerPath,"-o",outputPath,url],{cwd:process.cwd(),env:process.env,stdio:["ignore","ignore","pipe"]}),stderr="";child.stderr.on("data",chunk=>{stderr+=String(chunk)}),child.on("error",reject),child.on("close",code2=>{if(code2===0){resolve16();return}reject(new Error(stderr.trim()||`curl \u4E0B\u8F7D\u5931\u8D25\uFF08exit ${code2??"unknown"}\uFF09`))})});let mimeType=extractLastContentType(existsSync16(headerPath)?readFileSync16(headerPath,"utf8"):"");if(mimeType&&!mimeType.startsWith("image/"))throw new Error(`\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u56FE\u7247\uFF1A${mimeType}`);let content=readFileSync16(outputPath);if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");return{mimeType,content,fileName:inferRemoteFileName(url,mimeType)}}finally{rmSync3(tempRoot,{recursive:!0,force:!0})}}function uploadImageViaCli(args){let commandArgs=["asset","upload",args.filePath,"--json"];args.title&&commandArgs.push("--title",args.title),args.folderId&&commandArgs.push("--folder-id",args.folderId);let result=spawnSync(args.cliCmd,commandArgs,{cwd:args.cwd,env:process.env,encoding:"utf8"});if(result.status!==0)throw new Error(result.stderr?.trim()||result.stdout?.trim()||"\u7D20\u6750\u4E0A\u4F20\u5931\u8D25");let parsed=JSON.parse(result.stdout);if(!parsed||typeof parsed.original_url!="string"||!parsed.original_url.trim())throw new Error("\u7D20\u6750\u4E0A\u4F20\u8FD4\u56DE\u7F3A\u5C11 original_url");return parsed}function commandExists(command){return spawnSync("bash",["-lc",`command -v ${command}`],{cwd:process.cwd(),env:process.env,encoding:"utf8"}).status===0}function shouldRetryWithCompression(error){let message=error instanceof Error?error.message:String(error);return/\b413\b/u.test(message)}function buildCompressedFilePath(tempRoot,sourcePath){let safeStem=sanitizeFileStem(basename2(sourcePath,extname2(sourcePath)))||"compressed-image";return join12(tempRoot,`${safeStem}-${LOCAL_IMAGE_UPLOAD_MAX_WIDTH}.jpg`)}function compressLocalImageWithSips(sourcePath,tempRoot){if(!commandExists("sips"))throw new Error("\u5F53\u524D\u673A\u5668\u7F3A\u5C11 sips\uFF0C\u65E0\u6CD5\u6267\u884C\u672C\u5730\u56FE\u7247\u538B\u7F29\u515C\u5E95");let outputPath=buildCompressedFilePath(tempRoot,sourcePath),result=spawnSync("sips",["-s","format","jpeg","--resampleWidth",String(LOCAL_IMAGE_UPLOAD_MAX_WIDTH),sourcePath,"--out",outputPath],{cwd:process.cwd(),env:process.env,encoding:"utf8"});if(result.status!==0)throw new Error(result.stderr?.trim()||result.stdout?.trim()||"sips \u538B\u7F29\u5931\u8D25");return outputPath}function shouldForceHttps(hostname){let lower=hostname.toLowerCase();return lower==="localhost"||lower==="127.0.0.1"||lower==="::1"?!1:HTTPS_FORCE_HOST_SUFFIXES.some(suffix=>lower===suffix||lower.endsWith(`.${suffix}`))}function normalizeUploadedAssetUrl(rawUrl){try{let parsed=new URL(rawUrl);return parsed.protocol==="http:"&&shouldForceHttps(parsed.hostname)?(parsed.protocol="https:",parsed.toString()):rawUrl}catch{return rawUrl}}function replaceUrlInContent(content,originalUrl,finalUrl){return content.split(originalUrl).join(finalUrl)}function normalizeLocalAssetReportPath(args,reportDir){return args.localReport?resolve8(args.localReport):join12(reportDir,"local-asset-report.json")}function loadLocalUploadMappings(reportPath){if(!existsSync16(reportPath))throw new Error(`\u672A\u627E\u5230\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A: ${reportPath}`);let payload=JSON.parse(readFileSync16(reportPath,"utf8"));if(!Array.isArray(payload.uploaded_local_assets))throw new Error(`\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11 uploaded_local_assets: ${reportPath}`);let bySourcePath=new Map;for(let item of payload.uploaded_local_assets){if(!item||typeof item.final_url!="string"||!item.final_url.trim()||item.status!=="uploaded"&&item.status!=="uploaded_after_compress"&&item.status!=="reused_from_cache")continue;let allSourcePaths=Array.isArray(item.source_paths)&&item.source_paths.length>0?item.source_paths:[item.source_path];for(let sourcePath of allSourcePaths)typeof sourcePath=="string"&&sourcePath.trim()&&bySourcePath.set(sourcePath,item.final_url)}return{reportPath,bySourcePath}}function rewriteImportedLocalAssets(rootDir,filePath,content,relativePathToUrl){let changed=!1,next=content.replace(IMPORT_LOCAL_ASSET_PATTERN,(fullMatch,leading,identifier,quote,rawRef,trailing)=>{let resolved=relative3(rootDir,resolve8(dirname10(filePath),rawRef)),finalUrl=relativePathToUrl.get(resolved);return finalUrl?(changed=!0,`${leading}const ${identifier} = ${quote}${finalUrl}${quote};${trailing}`):fullMatch});return{changed,content:next}}function rewriteLiteralLocalAssetRefs(rootDir,filePath,content,relativePathToUrl){let changed=!1,next=content.replace(LOCAL_ASSET_REF_PATTERN,(fullMatch,rawRef)=>{let resolved=relative3(rootDir,resolve8(dirname10(filePath),rawRef)),finalUrl=relativePathToUrl.get(resolved);return finalUrl?(changed=!0,fullMatch.replace(rawRef,finalUrl)):fullMatch});return{changed,content:next}}async function runRewriteLocal(args,report,files,cacheContext){let warnings=[];if(!Array.isArray(report.local_asset_candidates)||report.local_asset_candidates.length===0)return{rewritten_files:[],deleted_clean_source_assets:[],warnings};let localReportPath=normalizeLocalAssetReportPath(args,report.report_dir),loaded=loadLocalUploadMappings(localReportPath),relativePathToUrl=loaded.bySourcePath;if(relativePathToUrl.size===0){let noLocalAssetCandidates=report.local_asset_candidates.length===0,message=noLocalAssetCandidates?`\u5F53\u524D\u6E90\u7801\u5305\u672A\u68C0\u6D4B\u5230\u9700\u8981\u56DE\u5199\u7684\u672C\u5730\u7D20\u6750: ${loaded.reportPath}`:`\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A\u91CC\u6CA1\u6709\u53EF\u56DE\u5199\u7684\u6210\u529F\u4E0A\u4F20\u8BB0\u5F55: ${loaded.reportPath}`;if(args.dryRun)return{rewritten_files:[],deleted_clean_source_assets:[],warnings:[`dry-run \u6A21\u5F0F\u4E0B\u672A\u751F\u6210\u672C\u5730\u7D20\u6750\u56DE\u5199\u6620\u5C04: ${loaded.reportPath}`]};if(noLocalAssetCandidates)return{rewritten_files:[],deleted_clean_source_assets:[],warnings:[message]};throw new Error(message)}let rewrittenFiles=[],deletedLocalAssets=[],hashBySourcePath=new Map;for(let asset of report.local_asset_candidates)for(let sourcePath of asset.source_paths)hashBySourcePath.set(sourcePath,asset.hash);for(let absolutePath of files){let before=readFileSync16(absolutePath,"utf8"),after=before;after=rewriteImportedLocalAssets(report.project_dir,absolutePath,after,relativePathToUrl).content,after=rewriteLiteralLocalAssetRefs(report.project_dir,absolutePath,after,relativePathToUrl).content,after!==before&&(args.dryRun||writeFileSync10(absolutePath,after,"utf8"),rewrittenFiles.push(relative3(report.project_dir,absolutePath)))}if(cacheContext?.enabled&&rewrittenFiles.length>0){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"rewrite_local_refs"});for(let sourcePath of[...relativePathToUrl.keys()]){let contentHash=hashBySourcePath.get(sourcePath);if(!contentHash)continue;let cacheKey=buildLocalCacheKey(contentHash),cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&updateCacheEntry(cacheContext.cache,cacheKey,{status:"rewritten"})}persistAssetCache(cacheContext.cacheFile,cacheContext.cache)}for(let sourcePath of[...relativePathToUrl.keys()].sort((left,right)=>left.localeCompare(right))){let absolutePath=join12(report.project_dir,sourcePath);if(!existsSync16(absolutePath))continue;let contentHash=hashBySourcePath.get(sourcePath),cacheKey=contentHash?buildLocalCacheKey(contentHash):null;if(cacheContext?.enabled&&cacheKey){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"cleanup_local_assets",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]});let cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&(updateCacheEntry(cacheContext.cache,cacheKey,{status:"cleaning"}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache))}args.dryRun||unlinkSync(absolutePath),deletedLocalAssets.push(sourcePath),cacheContext?.enabled&&cacheKey&&(cacheContext.cache.entries[cacheKey]&&(updateCacheEntry(cacheContext.cache,cacheKey,{status:"cleaned"}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache)),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}))}return warnings.push(`\u5DF2\u57FA\u4E8E\u4E0A\u4F20\u62A5\u544A\u56DE\u5199\u672C\u5730\u56FE\u7247\u5F15\u7528: ${loaded.reportPath}`),{rewritten_files:rewrittenFiles,deleted_clean_source_assets:deletedLocalAssets,warnings}}function copyWorkspaceForPreprocess(sourceDir,cleanSourceDir){rmSync3(cleanSourceDir,{recursive:!0,force:!0}),ensureDir(cleanSourceDir);let entries=readdirSync5(sourceDir,{withFileTypes:!0});for(let entry of entries)DEFAULT_SKIP_DIRS.has(entry.name)||cpSync2(join12(sourceDir,entry.name),join12(cleanSourceDir,entry.name),{recursive:!0})}function buildPreflightPayload(report,sourceDir,cleanSourceDir,options){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,detected_type:options.detectedType,upstream_source_package_bytes:options.upstreamSourcePackageBytes,clean_source_package_bytes_before_rewrite:options.cleanSourcePackageBytesBeforeRewrite,summary:report.summary,path_base_violations_detected:options.pathBaseViolationsDetected,path_base_rewrites:options.pathBaseRewrites,path_base_violations_remaining:options.pathBaseViolationsRemaining,preflight_warnings:options.preflightWarnings,remote_candidates:report.remote_candidates,local_asset_candidates:report.local_asset_candidates,pending_videos:report.pending_videos,pending_manual_items:report.pending_manual_items}}function buildAssetInventoryPayload(report,rewriteResult,localUploadResult,sourceDir,cleanSourceDir){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,remote_candidates:report.remote_candidates,local_asset_candidates:report.local_asset_candidates,uploaded_assets:rewriteResult.uploaded_assets,uploaded_local_assets:localUploadResult.uploaded_local_assets}}function countAppliedRemoteUploads(rewriteResult){return rewriteResult.uploaded_assets.filter(item=>item.status==="uploaded").length}function countAppliedLocalUploads(localUploadResult){return localUploadResult.uploaded_local_assets.filter(item=>item.status==="uploaded"||item.status==="uploaded_after_compress").length}function buildPlannedActions(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult){return{remote_upload_candidates:rewriteResult.uploaded_assets.length,local_upload_candidates:localUploadResult.uploaded_local_assets.length,path_base_rewrite_candidates:pathBaseRewriteResult.rewritten_files.length,local_cleanup_candidates:localRewriteResult.deleted_clean_source_assets.length,file_rewrite_candidates:rewriteResult.rewritten_files.length+localRewriteResult.rewritten_files.length+pathBaseRewriteResult.rewritten_files.length,pending_video_candidates:report.pending_videos.length}}function buildWarningsPayload(report,importManifest,reportsDir,cacheContext){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:importManifest.source_dir,clean_source_dir:importManifest.clean_source_dir,warnings:importManifest.warnings,pending_manual_items:report.pending_manual_items,pending_videos:report.pending_videos,cache_warnings:cacheContext?.warnings??[],recovery_actions:{resumed_from_cache:cacheContext?.stats?.resumed_from_cache??!1,reused_uploaded_assets_count:cacheContext?.stats?.remote_reused??0,reused_uploaded_local_assets_count:cacheContext?.stats?.local_reused??0,interrupted_items_count:cacheContext?.stats?.interrupted_items_count??0},report_files:{preflight_report:join12(reportsDir,"preflight-report.json"),asset_inventory:join12(reportsDir,"asset-inventory.json"),import_manifest:join12(reportsDir,"import-manifest.json"),pending_videos:join12(reportsDir,"pending-videos.json")}}}function buildImportManifest(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult,sourceDir,cleanSourceDir,cacheContext){return{tool:report.tool,version:report.version,generated_at:new Date().toISOString(),mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,cache_dir:cacheContext?.cacheDir??null,cache_enabled:cacheContext?.enabled??!1,resumed_from_cache:cacheContext?.stats?.resumed_from_cache??!1,reused_uploaded_assets_count:cacheContext?.stats?.remote_reused??0,reused_uploaded_local_assets_count:cacheContext?.stats?.local_reused??0,interrupted_items_count:cacheContext?.stats?.interrupted_items_count??0,clean_source_package_bytes:collectSourcePackageBytes(cleanSourceDir),summary:report.summary,planned_actions:buildPlannedActions(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult),asset_mappings:{remote:rewriteResult.uploaded_assets,local:localUploadResult.uploaded_local_assets},rewritten_files:[...rewriteResult.rewritten_files,...localRewriteResult.rewritten_files,...pathBaseRewriteResult.rewritten_files],deleted_clean_source_assets:localRewriteResult.deleted_clean_source_assets,path_base_rewrites:pathBaseRewriteResult.rewrite_entries,pending_videos:report.pending_videos,warnings:[...rewriteResult.warnings,...localUploadResult.warnings,...localRewriteResult.warnings,...pathBaseRewriteResult.warnings]}}async function runRewrite(args,report,cacheContext){let imageCandidates=report.remote_candidates.filter(item=>item.kind==="image"&&item.rewrite_supported===!0),warnings=[],uploads=[],replacements=new Map;if(args.dryRun)return{uploaded_assets:imageCandidates.map(item=>({original_url:item.url,final_url:item.url,status:"dry-run"})),rewritten_files:[],warnings};let tempRoot=mkdtempSync2(join12(tmpdir2(),"platform-assetize-project-"));try{let total=imageCandidates.length,uploadResults=await runWithConcurrency(imageCandidates,REMOTE_IMAGE_CONCURRENCY,async(candidate,index)=>{let itemLabel=`remote image ${index+1}/${total}`,cacheKey=buildRemoteCacheKey(candidate.url),cached=cacheContext?.cache?.entries?.[cacheKey];if(cacheContext?.enabled&&cacheEntryReusable(cached))return logProgress(`${itemLabel} reused from cache: ${candidate.url}`),cacheContext.stats.remote_reused+=1,{candidate,finalUrl:cached.final_url,assetId:cached.asset_id??null,status:"reused_from_cache"};try{cacheContext?.enabled&&(cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"upload_remote",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]}),updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"uploading",original_ref:candidate.url}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache));let downloadStart=Date.now();logProgress(`${itemLabel} downloading: ${candidate.url}`);let downloaded=await downloadRemoteImage(candidate.url),downloadMs=Date.now()-downloadStart,tempFilePath=join12(tempRoot,`${index+1}-${downloaded.fileName}`);writeFileSync10(tempFilePath,downloaded.content),logProgress(`${itemLabel} downloaded in ${downloadMs}ms, uploading asset`);let uploadStart=Date.now(),uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:tempFilePath,title:downloaded.fileName,folderId:args.folderId||void 0}),uploadMs=Date.now()-uploadStart,finalUrl=normalizeUploadedAssetUrl(uploaded.original_url);return logProgress(`${itemLabel} uploaded in ${uploadMs}ms`),finalUrl!==uploaded.original_url&&warnings.push(`\u5DF2\u5C06\u7D20\u6750 URL \u534F\u8BAE\u89C4\u8303\u5316\u4E3A HTTPS: ${uploaded.original_url} -> ${finalUrl}`),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"uploaded",original_ref:candidate.url,final_url:finalUrl,asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,content_digest:`sha256:${createHash5("sha256").update(downloaded.content).digest("hex")}`}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)})),{candidate,finalUrl,assetId:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded"}}catch(error){let message=error instanceof Error?error.message:String(error);return logProgress(`${itemLabel} failed: ${message}`),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"failed",original_ref:candidate.url,last_error:message}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache)),{candidate,error:message,status:"fallback"}}});for(let result of uploadResults){if(result.error){warnings.push(`\u56FE\u7247\u4E0A\u4F20\u5931\u8D25: ${result.candidate.url} (${result.error})`),uploads.push({original_url:result.candidate.url,final_url:result.candidate.url,status:"fallback"});continue}replacements.set(result.candidate.url,result.finalUrl),uploads.push({original_url:result.candidate.url,final_url:result.finalUrl,asset_id:result.assetId??null,status:result.status})}let targetFiles=new Set(imageCandidates.flatMap(candidate=>candidate.occurrences.map(occurrence=>occurrence.file))),rewrittenFiles=[];for(let relativePath of[...targetFiles].sort((left,right)=>left.localeCompare(right))){let absolutePath=join12(report.project_dir,relativePath),before=readFileSync16(absolutePath,"utf8"),after=before;for(let[originalUrl,finalUrl]of replacements)after=replaceUrlInContent(after,originalUrl,finalUrl);after!==before&&(writeFileSync10(absolutePath,after,"utf8"),rewrittenFiles.push(relativePath))}if(cacheContext?.enabled&&rewrittenFiles.length>0){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"rewrite_remote_refs"});for(let candidate of imageCandidates){let cacheKey=buildRemoteCacheKey(candidate.url),cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&updateCacheEntry(cacheContext.cache,cacheKey,{status:"rewritten"})}persistAssetCache(cacheContext.cacheFile,cacheContext.cache)}return{uploaded_assets:uploads,rewritten_files:rewrittenFiles,warnings}}finally{rmSync3(tempRoot,{recursive:!0,force:!0})}}async function runUploadLocal(args,report,cacheContext){let warnings=[],uploads=[],tempRoot=mkdtempSync2(join12(tmpdir2(),"platform-assetize-local-"));try{if(args.dryRun)return{uploaded_local_assets:report.local_asset_candidates.map(item=>({source_path:item.path,title:item.file_name,status:"dry-run"})),warnings};for(let asset of report.local_asset_candidates){let absolutePath=join12(report.project_dir,asset.path),cacheKey=buildLocalCacheKey(asset.hash),cached=cacheContext?.cache?.entries?.[cacheKey];if(cacheContext?.enabled&&cacheEntryReusable(cached)){uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:cached.title??asset.file_name,final_url:cached.final_url,asset_id:cached.asset_id??null,status:"reused_from_cache"}),cacheContext.stats.local_reused+=1;continue}try{cacheContext?.enabled&&(cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"upload_local",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]}),updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploading",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache));let uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:absolutePath,title:asset.file_name,folderId:args.folderId||void 0});uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploaded",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}))}catch(error){if(shouldRetryWithCompression(error))try{let compressedPath=compressLocalImageWithSips(absolutePath,tempRoot),uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:compressedPath,title:basename2(compressedPath),folderId:args.folderId||void 0});warnings.push(`\u672C\u5730\u56FE\u7247\u8FC7\u5927\uFF0C\u5DF2\u81EA\u52A8\u538B\u7F29\u540E\u4E0A\u4F20: ${asset.path}`),uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:basename2(compressedPath),final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded_after_compress"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploaded",source_paths:asset.source_paths,content_hash:asset.hash,title:basename2(compressedPath),final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}));continue}catch(compressionError){warnings.push(`\u672C\u5730\u56FE\u7247\u538B\u7F29\u91CD\u8BD5\u5931\u8D25: ${asset.path} (${compressionError instanceof Error?compressionError.message:String(compressionError)})`)}warnings.push(`\u672C\u5730\u56FE\u7247\u4E0A\u4F20\u5931\u8D25: ${asset.path} (${error instanceof Error?error.message:String(error)})`),uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,status:"failed"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"failed",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,last_error:error instanceof Error?error.message:String(error)}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache))}}return{uploaded_local_assets:uploads,warnings}}finally{rmSync3(tempRoot,{recursive:!0,force:!0})}}function renderMarkdown(report){let lines=[];if(lines.push("# Scan Report",""),lines.push(`- Project: \`${report.project_dir}\``),lines.push(`- Mode: \`${report.mode}\``),lines.push(`- Scanned files: ${report.summary.scanned_file_count}`),lines.push(`- Unique remote candidates: ${report.summary.unique_remote_candidates}`),lines.push(`- Images: ${report.summary.image_count}`),lines.push(`- Videos: ${report.summary.video_count}`),lines.push(`- Posters: ${report.summary.poster_count}`),lines.push(`- Unknown remote: ${report.summary.unknown_remote_count}`),lines.push(`- Local images: ${report.summary.local_asset_count??0}`,""),report.remote_candidates.length===0&&(!Array.isArray(report.local_asset_candidates)||report.local_asset_candidates.length===0))return lines.push("No candidates found.",""),lines.join(`
2412
+ `))}function parseArgs2(argv){let result={dir:"",include:new Set(DEFAULT_INCLUDE_EXTENSIONS),folderId:"",type:"auto",dryRun:!1,resume:!0,resetCache:!1,cliCmd:process.env.PLATFORM_CLI_CMD?.trim()||"platform",localReport:"",json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--dry-run"){result.dryRun=!0;continue}if(arg==="--resume"){result.resume=!0;continue}if(arg==="--reset-cache"){result.resetCache=!0;continue}if(arg==="--dir"){result.dir=argv[index+1]??"",index+=1;continue}if(arg==="--include"){let raw=argv[index+1]??"";index+=1,result.include=normalizeInclude(raw);continue}if(arg==="--folder-id"){result.folderId=argv[index+1]??"",index+=1;continue}if(arg==="--type"){result.type=argv[index+1]??result.type,index+=1;continue}if(arg==="--cli-cmd"){result.cliCmd=argv[index+1]??result.cliCmd,index+=1;continue}if(arg==="--local-report"){result.localReport=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function normalizeInclude(raw){let values=raw.split(",").map(item=>item.trim().toLowerCase()).filter(Boolean).map(item=>item.startsWith(".")?item:`.${item}`);return values.length>0?new Set(values):new Set(DEFAULT_INCLUDE_EXTENSIONS)}function buildRemoteCacheKey(url){return`remote:${url}`}function buildLocalCacheKey(contentHash){return`local:${contentHash}`}function defaultAssetCache(sourceDir){return{version:CACHE_VERSION,source_dir:sourceDir,entries:{}}}function defaultLockState(){return{version:CACHE_VERSION,active_run_id:null,started_at:null,phase:null,in_progress_keys:[],last_interrupted_at:null}}function readJsonIfExists2(filePath,fallbackValue){if(!existsSync16(filePath))return fallbackValue;try{return JSON.parse(readFileSync16(filePath,"utf8"))}catch{return fallbackValue}}function loadAssetCache(cacheFile,sourceDir){let loaded=readJsonIfExists2(cacheFile,defaultAssetCache(sourceDir));return{version:CACHE_VERSION,source_dir:loaded.source_dir||sourceDir,entries:loaded.entries&&typeof loaded.entries=="object"?loaded.entries:{}}}function persistAssetCache(cacheFile,payload){ensureDir(dirname10(cacheFile)),writeJson2(cacheFile,payload)}function loadLockState(lockFile){let loaded=readJsonIfExists2(lockFile,defaultLockState());return{version:CACHE_VERSION,active_run_id:loaded.active_run_id??null,started_at:loaded.started_at??null,phase:loaded.phase??null,in_progress_keys:Array.isArray(loaded.in_progress_keys)?loaded.in_progress_keys:[],last_interrupted_at:loaded.last_interrupted_at??null}}function persistLockState(lockFile,payload){ensureDir(dirname10(lockFile)),writeJson2(lockFile,payload)}function beginLockRun(lockFile,previousLock){let interruptedItems=previousLock.active_run_id?previousLock.in_progress_keys.length:0,next={version:CACHE_VERSION,active_run_id:`preprocess-${Date.now()}`,started_at:new Date().toISOString(),phase:"scan",in_progress_keys:[],last_interrupted_at:previousLock.active_run_id?new Date().toISOString():previousLock.last_interrupted_at};return persistLockState(lockFile,next),{lock:next,interruptedItems}}function updateLockState(lockFile,currentLock,patch){let next={...currentLock,...patch};return persistLockState(lockFile,next),next}function completeLockRun(lockFile,currentLock){let next={...currentLock,active_run_id:null,phase:"completed",in_progress_keys:[]};return persistLockState(lockFile,next),next}function cacheEntryReusable(entry){return!!(entry&&typeof entry.final_url=="string"&&entry.final_url.trim()&&entry.asset_id&&entry.status!=="failed")}function updateCacheEntry(cache,cacheKey,patch){cache.entries[cacheKey]={...cache.entries[cacheKey]??{},...patch,updated_at:new Date().toISOString()}}function walkFiles(rootDir,includeExtensions){let files=[];function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;visit(fullPath);continue}if(!entry.isFile())continue;let extension=extname2(entry.name).toLowerCase();includeExtensions.has(extension)&&files.push(fullPath)}}return visit(rootDir),files.sort((left,right)=>left.localeCompare(right))}function walkAssetFiles(rootDir){let files=[];function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;visit(fullPath);continue}if(!entry.isFile())continue;let extension=extname2(entry.name).toLowerCase();IMAGE_EXTENSIONS.has(extension)&&files.push(fullPath)}}return visit(rootDir),files.sort((left,right)=>left.localeCompare(right))}function normalizeMatchedUrl(rawUrl){return rawUrl.replace(/[),.;]+$/u,"").replace(/^(&quot;?|&#34;?|&apos;?|&#39;?)+/iu,"").replace(/(&quot;?|&#34;?|&apos;?|&#39;?)+$/iu,"").replace(/&amp;/giu,"&")}function findLineNumber(text2,offset){let line=1;for(let index=0;index<offset;index+=1)text2.charCodeAt(index)===10&&(line+=1);return line}function inferExtensionFromUrl(url){try{let parsed=new URL(url);return extname2(parsed.pathname).toLowerCase()}catch{return extname2(url).toLowerCase()}}function classifyUrl(url,surroundingText){let lowerUrl=url.toLowerCase(),extension=inferExtensionFromUrl(lowerUrl),lowerContext=surroundingText.toLowerCase(),nonImageContext=lowerContext.includes("<script")||lowerContext.includes("script src")||lowerContext.includes('rel="stylesheet"')||lowerContext.includes("rel='stylesheet'")||lowerContext.includes("xmlns="),nonImageUrl=lowerUrl.includes("cdn.tailwindcss.com")||lowerUrl.includes("fonts.googleapis.com")||lowerUrl.includes("fonts.gstatic.com")||lowerUrl.includes("w3.org/2000/svg");return lowerContext.includes("poster")?"poster":VIDEO_EXTENSIONS.has(extension)?"video":nonImageContext||nonImageUrl||extension===".js"||extension===".mjs"||extension===".css"?"unknown_remote":IMAGE_EXTENSIONS.has(extension)||IMAGE_HOST_HINTS.some(item=>lowerUrl.includes(item))||lowerContext.includes("<img")||lowerContext.includes("background-image")||lowerContext.includes("url(")?"image":"unknown_remote"}function computeRewriteSupported(kind){return kind==="image"}function compactContext(value){return value.replace(/\s+/gu," ").trim().slice(0,200)}function kindPriority(kind){switch(kind){case"video":return 4;case"poster":return 3;case"image":return 2;default:return 1}}function collectRemoteCandidates(rootDir,files){let byUrl=new Map;for(let filePath of files){let raw=readFileSync16(filePath,"utf8");for(let match2 of raw.matchAll(URL_PATTERN)){let matched=match2[0],offset=match2.index??0,url=normalizeMatchedUrl(matched),line=findLineNumber(raw,offset),surroundingText=raw.slice(Math.max(0,offset-80),Math.min(raw.length,offset+url.length+80)),kind=classifyUrl(url,surroundingText),occurrence={file:relative3(rootDir,filePath),line,kind,context:compactContext(surroundingText)},existing=byUrl.get(url);if(existing){existing.occurrences.push(occurrence),kindPriority(kind)>kindPriority(existing.kind)&&(existing.kind=kind,existing.rewrite_supported=computeRewriteSupported(kind));continue}byUrl.set(url,{url,kind,rewrite_supported:computeRewriteSupported(kind),occurrences:[occurrence],notes:kind==="video"?["\u5F53\u524D\u7B2C\u4E00\u7248\u4EC5\u626B\u63CF\uFF0C\u4E0D\u81EA\u52A8\u56DE\u5199\u89C6\u9891\u3002"]:[]})}}return[...byUrl.values()].sort((left,right)=>left.url.localeCompare(right.url))}function buildReport(rootDir,files,candidates,reportDir=join12(rootDir,".third-party-design-reports")){let byKind=candidates.reduce((accumulator,item)=>(accumulator[item.kind]=(accumulator[item.kind]??0)+1,accumulator),{}),pendingManualItems=candidates.filter(item=>item.rewrite_supported!==!0);return{tool:"assetize-project-urls",version:1,mode:"scan",project_dir:rootDir,scanned_files:files.map(file=>relative3(rootDir,file)),summary:{scanned_file_count:files.length,unique_remote_candidates:candidates.length,image_count:byKind.image??0,video_count:byKind.video??0,poster_count:byKind.poster??0,unknown_remote_count:byKind.unknown_remote??0},remote_candidates:candidates,pending_videos:candidates.filter(item=>item.kind==="video"),pending_manual_items:pendingManualItems,report_dir:reportDir}}function hashFileContent(filePath){let content=readFileSync16(filePath);return createHash5("sha256").update(content).digest("hex")}function collectReferencedLocalAssetPaths(sourceFilePath,sourceText){let found=new Set;for(let match2 of sourceText.matchAll(LOCAL_ASSET_REF_PATTERN))found.add(resolve9(dirname10(sourceFilePath),match2[1]));for(let match2 of sourceText.matchAll(CSS_URL_PATTERN))found.add(resolve9(dirname10(sourceFilePath),match2[2]));return found}function collectLocalAssetCandidates(rootDir,sourceFiles,assetFiles){let assetPathSet=new Set(assetFiles.map(filePath=>resolve9(filePath))),byHash=new Map,referencedAssets=new Map;for(let sourceFilePath of sourceFiles){let raw=readFileSync16(sourceFilePath,"utf8"),refs=collectReferencedLocalAssetPaths(sourceFilePath,raw);for(let absoluteRef of refs){if(!assetPathSet.has(absoluteRef))continue;let existing=referencedAssets.get(absoluteRef);if(existing){existing.referenced_by.push(relative3(rootDir,sourceFilePath));continue}referencedAssets.set(absoluteRef,{absolute_path:absoluteRef,relative_path:relative3(rootDir,absoluteRef),referenced_by:[relative3(rootDir,sourceFilePath)]})}}for(let asset of referencedAssets.values()){let stats=statSync5(asset.absolute_path),contentHash=hashFileContent(asset.absolute_path),existing=byHash.get(contentHash);if(existing){existing.source_paths.push(asset.relative_path),existing.referenced_by.push(...asset.referenced_by);continue}byHash.set(contentHash,{hash:contentHash,path:asset.relative_path,source_paths:[asset.relative_path],file_name:basename3(asset.absolute_path),size_bytes:stats.size,kind:"local_image",upload_supported:!0,referenced_by:[...asset.referenced_by]})}return[...byHash.values()].sort((left,right)=>left.path.localeCompare(right.path))}function detectProjectType(rootDir,requestedType="auto"){return requestedType==="static-site"||requestedType==="frontend-app"?requestedType:existsSync16(join12(rootDir,"package.json"))?"frontend-app":"static-site"}function collectPathBaseViolations(rootDir,files){let violations=[],textFilePattern=/\.(?:[cm]?[jt]sx?|html?|css)$/i,patterns=[{kind:"root_relative_fetch",regex:/\bfetch\(\s*['"`]\/(?!\/)/g},{kind:"root_relative_href",regex:/\bhref\s*=\s*['"]\/(?!\/)/g},{kind:"root_relative_src",regex:/\bsrc\s*=\s*['"]\/(?!\/)/g}];for(let filePath of files){let relativePath=relative3(rootDir,filePath);if(!textFilePattern.test(relativePath))continue;let lines=readFileSync16(filePath,"utf8").split(/\r?\n/u);for(let index=0;index<lines.length;index+=1){let line=lines[index];for(let pattern of patterns)pattern.regex.lastIndex=0,pattern.regex.test(line)&&violations.push({file:relativePath,line:index+1,kind:pattern.kind,snippet:line.trim().slice(0,180)})}}return violations}function toPosixPath(value){return value.replace(/\\/gu,"/")}function ensureDotRelativePath(value){return value===""||value==="."?"./":value.startsWith("./")||value.startsWith("../")?value:`./${value}`}function resolveRootRelativePathForFile(rootDir,filePath,rootRelativePath){let normalizedTarget=rootRelativePath.replace(/^\/+/u,""),targetPath=join12(rootDir,normalizedTarget),relativePath=relative3(dirname10(filePath),targetPath);return ensureDotRelativePath(toPosixPath(relativePath))}function rewritePathBaseRefsInContent(rootDir,filePath,content){let changed=!1,rewrites=[],patterns=[{regex:/\b(src|href)\s*=\s*(["'])\/(?!\/)([^"'`]+)\2/gu,buildReplacement(attrName,quote,rawPath){let nextPath=resolveRootRelativePathForFile(rootDir,filePath,rawPath);return rewrites.push({kind:"attribute",attr:attrName,from:`/${rawPath}`,to:nextPath}),`${attrName}=${quote}${nextPath}${quote}`}},{regex:/\bfetch\(\s*(["'])\/(?!\/)([^"'`]+)\1/gu,buildReplacement(quote,rawPath){let nextPath=resolveRootRelativePathForFile(rootDir,filePath,rawPath);return rewrites.push({kind:"fetch",from:`/${rawPath}`,to:nextPath}),`fetch(${quote}${nextPath}${quote}`}}],next=content;return next=next.replace(patterns[0].regex,(fullMatch,attrName,quote,rawPath)=>(changed=!0,patterns[0].buildReplacement(attrName,quote,rawPath))),next=next.replace(patterns[1].regex,(fullMatch,quote,rawPath)=>(changed=!0,patterns[1].buildReplacement(quote,rawPath))),{changed,content:next,rewrites}}async function runPathBaseRewrite(args,report,files){let rewrittenFiles=[],rewriteEntries=[],warnings=[];for(let absolutePath of files){let before=readFileSync16(absolutePath,"utf8"),rewritten=rewritePathBaseRefsInContent(report.project_dir,absolutePath,before);rewritten.changed&&(args.dryRun||writeFileSync10(absolutePath,rewritten.content,"utf8"),rewrittenFiles.push(relative3(report.project_dir,absolutePath)),rewriteEntries.push({file:relative3(report.project_dir,absolutePath),rewrites:rewritten.rewrites}))}return rewriteEntries.length>0&&warnings.push(`\u5DF2\u4FEE\u6B63 root-relative \u9759\u6001\u8D44\u6E90\u5F15\u7528: ${rewriteEntries.length} \u4E2A\u6587\u4EF6`),{rewritten_files:rewrittenFiles,rewrite_entries:rewriteEntries,warnings}}function collectSourcePackageBytes(rootDir){let total=0;function visit(currentDir){let entries=readdirSync5(currentDir,{withFileTypes:!0});for(let entry of entries){if(DEFAULT_SKIP_DIRS.has(entry.name))continue;let fullPath=join12(currentDir,entry.name);if(entry.isDirectory()){visit(fullPath);continue}entry.isFile()&&(total+=statSync5(fullPath).size)}}return visit(rootDir),total}function collectPreflightWarnings(rootDir,localAssetCandidates){let warnings=[];existsSync16(join12(rootDir,"pnpm-workspace.yaml"))&&warnings.push({kind:"workspace_like",file:"pnpm-workspace.yaml",message:"\u68C0\u6D4B\u5230 pnpm-workspace.yaml\uFF1B\u540E\u7EED\u6A21\u677F\u627F\u63A5\u6216\u4E91\u7AEF\u6784\u5EFA\u524D\u901A\u5E38\u9700\u8981\u5904\u7406 workspace-like \u7ED3\u6784\u3002"});for(let asset of localAssetCandidates)asset.size_bytes>=PREFLIGHT_LOCAL_ASSET_WARN_BYTES&&warnings.push({kind:"large_local_asset",file:asset.path,size_bytes:asset.size_bytes,message:"\u68C0\u6D4B\u5230\u5927\u4F53\u79EF\u672C\u5730\u56FE\u7247\uFF1B\u5EFA\u8BAE\u5728\u9884\u5904\u7406\u9636\u6BB5\u5B8C\u6210\u4E0A\u4F20\u3001\u56DE\u5199\u4E0E\u6E05\u7406\u3002"});return warnings}function inferExtensionFromMimeType2(mimeType){switch((mimeType||"").toLowerCase()){case"image/png":return".png";case"image/webp":return".webp";case"image/gif":return".gif";case"image/svg+xml":return".svg";case"image/avif":return".avif";case"image/jpeg":case"image/jpg":return".jpg";default:return".jpg"}}function sanitizeFileStem(value){return value.toLowerCase().replace(/[^a-z0-9]+/gu,"-").replace(/^-+|-+$/gu,"").slice(0,80)}function sanitizeFileName(value){let trimmed=value.trim(),extension=extname2(trimmed).toLowerCase(),stem=trimmed.slice(0,Math.max(0,trimmed.length-extension.length));return`${sanitizeFileStem(stem)||"remote-image"}${extension||".jpg"}`}function inferRemoteFileName(url,mimeType){let extension=inferExtensionFromUrl(url),fallbackExtension=inferExtensionFromMimeType2(mimeType);if(extension)try{let segment=new URL(url).pathname.split("/").filter(Boolean).at(-1);if(segment)return sanitizeFileName(decodeURIComponent(segment))}catch{}try{let parsed=new URL(url),rawSegment=parsed.pathname.split("/").filter(Boolean).at(-1)||parsed.hostname,sanitizedBase=sanitizeFileStem(decodeURIComponent(rawSegment).replace(/\.[a-z0-9]+$/iu,"").trim());if(sanitizedBase)return`${sanitizedBase}${fallbackExtension}`}catch{}switch((mimeType||"").toLowerCase()){case"image/png":return"remote-image.png";case"image/webp":return"remote-image.webp";case"image/gif":return"remote-image.gif";case"image/svg+xml":return"remote-image.svg";case"image/avif":return"remote-image.avif";default:return"remote-image.jpg"}}async function downloadRemoteImage(url){try{return await downloadRemoteImageViaFetch(url)}catch(error){if(!shouldRetryRemoteDownloadWithCurl(error)||!commandExists("curl"))throw error;return await downloadRemoteImageViaCurl(url)}}async function downloadRemoteImageViaFetch(url){let response=await fetch(url,{headers:{accept:"image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8"}});if(!response.ok)throw new Error(`\u4E0B\u8F7D\u5931\u8D25\uFF08HTTP ${response.status}\uFF09`);let mimeType=String(response.headers.get("content-type")??"").split(";")[0].trim().toLowerCase();if(mimeType&&!mimeType.startsWith("image/"))throw new Error(`\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u56FE\u7247\uFF1A${mimeType}`);let content=Buffer.from(await response.arrayBuffer());if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");return{mimeType,content,fileName:inferRemoteFileName(url,mimeType)}}function shouldRetryRemoteDownloadWithCurl(error){let message=error instanceof Error?error.message:String(error);return/fetch failed|timed?out|econnreset|socket|network|tls|und_err/iu.test(message)}function extractLastContentType(headerText){let matches=[...headerText.matchAll(/^content-type:\s*([^\r\n;]+)/gimu)];return matches.length>0?String(matches[matches.length-1][1]).trim().toLowerCase():""}async function downloadRemoteImageViaCurl(url){let tempRoot=mkdtempSync3(join12(tmpdir2(),"platform-assetize-remote-")),outputPath=join12(tempRoot,"remote.bin"),headerPath=join12(tempRoot,"headers.txt");try{await new Promise((resolve17,reject)=>{let child=spawn("curl",["-L","--fail","--silent","--show-error","-D",headerPath,"-o",outputPath,url],{cwd:process.cwd(),env:process.env,stdio:["ignore","ignore","pipe"]}),stderr="";child.stderr.on("data",chunk=>{stderr+=String(chunk)}),child.on("error",reject),child.on("close",code2=>{if(code2===0){resolve17();return}reject(new Error(stderr.trim()||`curl \u4E0B\u8F7D\u5931\u8D25\uFF08exit ${code2??"unknown"}\uFF09`))})});let mimeType=extractLastContentType(existsSync16(headerPath)?readFileSync16(headerPath,"utf8"):"");if(mimeType&&!mimeType.startsWith("image/"))throw new Error(`\u8FDC\u7A0B\u8D44\u6E90\u4E0D\u662F\u56FE\u7247\uFF1A${mimeType}`);let content=readFileSync16(outputPath);if(content.byteLength===0)throw new Error("\u8FDC\u7A0B\u56FE\u7247\u5185\u5BB9\u4E3A\u7A7A");return{mimeType,content,fileName:inferRemoteFileName(url,mimeType)}}finally{rmSync4(tempRoot,{recursive:!0,force:!0})}}function uploadImageViaCli(args){let commandArgs=["asset","upload",args.filePath,"--json"];args.title&&commandArgs.push("--title",args.title),args.folderId&&commandArgs.push("--folder-id",args.folderId);let result=spawnSync(args.cliCmd,commandArgs,{cwd:args.cwd,env:process.env,encoding:"utf8"});if(result.status!==0)throw new Error(result.stderr?.trim()||result.stdout?.trim()||"\u7D20\u6750\u4E0A\u4F20\u5931\u8D25");let parsed=JSON.parse(result.stdout);if(!parsed||typeof parsed.original_url!="string"||!parsed.original_url.trim())throw new Error("\u7D20\u6750\u4E0A\u4F20\u8FD4\u56DE\u7F3A\u5C11 original_url");return parsed}function commandExists(command){return spawnSync("bash",["-lc",`command -v ${command}`],{cwd:process.cwd(),env:process.env,encoding:"utf8"}).status===0}function shouldRetryWithCompression(error){let message=error instanceof Error?error.message:String(error);return/\b413\b/u.test(message)}function buildCompressedFilePath(tempRoot,sourcePath){let safeStem=sanitizeFileStem(basename3(sourcePath,extname2(sourcePath)))||"compressed-image";return join12(tempRoot,`${safeStem}-${LOCAL_IMAGE_UPLOAD_MAX_WIDTH}.jpg`)}function compressLocalImageWithSips(sourcePath,tempRoot){if(!commandExists("sips"))throw new Error("\u5F53\u524D\u673A\u5668\u7F3A\u5C11 sips\uFF0C\u65E0\u6CD5\u6267\u884C\u672C\u5730\u56FE\u7247\u538B\u7F29\u515C\u5E95");let outputPath=buildCompressedFilePath(tempRoot,sourcePath),result=spawnSync("sips",["-s","format","jpeg","--resampleWidth",String(LOCAL_IMAGE_UPLOAD_MAX_WIDTH),sourcePath,"--out",outputPath],{cwd:process.cwd(),env:process.env,encoding:"utf8"});if(result.status!==0)throw new Error(result.stderr?.trim()||result.stdout?.trim()||"sips \u538B\u7F29\u5931\u8D25");return outputPath}function shouldForceHttps(hostname){let lower=hostname.toLowerCase();return lower==="localhost"||lower==="127.0.0.1"||lower==="::1"?!1:HTTPS_FORCE_HOST_SUFFIXES.some(suffix=>lower===suffix||lower.endsWith(`.${suffix}`))}function normalizeUploadedAssetUrl(rawUrl){try{let parsed=new URL(rawUrl);return parsed.protocol==="http:"&&shouldForceHttps(parsed.hostname)?(parsed.protocol="https:",parsed.toString()):rawUrl}catch{return rawUrl}}function replaceUrlInContent(content,originalUrl,finalUrl){return content.split(originalUrl).join(finalUrl)}function normalizeLocalAssetReportPath(args,reportDir){return args.localReport?resolve9(args.localReport):join12(reportDir,"local-asset-report.json")}function loadLocalUploadMappings(reportPath){if(!existsSync16(reportPath))throw new Error(`\u672A\u627E\u5230\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A: ${reportPath}`);let payload=JSON.parse(readFileSync16(reportPath,"utf8"));if(!Array.isArray(payload.uploaded_local_assets))throw new Error(`\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A\u683C\u5F0F\u65E0\u6548\uFF0C\u7F3A\u5C11 uploaded_local_assets: ${reportPath}`);let bySourcePath=new Map;for(let item of payload.uploaded_local_assets){if(!item||typeof item.final_url!="string"||!item.final_url.trim()||item.status!=="uploaded"&&item.status!=="uploaded_after_compress"&&item.status!=="reused_from_cache")continue;let allSourcePaths=Array.isArray(item.source_paths)&&item.source_paths.length>0?item.source_paths:[item.source_path];for(let sourcePath of allSourcePaths)typeof sourcePath=="string"&&sourcePath.trim()&&bySourcePath.set(sourcePath,item.final_url)}return{reportPath,bySourcePath}}function rewriteImportedLocalAssets(rootDir,filePath,content,relativePathToUrl){let changed=!1,next=content.replace(IMPORT_LOCAL_ASSET_PATTERN,(fullMatch,leading,identifier,quote,rawRef,trailing)=>{let resolved=relative3(rootDir,resolve9(dirname10(filePath),rawRef)),finalUrl=relativePathToUrl.get(resolved);return finalUrl?(changed=!0,`${leading}const ${identifier} = ${quote}${finalUrl}${quote};${trailing}`):fullMatch});return{changed,content:next}}function rewriteLiteralLocalAssetRefs(rootDir,filePath,content,relativePathToUrl){let changed=!1,next=content.replace(LOCAL_ASSET_REF_PATTERN,(fullMatch,rawRef)=>{let resolved=relative3(rootDir,resolve9(dirname10(filePath),rawRef)),finalUrl=relativePathToUrl.get(resolved);return finalUrl?(changed=!0,fullMatch.replace(rawRef,finalUrl)):fullMatch});return{changed,content:next}}async function runRewriteLocal(args,report,files,cacheContext){let warnings=[];if(!Array.isArray(report.local_asset_candidates)||report.local_asset_candidates.length===0)return{rewritten_files:[],deleted_clean_source_assets:[],warnings};let localReportPath=normalizeLocalAssetReportPath(args,report.report_dir),loaded=loadLocalUploadMappings(localReportPath),relativePathToUrl=loaded.bySourcePath;if(relativePathToUrl.size===0){let noLocalAssetCandidates=report.local_asset_candidates.length===0,message=noLocalAssetCandidates?`\u5F53\u524D\u6E90\u7801\u5305\u672A\u68C0\u6D4B\u5230\u9700\u8981\u56DE\u5199\u7684\u672C\u5730\u7D20\u6750: ${loaded.reportPath}`:`\u672C\u5730\u7D20\u6750\u4E0A\u4F20\u62A5\u544A\u91CC\u6CA1\u6709\u53EF\u56DE\u5199\u7684\u6210\u529F\u4E0A\u4F20\u8BB0\u5F55: ${loaded.reportPath}`;if(args.dryRun)return{rewritten_files:[],deleted_clean_source_assets:[],warnings:[`dry-run \u6A21\u5F0F\u4E0B\u672A\u751F\u6210\u672C\u5730\u7D20\u6750\u56DE\u5199\u6620\u5C04: ${loaded.reportPath}`]};if(noLocalAssetCandidates)return{rewritten_files:[],deleted_clean_source_assets:[],warnings:[message]};throw new Error(message)}let rewrittenFiles=[],deletedLocalAssets=[],hashBySourcePath=new Map;for(let asset of report.local_asset_candidates)for(let sourcePath of asset.source_paths)hashBySourcePath.set(sourcePath,asset.hash);for(let absolutePath of files){let before=readFileSync16(absolutePath,"utf8"),after=before;after=rewriteImportedLocalAssets(report.project_dir,absolutePath,after,relativePathToUrl).content,after=rewriteLiteralLocalAssetRefs(report.project_dir,absolutePath,after,relativePathToUrl).content,after!==before&&(args.dryRun||writeFileSync10(absolutePath,after,"utf8"),rewrittenFiles.push(relative3(report.project_dir,absolutePath)))}if(cacheContext?.enabled&&rewrittenFiles.length>0){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"rewrite_local_refs"});for(let sourcePath of[...relativePathToUrl.keys()]){let contentHash=hashBySourcePath.get(sourcePath);if(!contentHash)continue;let cacheKey=buildLocalCacheKey(contentHash),cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&updateCacheEntry(cacheContext.cache,cacheKey,{status:"rewritten"})}persistAssetCache(cacheContext.cacheFile,cacheContext.cache)}for(let sourcePath of[...relativePathToUrl.keys()].sort((left,right)=>left.localeCompare(right))){let absolutePath=join12(report.project_dir,sourcePath);if(!existsSync16(absolutePath))continue;let contentHash=hashBySourcePath.get(sourcePath),cacheKey=contentHash?buildLocalCacheKey(contentHash):null;if(cacheContext?.enabled&&cacheKey){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"cleanup_local_assets",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]});let cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&(updateCacheEntry(cacheContext.cache,cacheKey,{status:"cleaning"}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache))}args.dryRun||unlinkSync2(absolutePath),deletedLocalAssets.push(sourcePath),cacheContext?.enabled&&cacheKey&&(cacheContext.cache.entries[cacheKey]&&(updateCacheEntry(cacheContext.cache,cacheKey,{status:"cleaned"}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache)),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}))}return warnings.push(`\u5DF2\u57FA\u4E8E\u4E0A\u4F20\u62A5\u544A\u56DE\u5199\u672C\u5730\u56FE\u7247\u5F15\u7528: ${loaded.reportPath}`),{rewritten_files:rewrittenFiles,deleted_clean_source_assets:deletedLocalAssets,warnings}}function copyWorkspaceForPreprocess(sourceDir,cleanSourceDir){rmSync4(cleanSourceDir,{recursive:!0,force:!0}),ensureDir(cleanSourceDir);let entries=readdirSync5(sourceDir,{withFileTypes:!0});for(let entry of entries)DEFAULT_SKIP_DIRS.has(entry.name)||cpSync2(join12(sourceDir,entry.name),join12(cleanSourceDir,entry.name),{recursive:!0})}function buildPreflightPayload(report,sourceDir,cleanSourceDir,options){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,detected_type:options.detectedType,upstream_source_package_bytes:options.upstreamSourcePackageBytes,clean_source_package_bytes_before_rewrite:options.cleanSourcePackageBytesBeforeRewrite,summary:report.summary,path_base_violations_detected:options.pathBaseViolationsDetected,path_base_rewrites:options.pathBaseRewrites,path_base_violations_remaining:options.pathBaseViolationsRemaining,preflight_warnings:options.preflightWarnings,remote_candidates:report.remote_candidates,local_asset_candidates:report.local_asset_candidates,pending_videos:report.pending_videos,pending_manual_items:report.pending_manual_items}}function buildAssetInventoryPayload(report,rewriteResult,localUploadResult,sourceDir,cleanSourceDir){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,remote_candidates:report.remote_candidates,local_asset_candidates:report.local_asset_candidates,uploaded_assets:rewriteResult.uploaded_assets,uploaded_local_assets:localUploadResult.uploaded_local_assets}}function countAppliedRemoteUploads(rewriteResult){return rewriteResult.uploaded_assets.filter(item=>item.status==="uploaded").length}function countAppliedLocalUploads(localUploadResult){return localUploadResult.uploaded_local_assets.filter(item=>item.status==="uploaded"||item.status==="uploaded_after_compress").length}function buildPlannedActions(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult){return{remote_upload_candidates:rewriteResult.uploaded_assets.length,local_upload_candidates:localUploadResult.uploaded_local_assets.length,path_base_rewrite_candidates:pathBaseRewriteResult.rewritten_files.length,local_cleanup_candidates:localRewriteResult.deleted_clean_source_assets.length,file_rewrite_candidates:rewriteResult.rewritten_files.length+localRewriteResult.rewritten_files.length+pathBaseRewriteResult.rewritten_files.length,pending_video_candidates:report.pending_videos.length}}function buildWarningsPayload(report,importManifest,reportsDir,cacheContext){return{tool:report.tool,version:report.version,mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:importManifest.source_dir,clean_source_dir:importManifest.clean_source_dir,warnings:importManifest.warnings,pending_manual_items:report.pending_manual_items,pending_videos:report.pending_videos,cache_warnings:cacheContext?.warnings??[],recovery_actions:{resumed_from_cache:cacheContext?.stats?.resumed_from_cache??!1,reused_uploaded_assets_count:cacheContext?.stats?.remote_reused??0,reused_uploaded_local_assets_count:cacheContext?.stats?.local_reused??0,interrupted_items_count:cacheContext?.stats?.interrupted_items_count??0},report_files:{preflight_report:join12(reportsDir,"preflight-report.json"),asset_inventory:join12(reportsDir,"asset-inventory.json"),import_manifest:join12(reportsDir,"import-manifest.json"),pending_videos:join12(reportsDir,"pending-videos.json")}}}function buildImportManifest(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult,sourceDir,cleanSourceDir,cacheContext){return{tool:report.tool,version:report.version,generated_at:new Date().toISOString(),mode:"preprocess",execution_mode:report.execution_mode??"apply",source_dir:sourceDir,clean_source_dir:cleanSourceDir,cache_dir:cacheContext?.cacheDir??null,cache_enabled:cacheContext?.enabled??!1,resumed_from_cache:cacheContext?.stats?.resumed_from_cache??!1,reused_uploaded_assets_count:cacheContext?.stats?.remote_reused??0,reused_uploaded_local_assets_count:cacheContext?.stats?.local_reused??0,interrupted_items_count:cacheContext?.stats?.interrupted_items_count??0,clean_source_package_bytes:collectSourcePackageBytes(cleanSourceDir),summary:report.summary,planned_actions:buildPlannedActions(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult),asset_mappings:{remote:rewriteResult.uploaded_assets,local:localUploadResult.uploaded_local_assets},rewritten_files:[...rewriteResult.rewritten_files,...localRewriteResult.rewritten_files,...pathBaseRewriteResult.rewritten_files],deleted_clean_source_assets:localRewriteResult.deleted_clean_source_assets,path_base_rewrites:pathBaseRewriteResult.rewrite_entries,pending_videos:report.pending_videos,warnings:[...rewriteResult.warnings,...localUploadResult.warnings,...localRewriteResult.warnings,...pathBaseRewriteResult.warnings]}}async function runRewrite(args,report,cacheContext){let imageCandidates=report.remote_candidates.filter(item=>item.kind==="image"&&item.rewrite_supported===!0),warnings=[],uploads=[],replacements=new Map;if(args.dryRun)return{uploaded_assets:imageCandidates.map(item=>({original_url:item.url,final_url:item.url,status:"dry-run"})),rewritten_files:[],warnings};let tempRoot=mkdtempSync3(join12(tmpdir2(),"platform-assetize-project-"));try{let total=imageCandidates.length,uploadResults=await runWithConcurrency(imageCandidates,REMOTE_IMAGE_CONCURRENCY,async(candidate,index)=>{let itemLabel=`remote image ${index+1}/${total}`,cacheKey=buildRemoteCacheKey(candidate.url),cached=cacheContext?.cache?.entries?.[cacheKey];if(cacheContext?.enabled&&cacheEntryReusable(cached))return logProgress(`${itemLabel} reused from cache: ${candidate.url}`),cacheContext.stats.remote_reused+=1,{candidate,finalUrl:cached.final_url,assetId:cached.asset_id??null,status:"reused_from_cache"};try{cacheContext?.enabled&&(cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"upload_remote",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]}),updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"uploading",original_ref:candidate.url}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache));let downloadStart=Date.now();logProgress(`${itemLabel} downloading: ${candidate.url}`);let downloaded=await downloadRemoteImage(candidate.url),downloadMs=Date.now()-downloadStart,tempFilePath=join12(tempRoot,`${index+1}-${downloaded.fileName}`);writeFileSync10(tempFilePath,downloaded.content),logProgress(`${itemLabel} downloaded in ${downloadMs}ms, uploading asset`);let uploadStart=Date.now(),uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:tempFilePath,title:downloaded.fileName,folderId:args.folderId||void 0}),uploadMs=Date.now()-uploadStart,finalUrl=normalizeUploadedAssetUrl(uploaded.original_url);return logProgress(`${itemLabel} uploaded in ${uploadMs}ms`),finalUrl!==uploaded.original_url&&warnings.push(`\u5DF2\u5C06\u7D20\u6750 URL \u534F\u8BAE\u89C4\u8303\u5316\u4E3A HTTPS: ${uploaded.original_url} -> ${finalUrl}`),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"uploaded",original_ref:candidate.url,final_url:finalUrl,asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,content_digest:`sha256:${createHash5("sha256").update(downloaded.content).digest("hex")}`}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)})),{candidate,finalUrl,assetId:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded"}}catch(error){let message=error instanceof Error?error.message:String(error);return logProgress(`${itemLabel} failed: ${message}`),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"remote_image",status:"failed",original_ref:candidate.url,last_error:message}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache)),{candidate,error:message,status:"fallback"}}});for(let result of uploadResults){if(result.error){warnings.push(`\u56FE\u7247\u4E0A\u4F20\u5931\u8D25: ${result.candidate.url} (${result.error})`),uploads.push({original_url:result.candidate.url,final_url:result.candidate.url,status:"fallback"});continue}replacements.set(result.candidate.url,result.finalUrl),uploads.push({original_url:result.candidate.url,final_url:result.finalUrl,asset_id:result.assetId??null,status:result.status})}let targetFiles=new Set(imageCandidates.flatMap(candidate=>candidate.occurrences.map(occurrence=>occurrence.file))),rewrittenFiles=[];for(let relativePath of[...targetFiles].sort((left,right)=>left.localeCompare(right))){let absolutePath=join12(report.project_dir,relativePath),before=readFileSync16(absolutePath,"utf8"),after=before;for(let[originalUrl,finalUrl]of replacements)after=replaceUrlInContent(after,originalUrl,finalUrl);after!==before&&(writeFileSync10(absolutePath,after,"utf8"),rewrittenFiles.push(relativePath))}if(cacheContext?.enabled&&rewrittenFiles.length>0){cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"rewrite_remote_refs"});for(let candidate of imageCandidates){let cacheKey=buildRemoteCacheKey(candidate.url),cached=cacheContext.cache.entries[cacheKey];cacheEntryReusable(cached)&&updateCacheEntry(cacheContext.cache,cacheKey,{status:"rewritten"})}persistAssetCache(cacheContext.cacheFile,cacheContext.cache)}return{uploaded_assets:uploads,rewritten_files:rewrittenFiles,warnings}}finally{rmSync4(tempRoot,{recursive:!0,force:!0})}}async function runUploadLocal(args,report,cacheContext){let warnings=[],uploads=[],tempRoot=mkdtempSync3(join12(tmpdir2(),"platform-assetize-local-"));try{if(args.dryRun)return{uploaded_local_assets:report.local_asset_candidates.map(item=>({source_path:item.path,title:item.file_name,status:"dry-run"})),warnings};for(let asset of report.local_asset_candidates){let absolutePath=join12(report.project_dir,asset.path),cacheKey=buildLocalCacheKey(asset.hash),cached=cacheContext?.cache?.entries?.[cacheKey];if(cacheContext?.enabled&&cacheEntryReusable(cached)){uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:cached.title??asset.file_name,final_url:cached.final_url,asset_id:cached.asset_id??null,status:"reused_from_cache"}),cacheContext.stats.local_reused+=1;continue}try{cacheContext?.enabled&&(cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{phase:"upload_local",in_progress_keys:[...new Set([...cacheContext.lock.in_progress_keys,cacheKey])]}),updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploading",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache));let uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:absolutePath,title:asset.file_name,folderId:args.folderId||void 0});uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploaded",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}))}catch(error){if(shouldRetryWithCompression(error))try{let compressedPath=compressLocalImageWithSips(absolutePath,tempRoot),uploaded=uploadImageViaCli({cliCmd:args.cliCmd,cwd:report.project_dir,filePath:compressedPath,title:basename3(compressedPath),folderId:args.folderId||void 0});warnings.push(`\u672C\u5730\u56FE\u7247\u8FC7\u5927\uFF0C\u5DF2\u81EA\u52A8\u538B\u7F29\u540E\u4E0A\u4F20: ${asset.path}`),uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:basename3(compressedPath),final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null,status:"uploaded_after_compress"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"uploaded",source_paths:asset.source_paths,content_hash:asset.hash,title:basename3(compressedPath),final_url:normalizeUploadedAssetUrl(uploaded.original_url),asset_id:uploaded.asset?.asset_id??uploaded.asset?.asset?.asset_id??null}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache),cacheContext.lock=updateLockState(cacheContext.lockFile,cacheContext.lock,{in_progress_keys:cacheContext.lock.in_progress_keys.filter(item=>item!==cacheKey)}));continue}catch(compressionError){warnings.push(`\u672C\u5730\u56FE\u7247\u538B\u7F29\u91CD\u8BD5\u5931\u8D25: ${asset.path} (${compressionError instanceof Error?compressionError.message:String(compressionError)})`)}warnings.push(`\u672C\u5730\u56FE\u7247\u4E0A\u4F20\u5931\u8D25: ${asset.path} (${error instanceof Error?error.message:String(error)})`),uploads.push({source_path:asset.path,source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,status:"failed"}),cacheContext?.enabled&&(updateCacheEntry(cacheContext.cache,cacheKey,{kind:"local_image",status:"failed",source_paths:asset.source_paths,content_hash:asset.hash,title:asset.file_name,last_error:error instanceof Error?error.message:String(error)}),persistAssetCache(cacheContext.cacheFile,cacheContext.cache))}}return{uploaded_local_assets:uploads,warnings}}finally{rmSync4(tempRoot,{recursive:!0,force:!0})}}function renderMarkdown(report){let lines=[];if(lines.push("# Scan Report",""),lines.push(`- Project: \`${report.project_dir}\``),lines.push(`- Mode: \`${report.mode}\``),lines.push(`- Scanned files: ${report.summary.scanned_file_count}`),lines.push(`- Unique remote candidates: ${report.summary.unique_remote_candidates}`),lines.push(`- Images: ${report.summary.image_count}`),lines.push(`- Videos: ${report.summary.video_count}`),lines.push(`- Posters: ${report.summary.poster_count}`),lines.push(`- Unknown remote: ${report.summary.unknown_remote_count}`),lines.push(`- Local images: ${report.summary.local_asset_count??0}`,""),report.remote_candidates.length===0&&(!Array.isArray(report.local_asset_candidates)||report.local_asset_candidates.length===0))return lines.push("No candidates found.",""),lines.join(`
2410
2413
  `);if(report.remote_candidates.length>0){lines.push("## Remote Candidates","","| Kind | Rewrite | URL | Refs |","|---|---|---|---:|");for(let item of report.remote_candidates)lines.push(`| ${item.kind} | ${item.rewrite_supported?"yes":"no"} | ${escapeMdCell(item.url)} | ${item.occurrences.length} |`);lines.push("")}if(report.pending_videos.length>0){lines.push("## Pending Videos","");for(let item of report.pending_videos)lines.push(`- ${item.url}`);lines.push("")}if(Array.isArray(report.local_asset_candidates)&&report.local_asset_candidates.length>0){lines.push("## Local Images","","| File | Dedupe Refs | Size (bytes) | Upload |","|---|---:|---:|---|");for(let item of report.local_asset_candidates)lines.push(`| ${escapeMdCell(item.path)} | ${item.source_paths.length} | ${item.size_bytes} | ${item.upload_supported?"yes":"no"} |`);lines.push("")}if(report.remote_candidates.length>0){lines.push("## Occurrences","");for(let item of report.remote_candidates){lines.push(`### ${item.url}`,"",`- kind: \`${item.kind}\``,`- rewrite_supported: \`${item.rewrite_supported}\``),Array.isArray(item.notes)&&item.notes.length>0&&lines.push(`- notes: ${item.notes.join(" / ")}`);for(let occurrence of item.occurrences)lines.push(`- ${occurrence.file}:${occurrence.line} (${occurrence.kind})`);lines.push("")}}return lines.join(`
2411
2414
  `)}function escapeMdCell(value){return value.replace(/\|/gu,"\\|")}function ensureDir(dirPath){mkdirSync9(dirPath,{recursive:!0})}function writeJson2(filePath,payload){writeFileSync10(filePath,`${JSON.stringify(payload,null,2)}
2412
- `,"utf8")}async function runPreprocess(args,sourceDir){let preprocessRoot=join12(sourceDir,".design-preprocess"),cleanSourceDir=join12(preprocessRoot,"clean-source"),reportsDir=join12(preprocessRoot,"reports"),cacheDir=join12(preprocessRoot,"cache"),cacheFile=join12(cacheDir,"assets.json"),lockFile=join12(cacheDir,"locks.json");args.resetCache&&!args.dryRun&&rmSync3(cacheDir,{recursive:!0,force:!0}),rmSync3(cleanSourceDir,{recursive:!0,force:!0}),rmSync3(reportsDir,{recursive:!0,force:!0}),ensureDir(reportsDir),ensureDir(cacheDir),copyWorkspaceForPreprocess(sourceDir,cleanSourceDir);let cache=loadAssetCache(cacheFile,sourceDir),previousLock=loadLockState(lockFile),lockRun=args.dryRun?{lock:defaultLockState(),interruptedItems:0}:beginLockRun(lockFile,previousLock),lock=lockRun.lock,cacheContext={enabled:!args.dryRun&&args.resume!==!1,cacheDir,cacheFile,cache,lockFile,lock,warnings:[],stats:{resumed_from_cache:!1,remote_reused:0,local_reused:0,interrupted_items_count:lockRun.interruptedItems}};cacheContext.stats.interrupted_items_count>0&&(cacheContext.stats.resumed_from_cache=!0,cacheContext.warnings.push(`\u68C0\u6D4B\u5230\u4E0A\u6B21\u9884\u5904\u7406\u53EF\u80FD\u4E2D\u65AD\uFF1B\u5C06\u5C1D\u8BD5\u4ECE\u672C\u5730 cache \u6062\u590D\uFF08\u4E2D\u65AD\u9879: ${cacheContext.stats.interrupted_items_count}\uFF09\u3002`));let files=walkFiles(cleanSourceDir,args.include),assetFiles=walkAssetFiles(cleanSourceDir),candidates=collectRemoteCandidates(cleanSourceDir,files),localAssetCandidates=collectLocalAssetCandidates(cleanSourceDir,files,assetFiles),report=buildReport(cleanSourceDir,files,candidates,reportsDir);report.execution_mode=args.dryRun?"dry-run":"apply",report.local_asset_candidates=localAssetCandidates,report.summary.local_asset_count=localAssetCandidates.length;let detectedType=detectProjectType(sourceDir,args.type),upstreamSourcePackageBytes=collectSourcePackageBytes(sourceDir),cleanSourcePackageBytesBeforeRewrite=collectSourcePackageBytes(cleanSourceDir),pathBaseViolationsDetected=collectPathBaseViolations(cleanSourceDir,files),preflightWarnings=collectPreflightWarnings(cleanSourceDir,localAssetCandidates);cacheContext.enabled&&(lock=updateLockState(lockFile,lock,{phase:"rewrite_path_base"}),cacheContext.lock=lock);let pathBaseRewriteResult=await runPathBaseRewrite(args,report,files),pathBaseViolationsRemaining=collectPathBaseViolations(cleanSourceDir,files);writeJson2(join12(reportsDir,"preflight-report.json"),buildPreflightPayload(report,sourceDir,cleanSourceDir,{detectedType,upstreamSourcePackageBytes,cleanSourcePackageBytesBeforeRewrite,pathBaseViolationsDetected,pathBaseRewrites:pathBaseRewriteResult.rewrite_entries,pathBaseViolationsRemaining,preflightWarnings})),writeFileSync10(join12(reportsDir,"preflight-report.md"),`${renderMarkdown(report)}
2415
+ `,"utf8")}async function runPreprocess(args,sourceDir){let preprocessRoot=join12(sourceDir,".design-preprocess"),cleanSourceDir=join12(preprocessRoot,"clean-source"),reportsDir=join12(preprocessRoot,"reports"),cacheDir=join12(preprocessRoot,"cache"),cacheFile=join12(cacheDir,"assets.json"),lockFile=join12(cacheDir,"locks.json");args.resetCache&&!args.dryRun&&rmSync4(cacheDir,{recursive:!0,force:!0}),rmSync4(cleanSourceDir,{recursive:!0,force:!0}),rmSync4(reportsDir,{recursive:!0,force:!0}),ensureDir(reportsDir),ensureDir(cacheDir),copyWorkspaceForPreprocess(sourceDir,cleanSourceDir);let cache=loadAssetCache(cacheFile,sourceDir),previousLock=loadLockState(lockFile),lockRun=args.dryRun?{lock:defaultLockState(),interruptedItems:0}:beginLockRun(lockFile,previousLock),lock=lockRun.lock,cacheContext={enabled:!args.dryRun&&args.resume!==!1,cacheDir,cacheFile,cache,lockFile,lock,warnings:[],stats:{resumed_from_cache:!1,remote_reused:0,local_reused:0,interrupted_items_count:lockRun.interruptedItems}};cacheContext.stats.interrupted_items_count>0&&(cacheContext.stats.resumed_from_cache=!0,cacheContext.warnings.push(`\u68C0\u6D4B\u5230\u4E0A\u6B21\u9884\u5904\u7406\u53EF\u80FD\u4E2D\u65AD\uFF1B\u5C06\u5C1D\u8BD5\u4ECE\u672C\u5730 cache \u6062\u590D\uFF08\u4E2D\u65AD\u9879: ${cacheContext.stats.interrupted_items_count}\uFF09\u3002`));let files=walkFiles(cleanSourceDir,args.include),assetFiles=walkAssetFiles(cleanSourceDir),candidates=collectRemoteCandidates(cleanSourceDir,files),localAssetCandidates=collectLocalAssetCandidates(cleanSourceDir,files,assetFiles),report=buildReport(cleanSourceDir,files,candidates,reportsDir);report.execution_mode=args.dryRun?"dry-run":"apply",report.local_asset_candidates=localAssetCandidates,report.summary.local_asset_count=localAssetCandidates.length;let detectedType=detectProjectType(sourceDir,args.type),upstreamSourcePackageBytes=collectSourcePackageBytes(sourceDir),cleanSourcePackageBytesBeforeRewrite=collectSourcePackageBytes(cleanSourceDir),pathBaseViolationsDetected=collectPathBaseViolations(cleanSourceDir,files),preflightWarnings=collectPreflightWarnings(cleanSourceDir,localAssetCandidates);cacheContext.enabled&&(lock=updateLockState(lockFile,lock,{phase:"rewrite_path_base"}),cacheContext.lock=lock);let pathBaseRewriteResult=await runPathBaseRewrite(args,report,files),pathBaseViolationsRemaining=collectPathBaseViolations(cleanSourceDir,files);writeJson2(join12(reportsDir,"preflight-report.json"),buildPreflightPayload(report,sourceDir,cleanSourceDir,{detectedType,upstreamSourcePackageBytes,cleanSourcePackageBytesBeforeRewrite,pathBaseViolationsDetected,pathBaseRewrites:pathBaseRewriteResult.rewrite_entries,pathBaseViolationsRemaining,preflightWarnings})),writeFileSync10(join12(reportsDir,"preflight-report.md"),`${renderMarkdown(report)}
2413
2416
  `,"utf8");let rewriteResult=await runRewrite(args,report,cacheContext),localUploadResult=await runUploadLocal(args,report,cacheContext),localUploadFullReport={...report,mode:"upload-local",uploaded_assets:[],uploaded_local_assets:localUploadResult.uploaded_local_assets,rewritten_files:[],warnings:[...localUploadResult.warnings]};writeJson2(join12(reportsDir,"local-asset-report.json"),localUploadFullReport),writeFileSync10(join12(reportsDir,"local-asset-report.md"),`${renderMarkdown(localUploadFullReport)}
2414
2417
  `,"utf8");let localRewriteResult=await runRewriteLocal({...args,localReport:join12(reportsDir,"local-asset-report.json")},report,files,cacheContext);(cacheContext.stats.remote_reused>0||cacheContext.stats.local_reused>0)&&(cacheContext.stats.resumed_from_cache=!0);let assetInventory=buildAssetInventoryPayload(report,rewriteResult,localUploadResult,sourceDir,cleanSourceDir),importManifestWithCache=buildImportManifest(report,rewriteResult,localUploadResult,localRewriteResult,pathBaseRewriteResult,sourceDir,cleanSourceDir,cacheContext),warningsPayload=buildWarningsPayload(report,importManifestWithCache,reportsDir,cacheContext);return writeJson2(join12(reportsDir,"asset-inventory.json"),assetInventory),writeJson2(join12(reportsDir,"import-manifest.json"),importManifestWithCache),writeJson2(join12(reportsDir,"warnings.json"),warningsPayload),writeJson2(join12(reportsDir,"pending-videos.json"),{pending_videos:report.pending_videos}),writeFileSync10(join12(reportsDir,"import-manifest.md"),`${renderMarkdown({...report,mode:"preprocess",uploaded_assets:rewriteResult.uploaded_assets,uploaded_local_assets:localUploadResult.uploaded_local_assets,rewritten_files:importManifestWithCache.rewritten_files,deleted_clean_source_assets:importManifestWithCache.deleted_clean_source_assets,warnings:importManifestWithCache.warnings})}
2415
- `,"utf8"),cacheContext.enabled&&(cacheContext.lock=completeLockRun(lockFile,cacheContext.lock)),{preprocess_root:preprocessRoot,clean_source_dir:cleanSourceDir,reports_dir:reportsDir,cache_dir:cacheDir,report,pathBaseRewriteResult,rewriteResult,localUploadResult,localRewriteResult,importManifest:importManifestWithCache,cacheContext}}async function runAppImportPreprocessCli(argv){let args=parseArgs2(argv);if(args.help){printAppImportPreprocessUsage();return}let rootDir=resolve8(args.dir||process.env.PLATFORM_INVOCATION_CWD||process.env.INIT_CWD||process.cwd()),stats=statSync5(rootDir,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${rootDir}`);let result=await runPreprocess(args,rootDir),warnings=result.importManifest.warnings,output={tool:"assetize-project-urls",version:1,mode:"preprocess",execution_mode:args.dryRun?"dry-run":"apply",source_dir:rootDir,clean_source_dir:result.clean_source_dir,reports_dir:result.reports_dir,cache_dir:result.cache_dir,summary:result.report.summary,planned_actions:result.importManifest.planned_actions,path_base_rewritten_files:result.pathBaseRewriteResult.rewritten_files.length,uploaded_assets:countAppliedRemoteUploads(result.rewriteResult),uploaded_local_assets:countAppliedLocalUploads(result.localUploadResult),resumed_from_cache:result.importManifest.resumed_from_cache,reused_uploaded_assets:result.importManifest.reused_uploaded_assets_count,reused_uploaded_local_assets:result.importManifest.reused_uploaded_local_assets_count,interrupted_items_count:result.importManifest.interrupted_items_count,rewritten_files:args.dryRun?0:result.importManifest.rewritten_files.length,deleted_clean_source_assets:args.dryRun?0:result.importManifest.deleted_clean_source_assets.length,warnings,report_files:{preflight_report:join12(result.reports_dir,"preflight-report.json"),asset_inventory:join12(result.reports_dir,"asset-inventory.json"),import_manifest:join12(result.reports_dir,"import-manifest.json"),warnings:join12(result.reports_dir,"warnings.json"),pending_videos:join12(result.reports_dir,"pending-videos.json")}};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2418
+ `,"utf8"),cacheContext.enabled&&(cacheContext.lock=completeLockRun(lockFile,cacheContext.lock)),{preprocess_root:preprocessRoot,clean_source_dir:cleanSourceDir,reports_dir:reportsDir,cache_dir:cacheDir,report,pathBaseRewriteResult,rewriteResult,localUploadResult,localRewriteResult,importManifest:importManifestWithCache,cacheContext}}async function runAppImportPreprocessCli(argv){let args=parseArgs2(argv);if(args.help){printAppImportPreprocessUsage();return}let rootDir=resolve9(args.dir||process.env.PLATFORM_INVOCATION_CWD||process.env.INIT_CWD||process.cwd()),stats=statSync5(rootDir,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${rootDir}`);let result=await runPreprocess(args,rootDir),warnings=result.importManifest.warnings,output={tool:"assetize-project-urls",version:1,mode:"preprocess",execution_mode:args.dryRun?"dry-run":"apply",source_dir:rootDir,clean_source_dir:result.clean_source_dir,reports_dir:result.reports_dir,cache_dir:result.cache_dir,summary:result.report.summary,planned_actions:result.importManifest.planned_actions,path_base_rewritten_files:result.pathBaseRewriteResult.rewritten_files.length,uploaded_assets:countAppliedRemoteUploads(result.rewriteResult),uploaded_local_assets:countAppliedLocalUploads(result.localUploadResult),resumed_from_cache:result.importManifest.resumed_from_cache,reused_uploaded_assets:result.importManifest.reused_uploaded_assets_count,reused_uploaded_local_assets:result.importManifest.reused_uploaded_local_assets_count,interrupted_items_count:result.importManifest.interrupted_items_count,rewritten_files:args.dryRun?0:result.importManifest.rewritten_files.length,deleted_clean_source_assets:args.dryRun?0:result.importManifest.deleted_clean_source_assets.length,warnings,report_files:{preflight_report:join12(result.reports_dir,"preflight-report.json"),asset_inventory:join12(result.reports_dir,"asset-inventory.json"),import_manifest:join12(result.reports_dir,"import-manifest.json"),warnings:join12(result.reports_dir,"warnings.json"),pending_videos:join12(result.reports_dir,"pending-videos.json")}};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2416
2419
  `);return}process.stdout.write(["third-party design preprocess completed",`mode: ${output.mode}`,`execution_mode: ${output.execution_mode}`,`source_dir: ${output.source_dir}`,`clean_source_dir: ${output.clean_source_dir}`,`cache_dir: ${output.cache_dir}`,`scanned_files: ${output.summary.scanned_file_count}`,`unique_remote_candidates: ${output.summary.unique_remote_candidates}`,`local_images: ${output.summary.local_asset_count}`,`planned_remote_upload_candidates: ${output.planned_actions.remote_upload_candidates}`,`planned_local_upload_candidates: ${output.planned_actions.local_upload_candidates}`,`planned_file_rewrite_candidates: ${output.planned_actions.file_rewrite_candidates}`,`planned_local_cleanup_candidates: ${output.planned_actions.local_cleanup_candidates}`,`path_base_rewritten_files: ${output.path_base_rewritten_files}`,`uploaded_assets: ${output.uploaded_assets}`,`uploaded_local_assets: ${output.uploaded_local_assets}`,`resumed_from_cache: ${output.resumed_from_cache}`,`reused_uploaded_assets: ${output.reused_uploaded_assets}`,`reused_uploaded_local_assets: ${output.reused_uploaded_local_assets}`,`interrupted_items_count: ${output.interrupted_items_count}`,`rewritten_files: ${output.rewritten_files}`,`deleted_clean_source_assets: ${output.deleted_clean_source_assets}`,`warnings: ${output.warnings.length}`,`preflight_report: ${output.report_files.preflight_report}`,`import_manifest: ${output.report_files.import_manifest}`].join(`
2417
2420
  `)+`
2418
- `)}import{cpSync as cpSync3,existsSync as existsSync17,mkdirSync as mkdirSync10,readFileSync as readFileSync17,readdirSync as readdirSync6,rmSync as rmSync4,statSync as statSync6,writeFileSync as writeFileSync11}from"node:fs";import{basename as basename3,dirname as dirname11,join as join13,resolve as resolve9}from"node:path";var WORKSPACE_REQUIRED_FILES=["app.yaml","package.json"],REPORT_FILE_NAMES=["import-manifest.json","preflight-report.json","asset-inventory.json","warnings.json","pending-videos.json"],TOP_LEVEL_IMPORT_CANDIDATES=["src","public","_videos","guidelines","index.html","README.md","ATTRIBUTIONS.md"],SKIP_DIRS=new Set([".git","node_modules","dist","build",".platform",".sandbox",".design-preprocess",".third-party-design-reports"]);function printAppImportStageUsage(){process.stdout.write(["platform app import stage","","\u7528\u6CD5\uFF1A"," platform app import stage [--workspace-dir <template-workspace-dir>] --preprocess <source-dir|.design-preprocess|reports|import-manifest.json> [--dry-run] [--json]","","\u4F5C\u7528\uFF1A"," \u5C06\u9884\u5904\u7406\u4EA7\u7269\u4EE5\u975E\u7834\u574F\u65B9\u5F0F stage \u5230\u6A21\u677F\u5DE5\u4F5C\u533A `.design-import/`\uFF0C\u4E0D\u76F4\u63A5\u8986\u76D6\u6A21\u677F\u5165\u53E3\u4E0E\u8FD0\u884C\u5951\u7EA6\u6587\u4EF6\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002",""].join(`
2421
+ `)}import{cpSync as cpSync3,existsSync as existsSync17,mkdirSync as mkdirSync10,readFileSync as readFileSync17,readdirSync as readdirSync6,rmSync as rmSync5,statSync as statSync6,writeFileSync as writeFileSync11}from"node:fs";import{basename as basename4,dirname as dirname11,join as join13,resolve as resolve10}from"node:path";var WORKSPACE_REQUIRED_FILES=["app.yaml","package.json"],REPORT_FILE_NAMES=["import-manifest.json","preflight-report.json","asset-inventory.json","warnings.json","pending-videos.json"],TOP_LEVEL_IMPORT_CANDIDATES=["src","public","_videos","guidelines","index.html","README.md","ATTRIBUTIONS.md"],SKIP_DIRS=new Set([".git","node_modules","dist","build",".platform",".sandbox",".design-preprocess",".third-party-design-reports"]);function printAppImportStageUsage(){process.stdout.write(["platform app import stage","","\u7528\u6CD5\uFF1A"," platform app import stage [--workspace-dir <template-workspace-dir>] --preprocess <source-dir|.design-preprocess|reports|import-manifest.json> [--dry-run] [--json]","","\u4F5C\u7528\uFF1A"," \u5C06\u9884\u5904\u7406\u4EA7\u7269\u4EE5\u975E\u7834\u574F\u65B9\u5F0F stage \u5230\u6A21\u677F\u5DE5\u4F5C\u533A `.design-import/`\uFF0C\u4E0D\u76F4\u63A5\u8986\u76D6\u6A21\u677F\u5165\u53E3\u4E0E\u8FD0\u884C\u5951\u7EA6\u6587\u4EF6\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002",""].join(`
2419
2422
  `))}function parseArgs3(argv){let result={workspaceDir:"",preprocess:"",dryRun:!1,json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--dry-run"){result.dryRun=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--workspace-dir"){result.workspaceDir=argv[index+1]??"",index+=1;continue}if(arg==="--preprocess"){result.preprocess=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function ensureDir2(dirPath){mkdirSync10(dirPath,{recursive:!0})}function writeJson3(filePath,payload){writeFileSync11(filePath,`${JSON.stringify(payload,null,2)}
2420
- `,"utf8")}function readJson2(filePath){return JSON.parse(readFileSync17(filePath,"utf8"))}function assertDirectory2(pathValue,label){let stats=statSync6(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function resolveManifestPath(inputPath){let absolute=resolve9(inputPath),stats=statSync6(absolute,{throwIfNoEntry:!1});if(!stats)throw new Error(`\u672A\u627E\u5230\u9884\u5904\u7406\u8F93\u5165: ${absolute}`);if(stats.isFile()){if(basename3(absolute)!=="import-manifest.json")throw new Error(`\u9884\u5904\u7406\u8F93\u5165\u6587\u4EF6\u5FC5\u987B\u662F import-manifest.json: ${absolute}`);return absolute}let candidates=[join13(absolute,"reports","import-manifest.json"),join13(absolute,"import-manifest.json"),join13(absolute,".design-preprocess","reports","import-manifest.json")];for(let candidate of candidates)if(existsSync17(candidate))return candidate;throw new Error(`\u65E0\u6CD5\u4ECE\u9884\u5904\u7406\u8F93\u5165\u89E3\u6790 import-manifest.json: ${absolute}`)}function validateWorkspace2(workspaceDir){assertDirectory2(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=WORKSPACE_REQUIRED_FILES.filter(file=>!existsSync17(join13(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function topLevelEntries(rootDir){return readdirSync6(rootDir,{withFileTypes:!0}).filter(entry=>!SKIP_DIRS.has(entry.name)).map(entry=>({name:entry.name,kind:entry.isDirectory()?"dir":entry.isFile()?"file":"other"})).sort((left,right)=>left.name.localeCompare(right.name))}function collectImportCandidates(cleanSourceDir,layout,sourceDetectedType){return topLevelEntries(cleanSourceDir).filter(entry=>TOP_LEVEL_IMPORT_CANDIDATES.includes(entry.name)).map(entry=>({path:entry.name,kind:entry.kind,suggested_target:entry.name==="src"?sourceDetectedType==="frontend-app"?`workspace/${layout.imported_upstream_root}/ (\u6309 pages/components/styles/lib/imports \u53D7\u63A7\u5E76\u5165)`:`workspace/.design-import/upstream-clean-source/${entry.name}`:entry.name==="_videos"?"workspace/public/imported-upstream/_videos/ \u6216\u6A21\u677F\u9759\u6001\u8D44\u6E90\u76EE\u5F55":entry.name==="public"?"workspace/public/imported-upstream/ (\u9700\u4EBA\u5DE5\u5BA1\u67E5\u51B2\u7A81)":`workspace/.design-import/upstream-clean-source/${entry.name}`}))}function collectPreservedWorkspaceFiles(workspaceDir,layout){return layout.preserved_workspace_files.filter(file=>existsSync17(join13(workspaceDir,file)))}function buildImportSummary(args,payload){let sourcePreprocessExecutionMode=payload.importManifest.execution_mode??"unknown",warnings=[];return sourcePreprocessExecutionMode==="dry-run"&&warnings.push("\u5F53\u524D\u9884\u5904\u7406\u4EA7\u7269\u6765\u81EA dry-run\uFF1Bstaged clean source \u4ECD\u53EF\u80FD\u5305\u542B\u672A\u771F\u5B9E\u56DE\u5199\u6216\u672A\u6E05\u7406\u7684\u672C\u5730\u7D20\u6750\u3002"),{tool:"import-clean-source",version:1,mode:"import-stage",execution_mode:args.dryRun?"dry-run":"apply",workspace_dir:payload.workspaceDir,preprocess_manifest:payload.manifestPath,source_dir:payload.importManifest.source_dir,clean_source_dir:payload.importManifest.clean_source_dir,source_preprocess_execution_mode:sourcePreprocessExecutionMode,target_template_key:payload.layout.template_key,frontend_root:payload.layout.frontend_root,imported_upstream_root:payload.layout.imported_upstream_root,staged_clean_source_dir:payload.stagedCleanSourceDir,staged_reports_dir:payload.stagedReportsDir,source_detected_type:payload.preflightReport.detected_type??"unknown",clean_source_package_bytes:payload.importManifest.clean_source_package_bytes??null,upstream_source_package_bytes:payload.preflightReport.upstream_source_package_bytes??null,import_candidates:collectImportCandidates(payload.importManifest.clean_source_dir,payload.layout,payload.preflightReport.detected_type??"unknown"),preserved_workspace_files:collectPreservedWorkspaceFiles(payload.workspaceDir,payload.layout),pending_videos_count:Array.isArray(payload.importManifest.pending_videos)?payload.importManifest.pending_videos.length:0,pending_manual_items_count:Array.isArray(payload.warningsReport.pending_manual_items)?payload.warningsReport.pending_manual_items.length:0,warnings,next_steps:["\u5148\u5728 .design-import/upstream-clean-source \u4E2D\u5BA1\u67E5\u4E0A\u6E38 clean source",`\u518D\u6309 import_candidates \u9009\u62E9\u6027\u5408\u5E76\u5230\u6A21\u677F\u5DE5\u4F5C\u533A\u7684 ${payload.layout.frontend_root}/public \u7B49\u76EE\u5F55`,"\u4FDD\u7559\u6A21\u677F\u4E3B\u5BFC\u6587\u4EF6\uFF08app.yaml / package.json / vite.config.ts / \u8FD0\u884C\u5165\u53E3 / platform \u5C42\uFF09\u4E0D\u88AB\u8986\u76D6","\u5B8C\u6210\u9875\u9762\u5408\u5E76\u540E\uFF0C\u518D\u6267\u884C platform dev / verify / preview"]}}function stageReports(sourceReportsDir,stagedReportsDir,dryRun){let copied=[];for(let fileName of REPORT_FILE_NAMES){let sourcePath=join13(sourceReportsDir,fileName);existsSync17(sourcePath)&&(copied.push(fileName),dryRun||cpSync3(sourcePath,join13(stagedReportsDir,fileName)))}return copied}async function runAppImportStageCli(argv){let args=parseArgs3(argv);if(args.help){printAppImportStageUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");if(!args.preprocess)throw new Error("\u7F3A\u5C11 `--preprocess <source-dir|.design-preprocess|reports|import-manifest.json>`\u3002");let workspaceDir=resolve9(args.workspaceDir);validateWorkspace2(workspaceDir);let manifestPath=resolveManifestPath(args.preprocess),reportsDir=resolve9(dirname11(manifestPath)),importManifest=readJson2(manifestPath),preflightReport=readJson2(join13(reportsDir,"preflight-report.json")),warningsReport=readJson2(join13(reportsDir,"warnings.json")),cleanSourceDir=resolve9(importManifest.clean_source_dir);assertDirectory2(cleanSourceDir,"clean-source");let layout=resolveAppImportLayout(workspaceDir),designImportRoot=join13(workspaceDir,".design-import"),stagedCleanSourceDir=join13(designImportRoot,"upstream-clean-source"),stagedReportsDir=join13(designImportRoot,"reports");args.dryRun||(rmSync4(designImportRoot,{recursive:!0,force:!0}),ensureDir2(stagedReportsDir),cpSync3(cleanSourceDir,stagedCleanSourceDir,{recursive:!0}));let copiedReports=stageReports(reportsDir,stagedReportsDir,args.dryRun),summary=buildImportSummary(args,{workspaceDir,manifestPath,importManifest,preflightReport,warningsReport,layout,stagedCleanSourceDir,stagedReportsDir});args.dryRun||writeJson3(join13(designImportRoot,"import-summary.json"),summary);let output={...summary,copied_report_files:copiedReports};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2423
+ `,"utf8")}function readJson2(filePath){return JSON.parse(readFileSync17(filePath,"utf8"))}function assertDirectory2(pathValue,label){let stats=statSync6(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function resolveManifestPath(inputPath){let absolute=resolve10(inputPath),stats=statSync6(absolute,{throwIfNoEntry:!1});if(!stats)throw new Error(`\u672A\u627E\u5230\u9884\u5904\u7406\u8F93\u5165: ${absolute}`);if(stats.isFile()){if(basename4(absolute)!=="import-manifest.json")throw new Error(`\u9884\u5904\u7406\u8F93\u5165\u6587\u4EF6\u5FC5\u987B\u662F import-manifest.json: ${absolute}`);return absolute}let candidates=[join13(absolute,"reports","import-manifest.json"),join13(absolute,"import-manifest.json"),join13(absolute,".design-preprocess","reports","import-manifest.json")];for(let candidate of candidates)if(existsSync17(candidate))return candidate;throw new Error(`\u65E0\u6CD5\u4ECE\u9884\u5904\u7406\u8F93\u5165\u89E3\u6790 import-manifest.json: ${absolute}`)}function validateWorkspace2(workspaceDir){assertDirectory2(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=WORKSPACE_REQUIRED_FILES.filter(file=>!existsSync17(join13(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function topLevelEntries(rootDir){return readdirSync6(rootDir,{withFileTypes:!0}).filter(entry=>!SKIP_DIRS.has(entry.name)).map(entry=>({name:entry.name,kind:entry.isDirectory()?"dir":entry.isFile()?"file":"other"})).sort((left,right)=>left.name.localeCompare(right.name))}function collectImportCandidates(cleanSourceDir,layout,sourceDetectedType){return topLevelEntries(cleanSourceDir).filter(entry=>TOP_LEVEL_IMPORT_CANDIDATES.includes(entry.name)).map(entry=>({path:entry.name,kind:entry.kind,suggested_target:entry.name==="src"?sourceDetectedType==="frontend-app"?`workspace/${layout.imported_upstream_root}/ (\u6309 pages/components/styles/lib/imports \u53D7\u63A7\u5E76\u5165)`:`workspace/.design-import/upstream-clean-source/${entry.name}`:entry.name==="_videos"?"workspace/public/imported-upstream/_videos/ \u6216\u6A21\u677F\u9759\u6001\u8D44\u6E90\u76EE\u5F55":entry.name==="public"?"workspace/public/imported-upstream/ (\u9700\u4EBA\u5DE5\u5BA1\u67E5\u51B2\u7A81)":`workspace/.design-import/upstream-clean-source/${entry.name}`}))}function collectPreservedWorkspaceFiles(workspaceDir,layout){return layout.preserved_workspace_files.filter(file=>existsSync17(join13(workspaceDir,file)))}function buildImportSummary(args,payload){let sourcePreprocessExecutionMode=payload.importManifest.execution_mode??"unknown",warnings=[];return sourcePreprocessExecutionMode==="dry-run"&&warnings.push("\u5F53\u524D\u9884\u5904\u7406\u4EA7\u7269\u6765\u81EA dry-run\uFF1Bstaged clean source \u4ECD\u53EF\u80FD\u5305\u542B\u672A\u771F\u5B9E\u56DE\u5199\u6216\u672A\u6E05\u7406\u7684\u672C\u5730\u7D20\u6750\u3002"),{tool:"import-clean-source",version:1,mode:"import-stage",execution_mode:args.dryRun?"dry-run":"apply",workspace_dir:payload.workspaceDir,preprocess_manifest:payload.manifestPath,source_dir:payload.importManifest.source_dir,clean_source_dir:payload.importManifest.clean_source_dir,source_preprocess_execution_mode:sourcePreprocessExecutionMode,target_template_key:payload.layout.template_key,frontend_root:payload.layout.frontend_root,imported_upstream_root:payload.layout.imported_upstream_root,staged_clean_source_dir:payload.stagedCleanSourceDir,staged_reports_dir:payload.stagedReportsDir,source_detected_type:payload.preflightReport.detected_type??"unknown",clean_source_package_bytes:payload.importManifest.clean_source_package_bytes??null,upstream_source_package_bytes:payload.preflightReport.upstream_source_package_bytes??null,import_candidates:collectImportCandidates(payload.importManifest.clean_source_dir,payload.layout,payload.preflightReport.detected_type??"unknown"),preserved_workspace_files:collectPreservedWorkspaceFiles(payload.workspaceDir,payload.layout),pending_videos_count:Array.isArray(payload.importManifest.pending_videos)?payload.importManifest.pending_videos.length:0,pending_manual_items_count:Array.isArray(payload.warningsReport.pending_manual_items)?payload.warningsReport.pending_manual_items.length:0,warnings,next_steps:["\u5148\u5728 .design-import/upstream-clean-source \u4E2D\u5BA1\u67E5\u4E0A\u6E38 clean source",`\u518D\u6309 import_candidates \u9009\u62E9\u6027\u5408\u5E76\u5230\u6A21\u677F\u5DE5\u4F5C\u533A\u7684 ${payload.layout.frontend_root}/public \u7B49\u76EE\u5F55`,"\u4FDD\u7559\u6A21\u677F\u4E3B\u5BFC\u6587\u4EF6\uFF08app.yaml / package.json / vite.config.ts / \u8FD0\u884C\u5165\u53E3 / platform \u5C42\uFF09\u4E0D\u88AB\u8986\u76D6","\u5B8C\u6210\u9875\u9762\u5408\u5E76\u540E\uFF0C\u518D\u6267\u884C platform dev / verify / preview"]}}function stageReports(sourceReportsDir,stagedReportsDir,dryRun){let copied=[];for(let fileName of REPORT_FILE_NAMES){let sourcePath=join13(sourceReportsDir,fileName);existsSync17(sourcePath)&&(copied.push(fileName),dryRun||cpSync3(sourcePath,join13(stagedReportsDir,fileName)))}return copied}async function runAppImportStageCli(argv){let args=parseArgs3(argv);if(args.help){printAppImportStageUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");if(!args.preprocess)throw new Error("\u7F3A\u5C11 `--preprocess <source-dir|.design-preprocess|reports|import-manifest.json>`\u3002");let workspaceDir=resolve10(args.workspaceDir);validateWorkspace2(workspaceDir);let manifestPath=resolveManifestPath(args.preprocess),reportsDir=resolve10(dirname11(manifestPath)),importManifest=readJson2(manifestPath),preflightReport=readJson2(join13(reportsDir,"preflight-report.json")),warningsReport=readJson2(join13(reportsDir,"warnings.json")),cleanSourceDir=resolve10(importManifest.clean_source_dir);assertDirectory2(cleanSourceDir,"clean-source");let layout=resolveAppImportLayout(workspaceDir),designImportRoot=join13(workspaceDir,".design-import"),stagedCleanSourceDir=join13(designImportRoot,"upstream-clean-source"),stagedReportsDir=join13(designImportRoot,"reports");args.dryRun||(rmSync5(designImportRoot,{recursive:!0,force:!0}),ensureDir2(stagedReportsDir),cpSync3(cleanSourceDir,stagedCleanSourceDir,{recursive:!0}));let copiedReports=stageReports(reportsDir,stagedReportsDir,args.dryRun),summary=buildImportSummary(args,{workspaceDir,manifestPath,importManifest,preflightReport,warningsReport,layout,stagedCleanSourceDir,stagedReportsDir});args.dryRun||writeJson3(join13(designImportRoot,"import-summary.json"),summary);let output={...summary,copied_report_files:copiedReports};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2421
2424
  `);return}process.stdout.write(["third-party design import stage completed",`execution_mode: ${output.execution_mode}`,`workspace_dir: ${output.workspace_dir}`,`source_detected_type: ${output.source_detected_type}`,`staged_clean_source_dir: ${output.staged_clean_source_dir}`,`staged_reports_dir: ${output.staged_reports_dir}`,`import_candidates: ${output.import_candidates.length}`,`preserved_workspace_files: ${output.preserved_workspace_files.length}`,`pending_videos_count: ${output.pending_videos_count}`,`pending_manual_items_count: ${output.pending_manual_items_count}`].join(`
2422
2425
  `)+`
2423
- `)}import{existsSync as existsSync18,readFileSync as readFileSync18,statSync as statSync7}from"node:fs";import{join as join14,resolve as resolve10}from"node:path";var REQUIRED_WORKSPACE_FILES2=["app.yaml","package.json"];function printAppImportVerifyUsage(){process.stdout.write(["platform app import verify","","\u7528\u6CD5\uFF1A"," platform app import verify [--workspace-dir <template-workspace-dir>] [--json]","","\u4F5C\u7528\uFF1A"," \u6821\u9A8C\u6A21\u677F\u5DE5\u4F5C\u533A\u662F\u5426\u5DF2\u5177\u5907 preprocess / stage / merge \u7684\u57FA\u7840\u4EA7\u7269\uFF0C\u5E76\u8F93\u51FA\u4E0B\u4E00\u6B65\u5EFA\u8BAE\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002"," - verify \u53EA\u505A\u72B6\u6001\u6821\u9A8C\uFF0C\u4E0D\u4F1A\u6267\u884C\u7D20\u6750\u4E0A\u4F20\u3001\u6587\u4EF6\u642C\u8FD0\u6216\u6A21\u677F\u63A5\u7EBF\u3002",""].join(`
2424
- `))}function parseArgs4(argv){let result={workspaceDir:"",json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--workspace-dir"){result.workspaceDir=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function readJsonIfExists3(filePath,fallbackValue=null){return existsSync18(filePath)?JSON.parse(readFileSync18(filePath,"utf8")):fallbackValue}function assertDirectory3(pathValue,label){let stats=statSync7(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function validateWorkspace3(workspaceDir){assertDirectory3(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=REQUIRED_WORKSPACE_FILES2.filter(file=>!existsSync18(join14(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function listMissingItems(state){let missing=[];return state.hasPreprocessManifest||missing.push(".design-import/reports/import-manifest.json"),state.hasPreflightReport||missing.push(".design-import/reports/preflight-report.json"),state.hasWarningsReport||missing.push(".design-import/reports/warnings.json"),state.hasImportSummary||missing.push(".design-import/import-summary.json"),state.mergeRequired&&(state.hasMergeSummary||missing.push(".design-import/merge-summary.json"),state.hasImportedUpstreamDir||missing.push(`${state.importedUpstreamRoot}/`)),missing}function deriveStatus(state){return state.hasImportSummary?state.mergeRequired&&(!state.hasMergeSummary||!state.hasImportedUpstreamDir)?"needs_merge":state.sourcePreprocessExecutionMode==="dry-run"?"needs_apply_preprocess":"ready_for_manual_wiring":"needs_stage"}function buildNextSteps(status,state){switch(status){case"needs_stage":return["\u5148\u6267\u884C platform app import stage --preprocess <source-dir|.design-preprocess|reports|import-manifest.json>","\u786E\u8BA4 .design-import/upstream-clean-source/ \u4E0E .design-import/reports/ \u5DF2\u751F\u6210"];case"needs_merge":return["\u6267\u884C platform app import merge",`\u786E\u8BA4 ${state.importedUpstreamRoot}/ \u5DF2\u751F\u6210\uFF0C\u518D\u5F00\u59CB\u4EBA\u5DE5\u63A5\u7EBF`];case"needs_apply_preprocess":return["\u5F53\u524D\u4E0A\u6E38\u9884\u5904\u7406\u4EA7\u7269\u6765\u81EA dry-run\uFF1B\u8BF7\u91CD\u65B0\u6267\u884C platform app import preprocess\uFF08\u975E --dry-run\uFF09","\u91CD\u65B0 stage / merge \u540E\u518D\u7EE7\u7EED\u6A21\u677F\u63A5\u7EBF"];default:return state.templateKey==="backend-app-node"?["\u5728 src/web/app.tsx \u6216 src/web/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9","\u4FDD\u6301 src/server/* \u4E0E src/web/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC\uFF0C\u518D\u7EE7\u7EED\u505A CMS / DB / Auth \u63A5\u5165","\u63A5\u7EBF\u5B8C\u6210\u540E\u518D\u6267\u884C platform dev / preview"]:["\u5728 src/app.tsx \u6216 src/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9","\u4FDD\u6301 src/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC\uFF0C\u518D\u7EE7\u7EED\u505A\u54CD\u5E94\u5F0F\u4FEE\u6B63\u4E0E CMS / DB / Auth \u63A5\u5165","\u63A5\u7EBF\u5B8C\u6210\u540E\u518D\u6267\u884C platform dev / preview"]}}async function runAppImportVerifyCli(argv){let args=parseArgs4(argv);if(args.help){printAppImportVerifyUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");let workspaceDir=resolve10(args.workspaceDir);validateWorkspace3(workspaceDir);let layout=resolveAppImportLayout(workspaceDir),designImportRoot=join14(workspaceDir,".design-import"),reportsDir=join14(designImportRoot,"reports"),importManifestPath=join14(reportsDir,"import-manifest.json"),preflightReportPath=join14(reportsDir,"preflight-report.json"),warningsReportPath=join14(reportsDir,"warnings.json"),importSummaryPath=join14(designImportRoot,"import-summary.json"),mergeSummaryPath=join14(designImportRoot,"merge-summary.json"),importedUpstreamDir=join14(workspaceDir,...layout.imported_upstream_root.split("/")),sourceContextPath=join14(workspaceDir,".platform","source-context.json"),importManifest=readJsonIfExists3(importManifestPath,{}),preflightReport=readJsonIfExists3(preflightReportPath,{}),warningsReport=readJsonIfExists3(warningsReportPath,{}),importSummary=readJsonIfExists3(importSummaryPath,{}),mergeSummary=readJsonIfExists3(mergeSummaryPath,{}),state={hasPreprocessManifest:existsSync18(importManifestPath),hasPreflightReport:existsSync18(preflightReportPath),hasWarningsReport:existsSync18(warningsReportPath),hasImportSummary:existsSync18(importSummaryPath),hasMergeSummary:existsSync18(mergeSummaryPath),hasImportedUpstreamDir:existsSync18(importedUpstreamDir),mergeRequired:!0,templateKey:layout.template_key,frontendRoot:layout.frontend_root,importedUpstreamRoot:layout.imported_upstream_root,hasSourceContext:existsSync18(sourceContextPath),sourcePreprocessExecutionMode:importSummary.source_preprocess_execution_mode||importManifest.execution_mode||"unknown",pendingVideosCount:Array.isArray(importManifest.pending_videos)?importManifest.pending_videos.length:Array.isArray(warningsReport.pending_videos)?warningsReport.pending_videos.length:0,pendingManualItemsCount:Array.isArray(warningsReport.pending_manual_items)?warningsReport.pending_manual_items.length:0,pathBaseViolationsRemaining:Array.isArray(preflightReport.path_base_violations_remaining)?preflightReport.path_base_violations_remaining.length:0,cleanSourcePackageBytes:importManifest.clean_source_package_bytes??null,upstreamSourcePackageBytes:preflightReport.upstream_source_package_bytes??null,mergedPathsCount:Array.isArray(mergeSummary.merged_paths)?mergeSummary.merged_paths.length:0},status=deriveStatus(state),output={tool:"app-import-verify",version:1,mode:"verify",workspace_dir:workspaceDir,design_import_dir:designImportRoot,target_template_key:layout.template_key,frontend_root:layout.frontend_root,imported_upstream_dir:layout.imported_upstream_root,status,state,missing_items:listMissingItems(state),next_steps:buildNextSteps(status,state)};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2426
+ `)}import{existsSync as existsSync18,readFileSync as readFileSync18,statSync as statSync7}from"node:fs";import{join as join14,resolve as resolve11}from"node:path";var REQUIRED_WORKSPACE_FILES2=["app.yaml","package.json"];function printAppImportVerifyUsage(){process.stdout.write(["platform app import verify","","\u7528\u6CD5\uFF1A"," platform app import verify [--workspace-dir <template-workspace-dir>] [--json]","","\u4F5C\u7528\uFF1A"," \u6821\u9A8C\u6A21\u677F\u5DE5\u4F5C\u533A\u662F\u5426\u5DF2\u5177\u5907 preprocess / stage / merge \u7684\u57FA\u7840\u4EA7\u7269\uFF0C\u5E76\u8F93\u51FA\u4E0B\u4E00\u6B65\u5EFA\u8BAE\u3002","","\u8BF4\u660E\uFF1A"," - \u9ED8\u8BA4\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u4F5C\u4E3A\u6A21\u677F\u5DE5\u4F5C\u533A\uFF1B\u82E5\u672A\u4F20 `--workspace-dir`\uFF0C\u5C06\u4F7F\u7528\u5F53\u524D\u5DE5\u4F5C\u76EE\u5F55\u3002"," - verify \u53EA\u505A\u72B6\u6001\u6821\u9A8C\uFF0C\u4E0D\u4F1A\u6267\u884C\u7D20\u6750\u4E0A\u4F20\u3001\u6587\u4EF6\u642C\u8FD0\u6216\u6A21\u677F\u63A5\u7EBF\u3002",""].join(`
2427
+ `))}function parseArgs4(argv){let result={workspaceDir:"",json:!1,help:!1};for(let index=0;index<argv.length;index+=1){let arg=argv[index];if(arg==="--help"||arg==="-h"){result.help=!0;continue}if(arg==="--json"){result.json=!0;continue}if(arg==="--workspace-dir"){result.workspaceDir=argv[index+1]??"",index+=1;continue}throw new Error(`\u672A\u77E5\u53C2\u6570: ${arg}`)}return result}function readJsonIfExists3(filePath,fallbackValue=null){return existsSync18(filePath)?JSON.parse(readFileSync18(filePath,"utf8")):fallbackValue}function assertDirectory3(pathValue,label){let stats=statSync7(pathValue,{throwIfNoEntry:!1});if(!stats||!stats.isDirectory())throw new Error(`${label} \u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u8BBF\u95EE: ${pathValue}`)}function validateWorkspace3(workspaceDir){assertDirectory3(workspaceDir,"\u6A21\u677F\u5DE5\u4F5C\u533A");let missing=REQUIRED_WORKSPACE_FILES2.filter(file=>!existsSync18(join14(workspaceDir,file)));if(missing.length>0)throw new Error(`\u76EE\u6807\u76EE\u5F55\u4E0D\u662F\u6709\u6548\u6A21\u677F\u5DE5\u4F5C\u533A\uFF0C\u7F3A\u5C11: ${missing.join(", ")}`)}function listMissingItems(state){let missing=[];return state.hasPreprocessManifest||missing.push(".design-import/reports/import-manifest.json"),state.hasPreflightReport||missing.push(".design-import/reports/preflight-report.json"),state.hasWarningsReport||missing.push(".design-import/reports/warnings.json"),state.hasImportSummary||missing.push(".design-import/import-summary.json"),state.mergeRequired&&(state.hasMergeSummary||missing.push(".design-import/merge-summary.json"),state.hasImportedUpstreamDir||missing.push(`${state.importedUpstreamRoot}/`)),missing}function deriveStatus(state){return state.hasImportSummary?state.mergeRequired&&(!state.hasMergeSummary||!state.hasImportedUpstreamDir)?"needs_merge":state.sourcePreprocessExecutionMode==="dry-run"?"needs_apply_preprocess":"ready_for_manual_wiring":"needs_stage"}function buildNextSteps(status,state){switch(status){case"needs_stage":return["\u5148\u6267\u884C platform app import stage --preprocess <source-dir|.design-preprocess|reports|import-manifest.json>","\u786E\u8BA4 .design-import/upstream-clean-source/ \u4E0E .design-import/reports/ \u5DF2\u751F\u6210"];case"needs_merge":return["\u6267\u884C platform app import merge",`\u786E\u8BA4 ${state.importedUpstreamRoot}/ \u5DF2\u751F\u6210\uFF0C\u518D\u5F00\u59CB\u4EBA\u5DE5\u63A5\u7EBF`];case"needs_apply_preprocess":return["\u5F53\u524D\u4E0A\u6E38\u9884\u5904\u7406\u4EA7\u7269\u6765\u81EA dry-run\uFF1B\u8BF7\u91CD\u65B0\u6267\u884C platform app import preprocess\uFF08\u975E --dry-run\uFF09","\u91CD\u65B0 stage / merge \u540E\u518D\u7EE7\u7EED\u6A21\u677F\u63A5\u7EBF"];default:return state.templateKey==="backend-app-node"?["\u5728 src/web/app.tsx \u6216 src/web/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9","\u4FDD\u6301 src/server/* \u4E0E src/web/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC\uFF0C\u518D\u7EE7\u7EED\u505A CMS / DB / Auth \u63A5\u5165","\u63A5\u7EBF\u5B8C\u6210\u540E\u518D\u6267\u884C platform dev / preview"]:["\u5728 src/app.tsx \u6216 src/pages/* \u4E2D\u9009\u62E9\u6027\u5F15\u7528 imported-upstream \u5185\u5BB9","\u4FDD\u6301 src/platform/* \u7531\u6A21\u677F\u4E3B\u5BFC\uFF0C\u518D\u7EE7\u7EED\u505A\u54CD\u5E94\u5F0F\u4FEE\u6B63\u4E0E CMS / DB / Auth \u63A5\u5165","\u63A5\u7EBF\u5B8C\u6210\u540E\u518D\u6267\u884C platform dev / preview"]}}async function runAppImportVerifyCli(argv){let args=parseArgs4(argv);if(args.help){printAppImportVerifyUsage();return}if(!args.workspaceDir)throw new Error("\u7F3A\u5C11 `--workspace-dir <template-workspace-dir>`\u3002");let workspaceDir=resolve11(args.workspaceDir);validateWorkspace3(workspaceDir);let layout=resolveAppImportLayout(workspaceDir),designImportRoot=join14(workspaceDir,".design-import"),reportsDir=join14(designImportRoot,"reports"),importManifestPath=join14(reportsDir,"import-manifest.json"),preflightReportPath=join14(reportsDir,"preflight-report.json"),warningsReportPath=join14(reportsDir,"warnings.json"),importSummaryPath=join14(designImportRoot,"import-summary.json"),mergeSummaryPath=join14(designImportRoot,"merge-summary.json"),importedUpstreamDir=join14(workspaceDir,...layout.imported_upstream_root.split("/")),sourceContextPath=join14(workspaceDir,".platform","source-context.json"),importManifest=readJsonIfExists3(importManifestPath,{}),preflightReport=readJsonIfExists3(preflightReportPath,{}),warningsReport=readJsonIfExists3(warningsReportPath,{}),importSummary=readJsonIfExists3(importSummaryPath,{}),mergeSummary=readJsonIfExists3(mergeSummaryPath,{}),state={hasPreprocessManifest:existsSync18(importManifestPath),hasPreflightReport:existsSync18(preflightReportPath),hasWarningsReport:existsSync18(warningsReportPath),hasImportSummary:existsSync18(importSummaryPath),hasMergeSummary:existsSync18(mergeSummaryPath),hasImportedUpstreamDir:existsSync18(importedUpstreamDir),mergeRequired:!0,templateKey:layout.template_key,frontendRoot:layout.frontend_root,importedUpstreamRoot:layout.imported_upstream_root,hasSourceContext:existsSync18(sourceContextPath),sourcePreprocessExecutionMode:importSummary.source_preprocess_execution_mode||importManifest.execution_mode||"unknown",pendingVideosCount:Array.isArray(importManifest.pending_videos)?importManifest.pending_videos.length:Array.isArray(warningsReport.pending_videos)?warningsReport.pending_videos.length:0,pendingManualItemsCount:Array.isArray(warningsReport.pending_manual_items)?warningsReport.pending_manual_items.length:0,pathBaseViolationsRemaining:Array.isArray(preflightReport.path_base_violations_remaining)?preflightReport.path_base_violations_remaining.length:0,cleanSourcePackageBytes:importManifest.clean_source_package_bytes??null,upstreamSourcePackageBytes:preflightReport.upstream_source_package_bytes??null,mergedPathsCount:Array.isArray(mergeSummary.merged_paths)?mergeSummary.merged_paths.length:0},status=deriveStatus(state),output={tool:"app-import-verify",version:1,mode:"verify",workspace_dir:workspaceDir,design_import_dir:designImportRoot,target_template_key:layout.template_key,frontend_root:layout.frontend_root,imported_upstream_dir:layout.imported_upstream_root,status,state,missing_items:listMissingItems(state),next_steps:buildNextSteps(status,state)};if(args.json){process.stdout.write(`${JSON.stringify(output,null,2)}
2425
2428
  `);return}process.stdout.write(["third-party design verify completed",`workspace_dir: ${output.workspace_dir}`,`status: ${output.status}`,`source_preprocess_execution_mode: ${output.state.sourcePreprocessExecutionMode}`,`has_import_summary: ${output.state.hasImportSummary}`,`has_merge_summary: ${output.state.hasMergeSummary}`,`has_imported_upstream_dir: ${output.state.hasImportedUpstreamDir}`,`pending_videos: ${output.state.pendingVideosCount}`,`pending_manual_items: ${output.state.pendingManualItemsCount}`,`path_base_violations_remaining: ${output.state.pathBaseViolationsRemaining}`,`missing_items: ${output.missing_items.length}`].join(`
2426
2429
  `)+`
2427
2430
  `)}function hasFlag(args,key){return args.options[key]===!0}function readOption(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function currentWorkspaceDir(){return process.env.PLATFORM_INVOCATION_CWD||process.env.INIT_CWD||process.cwd()}function printAppImportHelp(subcommand){switch(subcommand){case"preprocess":printAppImportPreprocessUsage();return;case"stage":printAppImportStageUsage();return;case"merge":printAppImportMergeUsage();return;case"verify":printAppImportVerifyUsage();return;default:process.stdout.write(["platform app import","","\u53EF\u7528\u5B50\u547D\u4EE4\uFF1A"," platform app import preprocess \u751F\u6210 clean-source \u4E0E\u9884\u5904\u7406\u62A5\u544A"," platform app import stage \u628A clean-source \u4E0E reports stage \u5230\u6A21\u677F\u5DE5\u4F5C\u533A"," platform app import merge \u6309\u6A21\u677F\u524D\u7AEF\u6839\u76EE\u5F55\u628A\u4E0A\u6E38\u5185\u5BB9\u5B89\u5168\u5E76\u5165 imported-upstream \u843D\u70B9"," platform app import verify \u6821\u9A8C preprocess / stage / merge \u4EA7\u7269\u72B6\u6001","","\u8BF4\u660E\uFF1A"," \u5F53\u524D P0 \u81EA\u52A8\u5316\u53EA\u8986\u76D6\u6700\u8017\u65F6\u3001\u6700\u673A\u68B0\u7684\u4E09\u6BB5\uFF1Apreprocess / stage / merge\u3002"," create / wiring / CMS-DB-Auth \u63A5\u7EBF\u4ECD\u7531\u6A21\u677F\u5DE5\u4F5C\u533A\u4E0E\u4EBA\u5DE5\u5DE5\u7A0B\u5316\u627F\u63A5\u3002",""].join(`
2428
- `))}}async function runAppImportCommand(args){let subcommand=args.rest[1]??"help";if(hasFlag(args,"help")||hasFlag(args,"h")){printAppImportHelp(subcommand==="help"?void 0:subcommand);return}if(subcommand==="help"){printAppImportHelp();return}if(subcommand!=="preprocess"&&subcommand!=="stage"&&subcommand!=="merge"&&subcommand!=="verify")throw new Error("`platform app import` \u76EE\u524D\u652F\u6301 `preprocess`\u3001`stage`\u3001`merge` \u6216 `verify`\u3002");if(subcommand==="preprocess"){let cliArgs2=["--dir",readOption(args,"dir")??currentWorkspaceDir()],include=readOption(args,"include"),folderId=readOption(args,"folder-id"),type=readOption(args,"type"),cliCmd=readOption(args,"cli-cmd"),localReport=readOption(args,"local-report");include&&cliArgs2.push("--include",include),folderId&&cliArgs2.push("--folder-id",folderId),type&&cliArgs2.push("--type",type),cliCmd&&cliArgs2.push("--cli-cmd",cliCmd),localReport&&cliArgs2.push("--local-report",localReport),hasFlag(args,"dry-run")&&cliArgs2.push("--dry-run"),hasFlag(args,"resume")&&cliArgs2.push("--resume"),hasFlag(args,"reset-cache")&&cliArgs2.push("--reset-cache"),hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportPreprocessCli(cliArgs2);return}if(subcommand==="stage"){let preprocess=readOption(args,"preprocess");if(!preprocess)throw new Error("`platform app import stage` \u9700\u8981 `--preprocess <source-dir|.design-preprocess|reports|import-manifest.json>`\u3002");let cliArgs2=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir(),"--preprocess",preprocess];hasFlag(args,"dry-run")&&cliArgs2.push("--dry-run"),hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportStageCli(cliArgs2);return}if(subcommand==="verify"){let cliArgs2=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir()];hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportVerifyCli(cliArgs2);return}let cliArgs=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir()];hasFlag(args,"dry-run")&&cliArgs.push("--dry-run"),hasFlag(args,"json")&&cliArgs.push("--json"),await runAppImportMergeCli(cliArgs)}var AUTH_CONFIGURE_TEMPLATE_VALUES=["email_magic_link_only","admin_password_only","email_magic_link_and_admin_password","phone_sms_otp_only","email_magic_link_and_phone_sms_otp"],AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT=AUTH_CONFIGURE_TEMPLATE_VALUES.map(item=>`\`${item}\``).join("\u3001");function normalizeAuthTemplate(value){if(value!==void 0){if(AUTH_CONFIGURE_TEMPLATE_VALUES.includes(value))return value;throw new Error(`\u65E0\u6548\u7684 \`--template\`\uFF0C\u4EC5\u652F\u6301 ${AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT}\u3002`)}}function buildAuthConfigurePayload(options){let templatePayload=buildTemplatePayload(options.template);if(options.enablePhoneSmsOtp===!1&&templatePayload.enable_phone_sms_otp===!0)throw new Error("\u5F53\u524D `--template` \u4F9D\u8D56 `phone_sms_otp`\uFF0C\u4E0D\u80FD\u540C\u65F6\u4F20 `--disable-phone-sms-otp`\u3002");return{auth_enabled:options.enable?!0:void 0,user_store_id:options.userStoreId,auth_template:templatePayload.auth_template,enable_admin_provisioned_password:options.enableAdminProvisionedPassword,enable_phone_sms_otp:typeof options.enablePhoneSmsOtp=="boolean"?options.enablePhoneSmsOtp:templatePayload.enable_phone_sms_otp,enabled_sign_in_methods:templatePayload.enabled_sign_in_methods,default_sign_in_method:templatePayload.default_sign_in_method,registration_mode:templatePayload.registration_mode}}function hasAuthConfigureChanges(payload){return payload.auth_enabled!==void 0||payload.user_store_id!==void 0||payload.auth_template!==void 0||payload.enable_admin_provisioned_password!==void 0||payload.enable_phone_sms_otp!==void 0||payload.enabled_sign_in_methods!==void 0||payload.default_sign_in_method!==void 0||payload.registration_mode!==void 0}function buildTemplatePayload(template){switch(template){case"phone_sms_otp_only":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["phone_sms_otp"],default_sign_in_method:"phone_sms_otp",registration_mode:"open"};case"email_magic_link_and_phone_sms_otp":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["email_magic_link","phone_sms_otp"],default_sign_in_method:"email_magic_link",registration_mode:"open"};case"email_magic_link_only":case"admin_password_only":case"email_magic_link_and_admin_password":return{auth_template:template};default:return{}}}var BUILD_POLL_INTERVAL_MS=1500,BUILD_POLL_TIMEOUT_MS=18e4;async function runBuildCommand(args){if(hasHelpFlag3(args)){printBuildHelp(args.rest[0]);return}let subcommand=args.rest[0];if(subcommand!=="get"&&subcommand!=="events"&&subcommand!=="validate"&&subcommand!=="run")throw new Error("`platform build` \u4EC5\u652F\u6301 `run`\u3001`get <build-id>`\u3001`events <build-id>` \u6216 `validate --source-version <srcver>`\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let binding;try{binding=readBinding(process.cwd())?.binding}catch{binding=null}let tenantId=readStringOption3(args,"tenant")??binding?.tenant_id,buildId=args.rest[1]??readStringOption3(args,"build");if((subcommand==="get"||subcommand==="events")&&!buildId)throw new Error(`\`platform build ${subcommand}\` \u9700\u8981 <build-id>\uFF0C\u6216\u4F20\u5165 \`--build <build-id>\`\u3002`);let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"});if(subcommand==="run"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!tenantId||!appId||!sourceVersionId)throw new Error("`platform build run` \u9700\u8981 `--source-version <srcver>`\uFF0C\u4EE5\u53CA\u5DF2\u7ED1\u5B9A\u76EE\u5F55\u6216 `--tenant` / `--app`\u3002");let requestedBy=await resolveRequestedBy(sdk),buildConfig=await resolveBuildRunConfig(sdk,appId,sourceVersionId,readBuildConfig(args.options)),created=await sdk.createBuild({tenant_id:tenantId,app_id:appId,source_version_id:sourceVersionId,requested_by:requestedBy,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildRunError(error,appId,sourceVersionId)}),wait=args.options.wait===!0;if(args.options.json===!0&&!wait){process.stdout.write(`${JSON.stringify(created,null,2)}
2431
+ `))}}async function runAppImportCommand(args){let subcommand=args.rest[1]??"help";if(hasFlag(args,"help")||hasFlag(args,"h")){printAppImportHelp(subcommand==="help"?void 0:subcommand);return}if(subcommand==="help"){printAppImportHelp();return}if(subcommand!=="preprocess"&&subcommand!=="stage"&&subcommand!=="merge"&&subcommand!=="verify")throw new Error("`platform app import` \u76EE\u524D\u652F\u6301 `preprocess`\u3001`stage`\u3001`merge` \u6216 `verify`\u3002");if(subcommand==="preprocess"){let cliArgs2=["--dir",readOption(args,"dir")??currentWorkspaceDir()],include=readOption(args,"include"),folderId=readOption(args,"folder-id"),type=readOption(args,"type"),cliCmd=readOption(args,"cli-cmd"),localReport=readOption(args,"local-report");include&&cliArgs2.push("--include",include),folderId&&cliArgs2.push("--folder-id",folderId),type&&cliArgs2.push("--type",type),cliCmd&&cliArgs2.push("--cli-cmd",cliCmd),localReport&&cliArgs2.push("--local-report",localReport),hasFlag(args,"dry-run")&&cliArgs2.push("--dry-run"),hasFlag(args,"resume")&&cliArgs2.push("--resume"),hasFlag(args,"reset-cache")&&cliArgs2.push("--reset-cache"),hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportPreprocessCli(cliArgs2);return}if(subcommand==="stage"){let preprocess=readOption(args,"preprocess");if(!preprocess)throw new Error("`platform app import stage` \u9700\u8981 `--preprocess <source-dir|.design-preprocess|reports|import-manifest.json>`\u3002");let cliArgs2=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir(),"--preprocess",preprocess];hasFlag(args,"dry-run")&&cliArgs2.push("--dry-run"),hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportStageCli(cliArgs2);return}if(subcommand==="verify"){let cliArgs2=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir()];hasFlag(args,"json")&&cliArgs2.push("--json"),await runAppImportVerifyCli(cliArgs2);return}let cliArgs=["--workspace-dir",readOption(args,"workspace-dir")??currentWorkspaceDir()];hasFlag(args,"dry-run")&&cliArgs.push("--dry-run"),hasFlag(args,"json")&&cliArgs.push("--json"),await runAppImportMergeCli(cliArgs)}var AUTH_CONFIGURE_TEMPLATE_VALUES=["email_magic_link_only","admin_password_only","email_magic_link_and_admin_password","phone_sms_otp_only","email_magic_link_and_phone_sms_otp"],AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT=AUTH_CONFIGURE_TEMPLATE_VALUES.map(item=>`\`${item}\``).join("\u3001");function formatAuthorizationCodeLoginPrompt(input){return input.opened?`\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002
2432
+ `:[input.source==="cli-app"?"\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002":"\u4F7F\u7528 workbench \u914D\u7F6E\u56DE\u9000\u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u5F3A\u5236 prompt=login consent \u4EE5\u907F\u514D\u590D\u7528\u9519\u8BEF SSO \u4F1A\u8BDD\u5E76\u6362\u53D6 refresh token\u3002","\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",`\u6388\u6743\u5730\u5740: ${input.authorizationUrl}`,`\u56DE\u8C03\u5730\u5740: ${input.redirectUri}`,input.source==="workbench-fallback"?"\u82E5\u56DE\u8C03\u7AEF\u53E3\u88AB\u672C\u5730 workbench \u5360\u7528\uFF0C\u8BF7\u5148\u6682\u65F6\u505C\u6B62\u5BF9\u5E94\u670D\u52A1\u540E\u91CD\u8BD5\u3002":"\u8BF7\u786E\u8BA4\u8BE5\u56DE\u8C03\u5730\u5740\u5DF2\u5728\u4E13\u7528 CLI App \u4E2D\u6CE8\u518C\u3002",""].join(`
2433
+ `)}function normalizeAuthTemplate(value){if(value!==void 0){if(AUTH_CONFIGURE_TEMPLATE_VALUES.includes(value))return value;throw new Error(`\u65E0\u6548\u7684 \`--template\`\uFF0C\u4EC5\u652F\u6301 ${AUTH_CONFIGURE_TEMPLATE_VALUES_TEXT}\u3002`)}}function buildAuthConfigurePayload(options){let templatePayload=buildTemplatePayload(options.template);if(options.enablePhoneSmsOtp===!1&&templatePayload.enable_phone_sms_otp===!0)throw new Error("\u5F53\u524D `--template` \u4F9D\u8D56 `phone_sms_otp`\uFF0C\u4E0D\u80FD\u540C\u65F6\u4F20 `--disable-phone-sms-otp`\u3002");return{auth_enabled:options.enable?!0:void 0,user_store_id:options.userStoreId,auth_template:templatePayload.auth_template,enable_admin_provisioned_password:options.enableAdminProvisionedPassword,enable_phone_sms_otp:typeof options.enablePhoneSmsOtp=="boolean"?options.enablePhoneSmsOtp:templatePayload.enable_phone_sms_otp,enabled_sign_in_methods:templatePayload.enabled_sign_in_methods,default_sign_in_method:templatePayload.default_sign_in_method,registration_mode:templatePayload.registration_mode}}function hasAuthConfigureChanges(payload){return payload.auth_enabled!==void 0||payload.user_store_id!==void 0||payload.auth_template!==void 0||payload.enable_admin_provisioned_password!==void 0||payload.enable_phone_sms_otp!==void 0||payload.enabled_sign_in_methods!==void 0||payload.default_sign_in_method!==void 0||payload.registration_mode!==void 0}function buildTemplatePayload(template){switch(template){case"phone_sms_otp_only":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["phone_sms_otp"],default_sign_in_method:"phone_sms_otp",registration_mode:"open"};case"email_magic_link_and_phone_sms_otp":return{enable_phone_sms_otp:!0,enabled_sign_in_methods:["email_magic_link","phone_sms_otp"],default_sign_in_method:"email_magic_link",registration_mode:"open"};case"email_magic_link_only":case"admin_password_only":case"email_magic_link_and_admin_password":return{auth_template:template};default:return{}}}var BUILD_POLL_INTERVAL_MS=1500,BUILD_POLL_TIMEOUT_MS=18e4;async function runBuildCommand(args){if(hasHelpFlag3(args)){printBuildHelp(args.rest[0]);return}let subcommand=args.rest[0];if(subcommand!=="get"&&subcommand!=="events"&&subcommand!=="validate"&&subcommand!=="run")throw new Error("`platform build` \u4EC5\u652F\u6301 `run`\u3001`get <build-id>`\u3001`events <build-id>` \u6216 `validate --source-version <srcver>`\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let binding;try{binding=readBinding(process.cwd())?.binding}catch{binding=null}let tenantId=readStringOption3(args,"tenant")??binding?.tenant_id,buildId=args.rest[1]??readStringOption3(args,"build");if((subcommand==="get"||subcommand==="events")&&!buildId)throw new Error(`\`platform build ${subcommand}\` \u9700\u8981 <build-id>\uFF0C\u6216\u4F20\u5165 \`--build <build-id>\`\u3002`);let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"});if(subcommand==="run"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!tenantId||!appId||!sourceVersionId)throw new Error("`platform build run` \u9700\u8981 `--source-version <srcver>`\uFF0C\u4EE5\u53CA\u5DF2\u7ED1\u5B9A\u76EE\u5F55\u6216 `--tenant` / `--app`\u3002");let requestedBy=await resolveRequestedBy(sdk),buildConfig=await resolveBuildRunConfig(sdk,appId,sourceVersionId,readBuildConfig(args.options)),created=await sdk.createBuild({tenant_id:tenantId,app_id:appId,source_version_id:sourceVersionId,requested_by:requestedBy,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildRunError(error,appId,sourceVersionId)}),wait=args.options.wait===!0;if(args.options.json===!0&&!wait){process.stdout.write(`${JSON.stringify(created,null,2)}
2429
2434
  `);return}if(!wait){printBuildStarted(created);return}let completed=await waitForBuild(sdk,created.id);if(args.options.json===!0){process.stdout.write(`${JSON.stringify(completed,null,2)}
2430
2435
  `);return}printBuildCompletion(completed);return}if(subcommand==="get"){let result2=await sdk.getBuild(buildId).catch(error=>{throw formatBuildCommandError(error,"get",buildId)});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
2431
2436
  `);return}printBuild(result2);return}if(subcommand==="validate"){let appId=readStringOption3(args,"app")??binding?.app_id,sourceVersionId=readStringOption3(args,"source-version")??readStringOption3(args,"source_version");if(!appId||!sourceVersionId)throw new Error("`platform build validate` \u9700\u8981 `--app <app-id>` \u4E0E `--source-version <srcver>`\uFF1B\u82E5\u5F53\u524D\u76EE\u5F55\u5DF2\u7ED1\u5B9A\uFF0C\u53EF\u7701\u7565 `--app`\u3002");let buildConfig=readBuildConfig(args.options),result2=await sdk.getBuildPrecheck(appId,{source_version_id:sourceVersionId,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}}).catch(error=>{throw formatBuildValidateError(error,appId,sourceVersionId)});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
@@ -2443,14 +2448,14 @@ ${routeMarker}`)}return next}function buildAuthDebugPageSource(){return["export
2443
2448
  `)}
2444
2449
  `)}async function loadBuildCliMetadata(sdk,appId,sourceVersionId){let[sourceVersions,publishSettings]=await Promise.all([sdk.listTenantAppSourceVersions(appId).catch(()=>({items:[]})),sdk.getTenantAppPublishSettings(appId).catch(()=>null)]);return{sourceVersion:sourceVersions.items.find(item=>item.source_version_id===sourceVersionId)??null,publishSettings}}function readStringOption3(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function hasHelpFlag3(args){return args.options.help===!0||args.options.h===!0}function printBuildHelp(subcommand){if(subcommand==="run"){process.stdout.write(["platform build run","","\u8BF4\u660E\uFF1A\u8FD9\u662F\u9AD8\u7EA7\u8BCA\u65AD\u5165\u53E3\u3002\u5E38\u89C4\u7248\u672C\u9884\u89C8\u4F18\u5148\u4F7F\u7528 `platform preview generate`\u3002","","\u7528\u6CD5\uFF1A"," platform build run --source-version <srcver> [--wait] [--tenant <tenant-id>] [--app <app-id>]","","\u53EF\u9009\u6784\u5EFA\u914D\u7F6E\uFF1A"," --dockerfile <path>"," --context-subdir <dir>"," --target <stage>","","\u8BF4\u660E\uFF1A"," \u53D1\u8D77\u771F\u5B9E\u4E91\u7AEF\u6784\u5EFA\uFF1B\u9ED8\u8BA4\u7ACB\u5373\u8FD4\u56DE build id\uFF0C\u52A0 `--wait` \u5219\u7B49\u5F85\u6784\u5EFA\u7ED3\u675F\u3002",""].join(`
2445
2450
  `));return}process.stdout.write(["platform build","","\u8BF4\u660E\uFF1A\u8FD9\u662F\u9AD8\u7EA7\u8BCA\u65AD\u5165\u53E3\u3002\u666E\u901A\u5F00\u53D1\u4E0E\u9A8C\u8BC1\u4E3B\u8DEF\u5F84\u4F18\u5148\u4F7F\u7528 `platform preview` / `platform publish`\u3002","","\u53EF\u7528\u5B50\u547D\u4EE4\uFF1A"," 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 build validate --app <app-id> --source-version <srcver> --target static","","\u8BF4\u660E\uFF1A"," - `run` \u53D1\u8D77\u771F\u5B9E\u4E91\u7AEF\u6784\u5EFA"," - `get/events` \u67E5\u8BE2\u6784\u5EFA\u72B6\u6001\u4E0E\u4E8B\u4EF6"," - `validate` \u53EA\u505A\u6784\u5EFA\u524D\u9884\u68C0\u67E5",""].join(`
2446
- `))}function readBuildConfig(options){let dockerfilePath=typeof options.dockerfile=="string"?options.dockerfile:void 0,contextSubdir=typeof options["context-subdir"]=="string"?options["context-subdir"]:void 0,target=typeof options.target=="string"?options.target:void 0;return{...dockerfilePath?{dockerfile_path:dockerfilePath}:{},...contextSubdir?{context_subdir:contextSubdir}:{},...target?{target}:{}}}async function resolveBuildRunConfig(sdk,appId,sourceVersionId,buildConfig){if(buildConfig.target)return buildConfig;try{return(await sdk.getBuildPrecheck(appId,{source_version_id:sourceVersionId,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}})).normalized_build_config??buildConfig}catch(error){if(!isBuildPrecheckFallbackAllowed(error))throw error;return buildConfig}}function isBuildPrecheckFallbackAllowed(error){return!(error instanceof PlatformApiError)||error.code==="capability_unavailable"?!0:error.status>=500}async function resolveRequestedBy(sdk){return(await sdk.getWhoAmI()).subject_id}async function waitForBuild(sdk,buildId,options){let timeoutMs=options?.timeoutMs??BUILD_POLL_TIMEOUT_MS,intervalMs=options?.intervalMs??BUILD_POLL_INTERVAL_MS,startedAt=Date.now();for(;;){let build=await sdk.getBuild(buildId);if(isTerminalBuildStatus(build.status)||Date.now()-startedAt>=timeoutMs)return build;await sleep2(intervalMs)}}function isTerminalBuildStatus(status){return status==="succeeded"||status==="failed"||status==="cancelled"}function extractReusedBuildId(result){return result.error_code!=="build_reused_existing_success"||!result.error_message?null:result.error_message.match(/reused successful build\s+([a-zA-Z0-9-]+)/)?.[1]??null}function sleep2(ms){return new Promise(resolve16=>{setTimeout(resolve16,ms)})}function formatBuildCommandError(error,subcommand,buildId){if(error instanceof PlatformApiError){let suffix=error.detail?`
2451
+ `))}function readBuildConfig(options){let dockerfilePath=typeof options.dockerfile=="string"?options.dockerfile:void 0,contextSubdir=typeof options["context-subdir"]=="string"?options["context-subdir"]:void 0,target=typeof options.target=="string"?options.target:void 0;return{...dockerfilePath?{dockerfile_path:dockerfilePath}:{},...contextSubdir?{context_subdir:contextSubdir}:{},...target?{target}:{}}}async function resolveBuildRunConfig(sdk,appId,sourceVersionId,buildConfig){if(buildConfig.target)return buildConfig;try{return(await sdk.getBuildPrecheck(appId,{source_version_id:sourceVersionId,...Object.keys(buildConfig).length>0?{build_config:buildConfig}:{}})).normalized_build_config??buildConfig}catch(error){if(!isBuildPrecheckFallbackAllowed(error))throw error;return buildConfig}}function isBuildPrecheckFallbackAllowed(error){return!(error instanceof PlatformApiError)||error.code==="capability_unavailable"?!0:error.status>=500}async function resolveRequestedBy(sdk){return(await sdk.getWhoAmI()).subject_id}async function waitForBuild(sdk,buildId,options){let timeoutMs=options?.timeoutMs??BUILD_POLL_TIMEOUT_MS,intervalMs=options?.intervalMs??BUILD_POLL_INTERVAL_MS,startedAt=Date.now();for(;;){let build=await sdk.getBuild(buildId);if(isTerminalBuildStatus(build.status)||Date.now()-startedAt>=timeoutMs)return build;await sleep2(intervalMs)}}function isTerminalBuildStatus(status){return status==="succeeded"||status==="failed"||status==="cancelled"}function extractReusedBuildId(result){return result.error_code!=="build_reused_existing_success"||!result.error_message?null:result.error_message.match(/reused successful build\s+([a-zA-Z0-9-]+)/)?.[1]??null}function sleep2(ms){return new Promise(resolve17=>{setTimeout(resolve17,ms)})}function formatBuildCommandError(error,subcommand,buildId){if(error instanceof PlatformApiError){let suffix=error.detail?`
2447
2452
  detail: ${JSON.stringify(error.detail)}`:"";return new Error([`platform build ${subcommand} \u5931\u8D25: ${buildId}`,`code: ${error.code}`,`message: ${error.message}${suffix}`].join(`
2448
2453
  `))}return error instanceof Error?error:new Error(`platform build ${subcommand} \u5931\u8D25: ${buildId}`)}function formatBuildValidateError(error,appId,sourceVersionId){if(error instanceof PlatformApiError){let suffix=error.detail?`
2449
2454
  detail: ${JSON.stringify(error.detail)}`:"";return new Error([`platform build validate \u5931\u8D25: ${appId}/${sourceVersionId}`,`code: ${error.code}`,`message: ${error.message}${suffix}`].join(`
2450
2455
  `))}return error instanceof Error?error:new Error(`platform build validate \u5931\u8D25: ${appId}/${sourceVersionId}`)}function formatBuildRunError(error,appId,sourceVersionId){if(error instanceof PlatformApiError){let suffix=error.detail?`
2451
2456
  detail: ${JSON.stringify(error.detail)}`:"";return new Error([`platform build run \u5931\u8D25: ${appId}/${sourceVersionId}`,`code: ${error.code}`,`message: ${error.message}${suffix}`].join(`
2452
- `))}return error instanceof Error?error:new Error(`platform build run \u5931\u8D25: ${appId}/${sourceVersionId}`)}import{readFileSync as readFileSync19}from"node:fs";import{basename as basename4,extname as extname3,resolve as resolve11}from"node:path";async function runBlobCommand(args,deps){if(hasHelpFlag4(args)||args.rest.length===0){printBlobHelp();return}let subcommand=args.rest[0];if(subcommand==="upload"){await runBlobUpload(args,deps);return}if(subcommand==="list"){await runBlobList(args,deps);return}if(subcommand==="get"){await runBlobGet(args,deps);return}if(subcommand==="url"){await runBlobUrl(args,deps);return}throw new Error("`platform blob` \u4EC5\u652F\u6301 `upload`\u3001`list`\u3001`get`\u3001`url`\u3002")}function isBlobHelpRequest(args){return hasHelpFlag4(args)||args.rest.length===0}function printBlobHelp(){process.stdout.write(["platform blob <command>","","Commands:"," platform blob upload <file-path> [--app <app-id>] [--content-type <mime>] [--client-request-id <id>] [--json]"," platform blob list [--app <app-id>] [--q <keyword>] [--cursor <cursor>] [--limit <n>] [--json]"," platform blob get <blob-id> [--json]"," platform blob url <blob-id> [--ttl-seconds <n>] [--json]","","Notes:"," - Object Storage \u5F53\u524D\u8D70 tenant \u63A7\u5236\u9762\uFF0C\u4E0D\u8D70 public/runtime SDK"," - `upload` \u590D\u7528\u4E09\u6B65\u5F0F\u4E0A\u4F20\uFF1Acreate session -> upload binary -> complete"," - `url` \u9ED8\u8BA4\u7B7E\u53D1 1 \u5C0F\u65F6\u4E0B\u8F7D\u94FE\u63A5",""].join(`
2453
- `))}async function runBlobUpload(args,deps){let filePathArg=args.rest[1];if(!filePathArg)throw new Error("`platform blob upload` \u9700\u8981 <file-path>\u3002");let filePath=resolve11(filePathArg),fileName=basename4(filePath),content=new Uint8Array(readFileSync19(filePath)),contentType=readStringOption4(args,"content-type")?.trim()||inferMimeType2(fileName),appId=readStringOption4(args,"app")?.trim(),clientRequestId=readStringOption4(args,"client-request-id")?.trim(),session=await deps.sdk.createTenantBlobUploadSession({original_filename:fileName,content_type:contentType,size_bytes:content.byteLength,...appId?{app_id:appId}:{},...clientRequestId?{client_request_id:clientRequestId}:{}}).catch(error=>{throw formatBlobError(error,"upload(create session)")});await deps.sdk.uploadTenantBlobBinary(session.upload_session_id,{content,content_type:contentType,upload_url:session.upload_url,headers:session.headers}).catch(error=>{throw formatBlobError(error,"upload(content)")});let response=await deps.sdk.completeTenantBlobUpload(session.upload_session_id,{size_bytes:content.byteLength}).catch(error=>{throw formatBlobError(error,"upload(complete)")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify({upload_session:session,result:response},null,2)}
2457
+ `))}return error instanceof Error?error:new Error(`platform build run \u5931\u8D25: ${appId}/${sourceVersionId}`)}import{readFileSync as readFileSync19}from"node:fs";import{basename as basename5,extname as extname3,resolve as resolve12}from"node:path";async function runBlobCommand(args,deps){if(hasHelpFlag4(args)||args.rest.length===0){printBlobHelp();return}let subcommand=args.rest[0];if(subcommand==="upload"){await runBlobUpload(args,deps);return}if(subcommand==="list"){await runBlobList(args,deps);return}if(subcommand==="get"){await runBlobGet(args,deps);return}if(subcommand==="url"){await runBlobUrl(args,deps);return}throw new Error("`platform blob` \u4EC5\u652F\u6301 `upload`\u3001`list`\u3001`get`\u3001`url`\u3002")}function isBlobHelpRequest(args){return hasHelpFlag4(args)||args.rest.length===0}function printBlobHelp(){process.stdout.write(["platform blob <command>","","Commands:"," platform blob upload <file-path> [--app <app-id>] [--content-type <mime>] [--client-request-id <id>] [--json]"," platform blob list [--app <app-id>] [--q <keyword>] [--cursor <cursor>] [--limit <n>] [--json]"," platform blob get <blob-id> [--json]"," platform blob url <blob-id> [--ttl-seconds <n>] [--json]","","Notes:"," - Object Storage \u5F53\u524D\u8D70 tenant \u63A7\u5236\u9762\uFF0C\u4E0D\u8D70 public/runtime SDK"," - `upload` \u590D\u7528\u4E09\u6B65\u5F0F\u4E0A\u4F20\uFF1Acreate session -> upload binary -> complete"," - `url` \u9ED8\u8BA4\u7B7E\u53D1 1 \u5C0F\u65F6\u4E0B\u8F7D\u94FE\u63A5",""].join(`
2458
+ `))}async function runBlobUpload(args,deps){let filePathArg=args.rest[1];if(!filePathArg)throw new Error("`platform blob upload` \u9700\u8981 <file-path>\u3002");let filePath=resolve12(filePathArg),fileName=basename5(filePath),content=new Uint8Array(readFileSync19(filePath)),contentType=readStringOption4(args,"content-type")?.trim()||inferMimeType2(fileName),appId=readStringOption4(args,"app")?.trim(),clientRequestId=readStringOption4(args,"client-request-id")?.trim(),session=await deps.sdk.createTenantBlobUploadSession({original_filename:fileName,content_type:contentType,size_bytes:content.byteLength,...appId?{app_id:appId}:{},...clientRequestId?{client_request_id:clientRequestId}:{}}).catch(error=>{throw formatBlobError(error,"upload(create session)")});await deps.sdk.uploadTenantBlobBinary(session.upload_session_id,{content,content_type:contentType,upload_url:session.upload_url,headers:session.headers}).catch(error=>{throw formatBlobError(error,"upload(content)")});let response=await deps.sdk.completeTenantBlobUpload(session.upload_session_id,{size_bytes:content.byteLength}).catch(error=>{throw formatBlobError(error,"upload(complete)")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify({upload_session:session,result:response},null,2)}
2454
2459
  `);return}process.stdout.write(["Blob \u5DF2\u4E0A\u4F20\u3002",`tenant: ${deps.tenantId}`,`blob: ${response.blob_id}`,`upload_session: ${response.upload_session_id}`,`file: ${fileName}`,`content_type: ${contentType}`,`size: ${content.byteLength} bytes`,`source: ${appId?`app:${appId}`:"tenant_workbench"}`,""].join(`
2455
2460
  `))}async function runBlobList(args,deps){let response=await deps.sdk.listTenantBlobs({...readStringOption4(args,"app")?{app_id:readStringOption4(args,"app")}:{},...readStringOption4(args,"q")?{q:readStringOption4(args,"q")}:{},...readStringOption4(args,"cursor")?{cursor:readStringOption4(args,"cursor")}:{},...readNumberOption2(args,"limit")!==void 0?{limit:readNumberOption2(args,"limit")}:{}}).catch(error=>{throw formatBlobError(error,"list")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
2456
2461
  `);return}process.stdout.write([`tenant: ${deps.tenantId}`,`items: ${response.items.length}`,`next_cursor: ${response.next_cursor??"-"}`,...response.items.map(item=>[item.blob_id,item.original_filename,`source=${item.source_type}`,`mime=${item.content_type??"-"}`,`size=${item.size_bytes}`,`created_at=${item.created_at}`].join(" ")),""].join(`
@@ -2459,15 +2464,15 @@ detail: ${JSON.stringify(error.detail)}`:"";return new Error([`platform build ru
2459
2464
  `))}async function runBlobUrl(args,deps){let blobId=args.rest[1];if(!blobId)throw new Error("`platform blob url` \u9700\u8981 <blob-id>\u3002");let ttlSeconds=readNumberOption2(args,"ttl-seconds")??3600,response=await deps.sdk.issueTenantBlobDownloadUrl(blobId,{ttl_seconds:ttlSeconds}).catch(error=>{throw formatBlobError(error,"url")});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(response,null,2)}
2460
2465
  `);return}process.stdout.write([response.url,`expires_at: ${response.expires_at}`,`ttl_seconds: ${ttlSeconds}`,`tenant: ${deps.tenantId}`,""].join(`
2461
2466
  `))}function readStringOption4(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readNumberOption2(args,key){let value=readStringOption4(args,key);if(value===void 0)return;let parsed=Number(value);if(!Number.isFinite(parsed)||parsed<=0)throw new Error(`\`--${key}\` \u9700\u8981\u6B63\u6574\u6570\u3002`);return Math.trunc(parsed)}function hasHelpFlag4(args){return args.options.help===!0||args.options.h===!0}function inferMimeType2(fileName){switch(extname3(fileName).toLowerCase()){case".json":return"application/json";case".pdf":return"application/pdf";case".txt":return"text/plain";case".csv":return"text/csv";case".html":return"text/html";case".md":return"text/markdown";case".png":return"image/png";case".jpg":case".jpeg":return"image/jpeg";case".gif":return"image/gif";case".webp":return"image/webp";case".svg":return"image/svg+xml";case".mp4":return"video/mp4";case".mov":return"video/quicktime";case".webm":return"video/webm";case".zip":return"application/zip";default:return"application/octet-stream"}}function formatBlobError(error,action){return error instanceof PlatformApiError?new Error([`Blob ${action} \u5931\u8D25\u3002`,`\u72B6\u6001\u7801: ${error.status}`,`\u9519\u8BEF\u7801: ${error.code??"-"}`,error.message].join(`
2462
- `)):error instanceof Error?error:new Error(`Blob ${action} \u5931\u8D25\u3002`)}function buildTenantAssetReference2(asset){return{asset_id:asset.asset.asset_id,title:asset.asset.title,media_type:asset.asset.media_type,mime_type:asset.asset.mime_type,size_bytes:asset.original_file.size_bytes,folder_id:asset.asset.folder_id,original_url:asset.original_url,variant_urls:asset.variant_urls}}function resolveCmsAttachAssetField(fields,fieldName){let field=fields.find(entry=>entry.name===fieldName);if(!field)throw new Error(`Collection does not contain field \`${fieldName}\`.`);if(field.type!=="image"&&field.type!=="images")throw new Error(`\u5B57\u6BB5 \`${fieldName}\` \u4E0D\u662F\u53EF\u6302\u8F7D\u7D20\u6750\u7684\u56FE\u7247\u5B57\u6BB5\u3002`);return field}function isAssetReferenceRecord(value){return typeof value=="object"&&value!==null&&typeof value.asset_id=="string"}function dedupeAssetReferences(values){let seen=new Set,deduped=[];for(let value of values)seen.has(value.asset_id)||(seen.add(value.asset_id),deduped.push(value));return deduped}function buildCmsAttachAssetPayload(args){let assetReferences=args.assets.map(buildTenantAssetReference2),nextContent=normalizeCmsContentForWrite2(args.item.content,args.fields);if(args.field.type==="image"){if(assetReferences.length!==1)throw new Error("\u5355\u56FE\u5B57\u6BB5\u4E00\u6B21\u53EA\u80FD\u6302\u8F7D\u4E00\u4E2A\u7D20\u6750\u3002");nextContent[args.field.name]=assetReferences[0]}else if(args.field.type==="images"){let currentValues=Array.isArray(args.item.content[args.field.name])?args.item.content[args.field.name].filter(isAssetReferenceRecord):[];nextContent[args.field.name]=dedupeAssetReferences(args.replace?assetReferences:[...currentValues,...assetReferences])}else throw new Error(`\u5B57\u6BB5 \`${args.field.name}\` \u4E0D\u662F\u53EF\u6302\u8F7D\u7D20\u6750\u7684\u56FE\u7247\u5B57\u6BB5\u3002`);return{collection:args.item.collection,system:{...args.item.system.publish_status?{publish_status:args.item.system.publish_status}:{},...args.item.system.slug?{slug:args.item.system.slug}:{},...args.item.system.tags?{tags:[...args.item.system.tags]}:{},...Object.prototype.hasOwnProperty.call(args.item.system,"category_id")?{category_id:args.item.system.category_id??null}:{},...args.item.system.content_format?{content_format:args.item.system.content_format}:{},...args.item.system.source?{source:{...args.item.system.source}}:{}},content:nextContent}}function normalizeCmsContentForWrite2(content,fields){let normalized={...content};for(let field of fields){let currentValue=normalized[field.name];if(field.type==="relation"){typeof currentValue=="object"&&currentValue!==null&&typeof currentValue.id=="string"&&(normalized[field.name]=currentValue.id);continue}field.type==="relations"&&Array.isArray(currentValue)&&(normalized[field.name]=currentValue.map(item=>typeof item=="string"?item:typeof item=="object"&&item!==null&&typeof item.id=="string"?item.id:null).filter(item=>typeof item=="string"))}return normalized}import{existsSync as existsSync19,readFileSync as readFileSync20}from"node:fs";import{createConnection}from"node:net";import{dirname as dirname12,resolve as resolve12}from"node:path";import process2 from"node:process";function isLikelyControlApiConnectionError(error){if(!(error instanceof Error))return!1;let message=error.message.toLowerCase();if(message.includes("fetch failed")||message.includes("econnrefused")||message.includes("failed to fetch"))return!0;let cause=error.cause;if(cause&&typeof cause=="object"&&"code"in cause){let code2=String(cause.code).toLowerCase();return code2==="econnrefused"||code2==="enotfound"||code2==="econnreset"}return!1}function isControlApiDiagnosticError(error){return error instanceof PlatformApiError&&(error.category==="capability_health"||error.category==="runtime_binding"||error.code==="capability_unavailable"||error.code==="runtime_binding_missing")}function formatControlApiDiagnosticErrorText(error){let lines=["control-api diagnostic error:",`- code: ${error.code??"unknown"}`,`- category: ${error.category??"unknown"}`,`- capability: ${error.capability??"unknown"}`,`- message: ${error.message}`];return error.requestId&&lines.push(`- request_id: ${error.requestId}`),error.remediation&&lines.push(`- action: ${error.remediation}`),`${lines.join(`
2467
+ `)):error instanceof Error?error:new Error(`Blob ${action} \u5931\u8D25\u3002`)}function buildTenantAssetReference2(asset){return{asset_id:asset.asset.asset_id,title:asset.asset.title,media_type:asset.asset.media_type,mime_type:asset.asset.mime_type,size_bytes:asset.original_file.size_bytes,folder_id:asset.asset.folder_id,original_url:asset.original_url,variant_urls:asset.variant_urls}}function resolveCmsAttachAssetField(fields,fieldName){let field=fields.find(entry=>entry.name===fieldName);if(!field)throw new Error(`Collection does not contain field \`${fieldName}\`.`);if(field.type!=="image"&&field.type!=="images")throw new Error(`\u5B57\u6BB5 \`${fieldName}\` \u4E0D\u662F\u53EF\u6302\u8F7D\u7D20\u6750\u7684\u56FE\u7247\u5B57\u6BB5\u3002`);return field}function isAssetReferenceRecord(value){return typeof value=="object"&&value!==null&&typeof value.asset_id=="string"}function dedupeAssetReferences(values){let seen=new Set,deduped=[];for(let value of values)seen.has(value.asset_id)||(seen.add(value.asset_id),deduped.push(value));return deduped}function buildCmsAttachAssetPayload(args){let assetReferences=args.assets.map(buildTenantAssetReference2),nextContent=normalizeCmsContentForWrite2(args.item.content,args.fields);if(args.field.type==="image"){if(assetReferences.length!==1)throw new Error("\u5355\u56FE\u5B57\u6BB5\u4E00\u6B21\u53EA\u80FD\u6302\u8F7D\u4E00\u4E2A\u7D20\u6750\u3002");nextContent[args.field.name]=assetReferences[0]}else if(args.field.type==="images"){let currentValues=Array.isArray(args.item.content[args.field.name])?args.item.content[args.field.name].filter(isAssetReferenceRecord):[];nextContent[args.field.name]=dedupeAssetReferences(args.replace?assetReferences:[...currentValues,...assetReferences])}else throw new Error(`\u5B57\u6BB5 \`${args.field.name}\` \u4E0D\u662F\u53EF\u6302\u8F7D\u7D20\u6750\u7684\u56FE\u7247\u5B57\u6BB5\u3002`);return{collection:args.item.collection,system:{...args.item.system.publish_status?{publish_status:args.item.system.publish_status}:{},...args.item.system.slug?{slug:args.item.system.slug}:{},...args.item.system.tags?{tags:[...args.item.system.tags]}:{},...Object.prototype.hasOwnProperty.call(args.item.system,"category_id")?{category_id:args.item.system.category_id??null}:{},...args.item.system.content_format?{content_format:args.item.system.content_format}:{},...args.item.system.source?{source:{...args.item.system.source}}:{}},content:nextContent}}function normalizeCmsContentForWrite2(content,fields){let normalized={...content};for(let field of fields){let currentValue=normalized[field.name];if(field.type==="relation"){typeof currentValue=="object"&&currentValue!==null&&typeof currentValue.id=="string"&&(normalized[field.name]=currentValue.id);continue}field.type==="relations"&&Array.isArray(currentValue)&&(normalized[field.name]=currentValue.map(item=>typeof item=="string"?item:typeof item=="object"&&item!==null&&typeof item.id=="string"?item.id:null).filter(item=>typeof item=="string"))}return normalized}import{existsSync as existsSync19,readFileSync as readFileSync20}from"node:fs";import{createConnection}from"node:net";import{dirname as dirname12,resolve as resolve13}from"node:path";import process2 from"node:process";function isLikelyControlApiConnectionError(error){if(!(error instanceof Error))return!1;let message=error.message.toLowerCase();if(message.includes("fetch failed")||message.includes("econnrefused")||message.includes("failed to fetch"))return!0;let cause=error.cause;if(cause&&typeof cause=="object"&&"code"in cause){let code2=String(cause.code).toLowerCase();return code2==="econnrefused"||code2==="enotfound"||code2==="econnreset"}return!1}function isControlApiDiagnosticError(error){return error instanceof PlatformApiError&&(error.category==="capability_health"||error.category==="runtime_binding"||error.code==="capability_unavailable"||error.code==="runtime_binding_missing")}function formatControlApiDiagnosticErrorText(error){let lines=["control-api diagnostic error:",`- code: ${error.code??"unknown"}`,`- category: ${error.category??"unknown"}`,`- capability: ${error.capability??"unknown"}`,`- message: ${error.message}`];return error.requestId&&lines.push(`- request_id: ${error.requestId}`),error.remediation&&lines.push(`- action: ${error.remediation}`),`${lines.join(`
2463
2468
  `)}
2464
2469
  `}async function collectControlApiFailureDiagnostics(baseUrl=getControlApiBaseUrl(),startDir=process2.cwd()){let parsedBaseUrl=new URL(baseUrl),isLocal=isLocalControlApiUrl(parsedBaseUrl),healthz=await probeEndpoint(new URL("/healthz",parsedBaseUrl)),readyz=healthz.status==="ok"||healthz.status==="failed"?await probeEndpoint(new URL("/readyz",parsedBaseUrl)):{status:"skipped",httpStatus:null},port=Number.parseInt(parsedBaseUrl.port||(parsedBaseUrl.protocol==="https:"?"443":"80"),10),host=normalizeProbeHost(parsedBaseUrl.hostname),lock=isLocal?readControlApiDevLock(startDir,port):emptyLock(),listening=isLocal?await isPortListening(host,port):null,diagnosis=buildDiagnosis({healthz,readyz,isLocal,lockExists:lock.exists,pidAlive:lock.pid_alive,portListening:listening}),endpoints=await collectEndpointDiagnostics(baseUrl,healthz),capabilityHealth=extractCapabilityHealthDiagnostics(healthz.body);return{control_api:{base_url:baseUrl,reachable:healthz.status==="ok"||healthz.status==="failed",healthz:{status:healthz.status==="not_ready"?"failed":healthz.status,http_status:healthz.httpStatus},readyz:{status:readyz.status,http_status:readyz.httpStatus}},capability_health:capabilityHealth,endpoints,local_dev:{is_local_base_url:isLocal,lock,port:{host,port,listening}},diagnosis,recommendations:buildRecommendations(diagnosis.code,isLocal)}}function formatControlApiFailureDiagnosticsText(diagnostics){return formatControlApiDiagnosticsText(diagnostics,"control-api unreachable:")}function formatControlApiDiagnosticsText(diagnostics,title="control-api diagnostics:"){let lines=[title,`- base_url: ${diagnostics.control_api.base_url}`,`- healthz: ${diagnostics.control_api.healthz.status}${diagnostics.control_api.healthz.http_status==null?"":` (${diagnostics.control_api.healthz.http_status})`}`,`- readyz: ${diagnostics.control_api.readyz.status}${diagnostics.control_api.readyz.http_status==null?"":` (${diagnostics.control_api.readyz.http_status})`}`];return lines.push(`- endpoint control: ${diagnostics.endpoints.control.healthz.status}`,`- endpoint runtime: ${formatEndpointState(diagnostics.endpoints.runtime)}`,`- endpoint public: ${formatEndpointState(diagnostics.endpoints.public)}`),diagnostics.capability_health.degraded.length>0&&lines.push(`- degraded capabilities: ${formatHealthItems(diagnostics.capability_health.degraded)}`),diagnostics.capability_health.workers.length>0&&lines.push(`- degraded workers: ${formatHealthItems(diagnostics.capability_health.workers)}`),diagnostics.local_dev.is_local_base_url&&lines.push(`- lock: ${diagnostics.local_dev.lock.exists?`exists pid=${diagnostics.local_dev.lock.pid??"-"} alive=${diagnostics.local_dev.lock.pid_alive??"-"}`:"missing"}`,`- port: ${diagnostics.local_dev.port.listening?"listening":"not listening"}`),lines.push(`- likely_cause: ${diagnostics.diagnosis.code}`,...diagnostics.recommendations.map(item=>`- action: ${item}`)),`${lines.join(`
2465
2470
  `)}
2466
- `}async function collectEndpointDiagnostics(controlBaseUrl,controlHealthz){let endpoints=listResolvedControlApiEndpoints({...process2.env,CONTROL_API_BASE_URL:controlBaseUrl}),results=await Promise.all(endpoints.map(async endpoint=>{if(endpoint.role==="control")return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!0,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,healthz:{status:controlHealthz.status,http_status:controlHealthz.httpStatus}};if(!endpoint.enabled||endpoint.baseUrl==null)return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!1,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,reason:endpoint.reason,healthz:{status:"skipped",http_status:null}};let healthz=await probeEndpoint(new URL("/healthz",endpoint.baseUrl));return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!0,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,healthz:{status:healthz.status,http_status:healthz.httpStatus}}}));return{control:results.find(endpoint=>endpoint.role==="control"),runtime:results.find(endpoint=>endpoint.role==="runtime"),public:results.find(endpoint=>endpoint.role==="public")}}function formatEndpointState(endpoint){return endpoint.enabled?`${endpoint.healthz.status}${endpoint.healthz.http_status==null?"":` (${endpoint.healthz.http_status})`}`:`${endpoint.reason??"disabled"}${endpoint.base_url?` (${endpoint.base_url})`:""}`}async function probeEndpoint(url){try{let response=await fetch(url,{signal:AbortSignal.timeout(1200)}),body=await readJsonBody(response);return response.ok?{status:"ok",httpStatus:response.status,body}:{status:response.status===503?"not_ready":"failed",httpStatus:response.status,body}}catch{return{status:"unreachable",httpStatus:null}}}async function readJsonBody(response){let text2=await response.text().catch(()=>"");if(text2)try{return JSON.parse(text2)}catch{return}}function extractCapabilityHealthDiagnostics(body){if(!body||typeof body!="object")return{status:null,degraded:[],workers:[]};let record=body;return{status:typeof record.status=="string"?record.status:null,degraded:extractDegradedHealthItems(record.capabilities),workers:extractDegradedHealthItems(record.workers)}}function extractDegradedHealthItems(input){return!input||typeof input!="object"?[]:Object.entries(input).map(([key,value])=>toHealthDiagnostic(key,value)).filter(item=>!!item)}function toHealthDiagnostic(key,value){if(!value||typeof value!="object")return null;let record=value,status=typeof record.status=="string"?record.status:"unknown";return status!=="degraded"&&status!=="unavailable"?null:{key,status,summary:typeof record.summary=="string"?record.summary:"",issues:Array.isArray(record.issues)?record.issues.filter(item=>typeof item=="string"):[],...typeof record.check_level=="string"?{check_level:record.check_level}:{}}}function formatHealthItems(items){return items.map(item=>{let issueText=item.issues.length>0?` issues=${item.issues.join(",")}`:"",levelText=item.check_level?` level=${item.check_level}`:"";return`${item.key}:${item.status}${levelText}${issueText}`}).join("; ")}function isLocalControlApiUrl(url){return url.hostname==="localhost"||url.hostname==="127.0.0.1"||url.hostname==="0.0.0.0"}function normalizeProbeHost(host){return host==="0.0.0.0"?"127.0.0.1":host}function readControlApiDevLock(startDir,port){let path=findControlApiLockPath(startDir,port);if(!path||!existsSync19(path))return{path,exists:!1,pid:null,pid_alive:null};let raw=readFileSync20(path,"utf8").trim(),pid=parseLockPid(raw);return{path,exists:!0,pid,pid_alive:pid==null?null:isPidRunning(pid)}}function emptyLock(){return{path:null,exists:!1,pid:null,pid_alive:null}}function findControlApiLockPath(startDir,port){let current=resolve12(startDir);for(;;){let candidate=resolve12(current,"services","control-api",`.dev-server.${port}.lock`);if(existsSync19(resolve12(current,"services","control-api")))return candidate;let parent=dirname12(current);if(parent===current)return null;current=parent}}function parseLockPid(raw){if(!raw)return null;try{let parsed=JSON.parse(raw),pid=Number.parseInt(String(parsed.pid??""),10);return Number.isFinite(pid)&&pid>0?pid:null}catch{let pid=Number.parseInt(raw,10);return Number.isFinite(pid)&&pid>0?pid:null}}function isPidRunning(pid){try{return process2.kill(pid,0),!0}catch{return!1}}function isPortListening(host,port){return new Promise(resolvePromise=>{let socket=createConnection({host,port});socket.setTimeout(800),socket.once("connect",()=>{socket.destroy(),resolvePromise(!0)}),socket.once("timeout",()=>{socket.destroy(),resolvePromise(!1)}),socket.once("error",()=>{socket.destroy(),resolvePromise(!1)})})}function buildDiagnosis(args){return args.healthz.status==="ok"&&args.readyz.status==="ok"?{category:"control_api_infrastructure",code:"control_api_ok",message:"control-api is reachable and ready"}:args.readyz.status==="not_ready"?{category:"control_api_infrastructure",code:"readyz_not_ready",message:"control-api is reachable but not ready"}:args.isLocal&&args.lockExists&&args.pidAlive===!0&&args.portListening===!1?{category:"control_api_infrastructure",code:"dev_manager_alive_but_http_not_ready",message:"control-api dev manager is alive but HTTP server is not listening"}:args.isLocal&&args.lockExists&&args.portListening===!1?{category:"control_api_infrastructure",code:"dev_lock_exists_port_not_listening",message:"control-api dev lock exists but HTTP port is not listening"}:{category:"control_api_infrastructure",code:args.healthz.status==="unreachable"?"healthz_unreachable":"control_api_unreachable",message:"control-api is unreachable"}}function buildRecommendations(code2,isLocal){return code2==="control_api_ok"?[]:isLocal?code2==="dev_manager_alive_but_http_not_ready"||code2==="dev_lock_exists_port_not_listening"?["restart `pnpm --filter @platform/control-api dev`"]:["start `pnpm --filter @platform/control-api dev`"]:["check CONTROL_API_BASE_URL, network connectivity, and environment configuration"]}function normalizeCategorySlug(value){return value.trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"category"}function parseCmsCategoryPath(path){let segments=path.split("/").map(segment=>segment.trim()).filter(Boolean);if(segments.length===0)throw new Error("\u5206\u7C7B\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A\u3002");return segments.map(name=>({name,slug:normalizeCategorySlug(name)}))}function findCmsCategoryPathMatch(categories,parentId,segment){return categories.find(node=>(node.parent_id??null)===parentId&&node.slug===segment.slug)??categories.find(node=>(node.parent_id??null)===parentId&&node.name===segment.name)??null}async function ensureCmsCategoryPath(args){let categories=[...args.categories],parentId=null,finalNode=null,ensuredNodes=[];for(let segment of args.segments){let existing=findCmsCategoryPathMatch(categories,parentId,segment);if(existing){finalNode=existing,parentId=existing.id,ensuredNodes.push({id:existing.id,name:existing.name,slug:existing.slug,parent_id:existing.parent_id??null,action:"reused"});continue}let created=await args.createCategory(segment,parentId);categories.push(created),finalNode=created,parentId=created.id,ensuredNodes.push({id:created.id,name:created.name,slug:created.slug,parent_id:created.parent_id??null,action:"created"})}if(!finalNode)throw new Error("\u5206\u7C7B\u8DEF\u5F84\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u751F\u6210\u76EE\u6807\u5206\u7C7B\u3002");return{categories,finalNode,ensuredNodes}}function planCmsCategoryPath(args){let categories=[...args.categories],parentId=null,finalNode=null,plannedNodeCounter=0,plannedNodes=[];for(let segment of args.segments){let existing=findCmsCategoryPathMatch(categories,parentId,segment);if(existing){finalNode=existing,parentId=existing.id,plannedNodes.push({id:existing.id,name:existing.name,slug:existing.slug,parent_id:existing.parent_id??null,action:"reused"});continue}plannedNodes.push({id:null,name:segment.name,slug:segment.slug,parent_id:parentId,action:"created"}),finalNode=null,plannedNodeCounter+=1,parentId=`__planned_category_${plannedNodeCounter}`}return{finalNode,plannedNodes}}import{createHash as createHash6}from"node:crypto";import{readdirSync as readdirSync7,statSync as statSync8}from"node:fs";import{basename as basename5,extname as extname4,join as join15,relative as relative4,resolve as resolve13}from"node:path";import YAML3 from"yaml";function normalizeLineEndings(input){return input.replace(/\r\n/g,`
2467
- `)}function computeChecksum2(input){return`sha256:${createHash6("sha256").update(input).digest("hex")}`}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function toStringArray(value){if(Array.isArray(value))return value.filter(item=>typeof item=="string").map(item=>item.trim()).filter(Boolean);if(typeof value=="string")return value.split(",").map(item=>item.trim()).filter(Boolean)}function toOptionalString(value){return typeof value=="string"&&value.trim().length>0?value.trim():void 0}function isMarkdownFilePath(filePath){let extension=extname4(filePath).toLowerCase();return extension===".md"||extension===".markdown"}function normalizeSourcePath(filePath){let normalized=relative4(process.cwd(),filePath).replace(/\\/g,"/");return normalized.length>0&&!normalized.startsWith("..")?normalized:filePath.replace(/\\/g,"/")}function inferDefaultTitleFromPath(filePath){let title=basename5(filePath,extname4(filePath)).trim();return title.length>0?title:void 0}function inferDefaultSlugFromPath(filePath){let slug=basename5(filePath,extname4(filePath)).trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,120);return slug.length>0?slug:void 0}function normalizeItemIdSegment(value){return value.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function inferItemIdFromPrefix(prefix,filePath){let normalizedPrefix=normalizeItemIdSegment(prefix)||"cms-item",normalizedSource=filePath.replace(/\.[^.]+$/,""),pathSegment=normalizeItemIdSegment(normalizedSource),hash=createHash6("sha256").update(filePath).digest("hex").slice(0,8),readableSegment=pathSegment.length>0?pathSegment.slice(0,64):"item";return`${normalizedPrefix}-${readableSegment}-${hash}`}function collectMarkdownImportSources(targetPath,recursive){let absoluteTargetPath=resolve13(targetPath),stats=statSync8(absoluteTargetPath);if(stats.isFile()){if(!isMarkdownFilePath(absoluteTargetPath))throw new Error(`\u4EC5\u652F\u6301\u5BFC\u5165 Markdown \u6587\u4EF6\uFF1A${targetPath}`);return[{absolutePath:absoluteTargetPath,sourcePath:normalizeSourcePath(absoluteTargetPath)}]}if(!stats.isDirectory())throw new Error(`\u4EC5\u652F\u6301\u5BFC\u5165 Markdown \u6587\u4EF6\u6216\u76EE\u5F55\uFF1A${targetPath}`);let collected=[],visitDirectory=directoryPath=>{let entries=readdirSync7(directoryPath,{withFileTypes:!0}).sort((left,right)=>left.name.localeCompare(right.name));for(let entry of entries){let entryPath=join15(directoryPath,entry.name);if(entry.isDirectory()){recursive&&visitDirectory(entryPath);continue}!entry.isFile()||!isMarkdownFilePath(entryPath)||collected.push({absolutePath:entryPath,sourcePath:normalizeSourcePath(entryPath)})}};return visitDirectory(absoluteTargetPath),collected}function parseMarkdownWithFrontmatter(input){let raw=normalizeLineEndings(input),checksum3=computeChecksum2(raw);if(!raw.startsWith(`---
2471
+ `}async function collectEndpointDiagnostics(controlBaseUrl,controlHealthz){let endpoints=listResolvedControlApiEndpoints({...process2.env,CONTROL_API_BASE_URL:controlBaseUrl}),results=await Promise.all(endpoints.map(async endpoint=>{if(endpoint.role==="control")return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!0,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,healthz:{status:controlHealthz.status,http_status:controlHealthz.httpStatus}};if(!endpoint.enabled||endpoint.baseUrl==null)return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!1,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,reason:endpoint.reason,healthz:{status:"skipped",http_status:null}};let healthz=await probeEndpoint(new URL("/healthz",endpoint.baseUrl));return{role:endpoint.role,base_url:endpoint.baseUrl,enabled:!0,capabilities:endpoint.capabilities,request_class:endpoint.requestClass,healthz:{status:healthz.status,http_status:healthz.httpStatus}}}));return{control:results.find(endpoint=>endpoint.role==="control"),runtime:results.find(endpoint=>endpoint.role==="runtime"),public:results.find(endpoint=>endpoint.role==="public")}}function formatEndpointState(endpoint){return endpoint.enabled?`${endpoint.healthz.status}${endpoint.healthz.http_status==null?"":` (${endpoint.healthz.http_status})`}`:`${endpoint.reason??"disabled"}${endpoint.base_url?` (${endpoint.base_url})`:""}`}async function probeEndpoint(url){try{let response=await fetch(url,{signal:AbortSignal.timeout(1200)}),body=await readJsonBody(response);return response.ok?{status:"ok",httpStatus:response.status,body}:{status:response.status===503?"not_ready":"failed",httpStatus:response.status,body}}catch{return{status:"unreachable",httpStatus:null}}}async function readJsonBody(response){let text2=await response.text().catch(()=>"");if(text2)try{return JSON.parse(text2)}catch{return}}function extractCapabilityHealthDiagnostics(body){if(!body||typeof body!="object")return{status:null,degraded:[],workers:[]};let record=body;return{status:typeof record.status=="string"?record.status:null,degraded:extractDegradedHealthItems(record.capabilities),workers:extractDegradedHealthItems(record.workers)}}function extractDegradedHealthItems(input){return!input||typeof input!="object"?[]:Object.entries(input).map(([key,value])=>toHealthDiagnostic(key,value)).filter(item=>!!item)}function toHealthDiagnostic(key,value){if(!value||typeof value!="object")return null;let record=value,status=typeof record.status=="string"?record.status:"unknown";return status!=="degraded"&&status!=="unavailable"?null:{key,status,summary:typeof record.summary=="string"?record.summary:"",issues:Array.isArray(record.issues)?record.issues.filter(item=>typeof item=="string"):[],...typeof record.check_level=="string"?{check_level:record.check_level}:{}}}function formatHealthItems(items){return items.map(item=>{let issueText=item.issues.length>0?` issues=${item.issues.join(",")}`:"",levelText=item.check_level?` level=${item.check_level}`:"";return`${item.key}:${item.status}${levelText}${issueText}`}).join("; ")}function isLocalControlApiUrl(url){return url.hostname==="localhost"||url.hostname==="127.0.0.1"||url.hostname==="0.0.0.0"}function normalizeProbeHost(host){return host==="0.0.0.0"?"127.0.0.1":host}function readControlApiDevLock(startDir,port){let path2=findControlApiLockPath(startDir,port);if(!path2||!existsSync19(path2))return{path:path2,exists:!1,pid:null,pid_alive:null};let raw=readFileSync20(path2,"utf8").trim(),pid=parseLockPid(raw);return{path:path2,exists:!0,pid,pid_alive:pid==null?null:isPidRunning(pid)}}function emptyLock(){return{path:null,exists:!1,pid:null,pid_alive:null}}function findControlApiLockPath(startDir,port){let current=resolve13(startDir);for(;;){let candidate=resolve13(current,"services","control-api",`.dev-server.${port}.lock`);if(existsSync19(resolve13(current,"services","control-api")))return candidate;let parent=dirname12(current);if(parent===current)return null;current=parent}}function parseLockPid(raw){if(!raw)return null;try{let parsed=JSON.parse(raw),pid=Number.parseInt(String(parsed.pid??""),10);return Number.isFinite(pid)&&pid>0?pid:null}catch{let pid=Number.parseInt(raw,10);return Number.isFinite(pid)&&pid>0?pid:null}}function isPidRunning(pid){try{return process2.kill(pid,0),!0}catch{return!1}}function isPortListening(host,port){return new Promise(resolvePromise=>{let socket=createConnection({host,port});socket.setTimeout(800),socket.once("connect",()=>{socket.destroy(),resolvePromise(!0)}),socket.once("timeout",()=>{socket.destroy(),resolvePromise(!1)}),socket.once("error",()=>{socket.destroy(),resolvePromise(!1)})})}function buildDiagnosis(args){return args.healthz.status==="ok"&&args.readyz.status==="ok"?{category:"control_api_infrastructure",code:"control_api_ok",message:"control-api is reachable and ready"}:args.readyz.status==="not_ready"?{category:"control_api_infrastructure",code:"readyz_not_ready",message:"control-api is reachable but not ready"}:args.isLocal&&args.lockExists&&args.pidAlive===!0&&args.portListening===!1?{category:"control_api_infrastructure",code:"dev_manager_alive_but_http_not_ready",message:"control-api dev manager is alive but HTTP server is not listening"}:args.isLocal&&args.lockExists&&args.portListening===!1?{category:"control_api_infrastructure",code:"dev_lock_exists_port_not_listening",message:"control-api dev lock exists but HTTP port is not listening"}:{category:"control_api_infrastructure",code:args.healthz.status==="unreachable"?"healthz_unreachable":"control_api_unreachable",message:"control-api is unreachable"}}function buildRecommendations(code2,isLocal){return code2==="control_api_ok"?[]:isLocal?code2==="dev_manager_alive_but_http_not_ready"||code2==="dev_lock_exists_port_not_listening"?["restart `pnpm --filter @platform/control-api dev`"]:["start `pnpm --filter @platform/control-api dev`"]:["check CONTROL_API_BASE_URL, network connectivity, and environment configuration"]}function normalizeCategorySlug(value){return value.trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,80)||"category"}function parseCmsCategoryPath(path2){let segments=path2.split("/").map(segment=>segment.trim()).filter(Boolean);if(segments.length===0)throw new Error("\u5206\u7C7B\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A\u3002");return segments.map(name=>({name,slug:normalizeCategorySlug(name)}))}function findCmsCategoryPathMatch(categories,parentId,segment){return categories.find(node=>(node.parent_id??null)===parentId&&node.slug===segment.slug)??categories.find(node=>(node.parent_id??null)===parentId&&node.name===segment.name)??null}async function ensureCmsCategoryPath(args){let categories=[...args.categories],parentId=null,finalNode=null,ensuredNodes=[];for(let segment of args.segments){let existing=findCmsCategoryPathMatch(categories,parentId,segment);if(existing){finalNode=existing,parentId=existing.id,ensuredNodes.push({id:existing.id,name:existing.name,slug:existing.slug,parent_id:existing.parent_id??null,action:"reused"});continue}let created=await args.createCategory(segment,parentId);categories.push(created),finalNode=created,parentId=created.id,ensuredNodes.push({id:created.id,name:created.name,slug:created.slug,parent_id:created.parent_id??null,action:"created"})}if(!finalNode)throw new Error("\u5206\u7C7B\u8DEF\u5F84\u89E3\u6790\u5931\u8D25\uFF0C\u672A\u751F\u6210\u76EE\u6807\u5206\u7C7B\u3002");return{categories,finalNode,ensuredNodes}}function planCmsCategoryPath(args){let categories=[...args.categories],parentId=null,finalNode=null,plannedNodeCounter=0,plannedNodes=[];for(let segment of args.segments){let existing=findCmsCategoryPathMatch(categories,parentId,segment);if(existing){finalNode=existing,parentId=existing.id,plannedNodes.push({id:existing.id,name:existing.name,slug:existing.slug,parent_id:existing.parent_id??null,action:"reused"});continue}plannedNodes.push({id:null,name:segment.name,slug:segment.slug,parent_id:parentId,action:"created"}),finalNode=null,plannedNodeCounter+=1,parentId=`__planned_category_${plannedNodeCounter}`}return{finalNode,plannedNodes}}import{createHash as createHash6}from"node:crypto";import{readdirSync as readdirSync7,statSync as statSync8}from"node:fs";import{basename as basename6,extname as extname4,join as join15,relative as relative4,resolve as resolve14}from"node:path";import YAML3 from"yaml";function normalizeLineEndings(input){return input.replace(/\r\n/g,`
2472
+ `)}function computeChecksum2(input){return`sha256:${createHash6("sha256").update(input).digest("hex")}`}function isPlainObject(value){return typeof value=="object"&&value!==null&&!Array.isArray(value)}function toStringArray(value){if(Array.isArray(value))return value.filter(item=>typeof item=="string").map(item=>item.trim()).filter(Boolean);if(typeof value=="string")return value.split(",").map(item=>item.trim()).filter(Boolean)}function toOptionalString(value){return typeof value=="string"&&value.trim().length>0?value.trim():void 0}function isMarkdownFilePath(filePath){let extension=extname4(filePath).toLowerCase();return extension===".md"||extension===".markdown"}function normalizeSourcePath(filePath){let normalized=relative4(process.cwd(),filePath).replace(/\\/g,"/");return normalized.length>0&&!normalized.startsWith("..")?normalized:filePath.replace(/\\/g,"/")}function inferDefaultTitleFromPath(filePath){let title=basename6(filePath,extname4(filePath)).trim();return title.length>0?title:void 0}function inferDefaultSlugFromPath(filePath){let slug=basename6(filePath,extname4(filePath)).trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,120);return slug.length>0?slug:void 0}function normalizeItemIdSegment(value){return value.trim().toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"")}function inferItemIdFromPrefix(prefix,filePath){let normalizedPrefix=normalizeItemIdSegment(prefix)||"cms-item",normalizedSource=filePath.replace(/\.[^.]+$/,""),pathSegment=normalizeItemIdSegment(normalizedSource),hash=createHash6("sha256").update(filePath).digest("hex").slice(0,8),readableSegment=pathSegment.length>0?pathSegment.slice(0,64):"item";return`${normalizedPrefix}-${readableSegment}-${hash}`}function collectMarkdownImportSources(targetPath,recursive){let absoluteTargetPath=resolve14(targetPath),stats=statSync8(absoluteTargetPath);if(stats.isFile()){if(!isMarkdownFilePath(absoluteTargetPath))throw new Error(`\u4EC5\u652F\u6301\u5BFC\u5165 Markdown \u6587\u4EF6\uFF1A${targetPath}`);return[{absolutePath:absoluteTargetPath,sourcePath:normalizeSourcePath(absoluteTargetPath)}]}if(!stats.isDirectory())throw new Error(`\u4EC5\u652F\u6301\u5BFC\u5165 Markdown \u6587\u4EF6\u6216\u76EE\u5F55\uFF1A${targetPath}`);let collected=[],visitDirectory=directoryPath=>{let entries=readdirSync7(directoryPath,{withFileTypes:!0}).sort((left,right)=>left.name.localeCompare(right.name));for(let entry of entries){let entryPath=join15(directoryPath,entry.name);if(entry.isDirectory()){recursive&&visitDirectory(entryPath);continue}!entry.isFile()||!isMarkdownFilePath(entryPath)||collected.push({absolutePath:entryPath,sourcePath:normalizeSourcePath(entryPath)})}};return visitDirectory(absoluteTargetPath),collected}function parseMarkdownWithFrontmatter(input){let raw=normalizeLineEndings(input),checksum3=computeChecksum2(raw);if(!raw.startsWith(`---
2468
2473
  `))return{frontmatter:{},body:raw.trim(),raw,checksum:checksum3};let closingIndex=raw.indexOf(`
2469
2474
  ---
2470
- `,4);if(closingIndex===-1)return{frontmatter:{},body:raw.trim(),raw,checksum:checksum3};let frontmatterSource=raw.slice(4,closingIndex),body=raw.slice(closingIndex+5).trim(),parsed=YAML3.parse(frontmatterSource);return{frontmatter:isPlainObject(parsed)?parsed:{},body,raw,checksum:checksum3}}function buildMarkdownItemPayload(args){let parsed=parseMarkdownWithFrontmatter(args.markdownContent),frontmatter={...parsed.frontmatter},title=args.title??toOptionalString(frontmatter.title)??inferDefaultTitleFromPath(args.markdownPath),slug=args.slug??toOptionalString(frontmatter.slug)??inferDefaultSlugFromPath(args.markdownPath),summary=args.summary??toOptionalString(frontmatter.summary),tags=args.tags??toStringArray(frontmatter.tags),categoryId=args.categoryId??toOptionalString(frontmatter.category_id)??null,publishStatus=args.publishStatus??toOptionalString(frontmatter.publish_status)??"draft";delete frontmatter.title,delete frontmatter.slug,delete frontmatter.summary,delete frontmatter.tags,delete frontmatter.category_id,delete frontmatter.publish_status;let content={...frontmatter,body:parsed.body};return title&&(content.title=title),summary&&(content.summary=summary),{...args.itemId?{item_id:args.itemId}:{},collection:args.collection,system:{publish_status:publishStatus,...slug?{slug}:{},...tags!==void 0?{tags}:{},...categoryId?{category_id:categoryId}:{},content_format:"markdown",source:{source_type:"markdown",source_url:null,source_path:args.markdownPath,source_raw:parsed.raw,checksum:parsed.checksum,imported_by:args.importedBy??"ide-agent",parser_version:"markdown-importer.v1"}},content}}function resolveMarkdownImportLookupKey(payload){return typeof payload.item_id=="string"&&payload.item_id.trim().length>0?{kind:"item_id",value:payload.item_id}:typeof payload.system.slug=="string"&&payload.system.slug.trim().length>0?{kind:"slug",value:payload.system.slug}:null}function summarizeMarkdownImportResults(items){let importedOrPlanned=0,skipped=0,draft=0,published=0,archived=0;for(let item of items){if(item.state==="skipped"?skipped+=1:importedOrPlanned+=1,item.publish_status==="draft"){draft+=1;continue}if(item.publish_status==="published"){published+=1;continue}item.publish_status==="archived"&&(archived+=1)}return{total:items.length,imported_or_planned:importedOrPlanned,skipped,draft,published,archived}}function normalizeSlugCandidate(value){return value.trim().slice(0,120)}function applySlugSuffix(baseSlug,suffix){let suffixText=`-${suffix}`;return`${baseSlug.slice(0,Math.max(1,120-suffixText.length))}${suffixText}`}async function findTenantCmsItemByExactSlug(args){let normalizedSlug=normalizeSlugCandidate(args.slug);if(!normalizedSlug)return null;let page=1,pageSize=100;for(;;){let response=await args.sdk.listTenantCmsItems({collection:args.collection,page,pageSize,query:normalizedSlug}),matched=response.items.find(item=>item.system.slug===normalizedSlug);if(matched)return matched;if(page*pageSize>=response.total||response.items.length===0)return null;page+=1}}async function resolveUniqueTenantCmsSlug(args){let normalizedSlug=args.slug?normalizeSlugCandidate(args.slug):void 0;if(!normalizedSlug)return{slug:void 0,adjusted:!1};let candidate=normalizedSlug,suffix=2;for(;;){let conflictsInBatch=args.reservedSlugs?.has(candidate)??!1,existing=conflictsInBatch?null:await findTenantCmsItemByExactSlug({sdk:args.sdk,collection:args.collection,slug:candidate});if(!conflictsInBatch&&(!existing||existing.system.id===args.itemId))return{slug:candidate,adjusted:candidate!==normalizedSlug,originalSlug:candidate!==normalizedSlug?normalizedSlug:void 0};candidate=applySlugSuffix(normalizedSlug,suffix),suffix+=1}}import{createHash as createHash7}from"node:crypto";import{URL as URL3}from"node:url";import{Readability}from"@mozilla/readability";import{JSDOM}from"jsdom";import sanitizeHtml from"sanitize-html";function computeChecksum3(input){return`sha256:${createHash7("sha256").update(input).digest("hex")}`}function stripUnsupportedJsonChars(value){return value.replace(/\u0000/g,"")}function trimToUndefined2(value){let normalized=value?.trim();return normalized||void 0}function getMetaContent(document,key){let selectors=[`meta[property="${key}"]`,`meta[name="${key}"]`,`meta[itemprop="${key}"]`];for(let selector of selectors){let value=trimToUndefined2(document.querySelector(selector)?.getAttribute("content"));if(value)return value}}function getFirstText(document,selectors){for(let selector of selectors){let value=trimToUndefined2(document.querySelector(selector)?.textContent);if(value)return value}}function normalizeUrl2(value,baseUrl){if(!value)return;let trimmed=value.trim();if(trimmed)try{return new URL3(trimmed,baseUrl).toString()}catch{return}}function escapeHtmlAttribute(value){return value.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function inferMimeTypeFromUrl2(value){if(!value)return;let pathname=(()=>{try{return new URL3(value).pathname.toLowerCase()}catch{return value.toLowerCase()}})();if(pathname.endsWith(".png"))return"image/png";if(pathname.endsWith(".webp"))return"image/webp";if(pathname.endsWith(".gif"))return"image/gif";if(pathname.endsWith(".svg"))return"image/svg+xml";if(pathname.endsWith(".jpg")||pathname.endsWith(".jpeg"))return"image/jpeg"}function extractArticleImageCandidates(document,baseUrl){let selectors=[".news-detail .image.parbase img",".news-detail .news-img img",".news-detail .richtext img","article img","main img"],results=[],seen=new Set;for(let selector of selectors)for(let image2 of document.querySelectorAll(selector)){let className=image2.getAttribute("class")?.toLowerCase()??"",parentClassName=image2.parentElement?.getAttribute("class")?.toLowerCase()??"";if(className.includes("qrcode")||className.includes("qr-code")||parentClassName.includes("qrcode")||parentClassName.includes("qr-code"))continue;let rawSrc=image2.getAttribute("src")??image2.getAttribute("data-src")??image2.getAttribute("data-original")??image2.getAttribute("data-original-src")??image2.getAttribute("data-lazy-src")??void 0,absoluteUrl=normalizeUrl2(rawSrc??void 0,baseUrl);!absoluteUrl||seen.has(absoluteUrl)||absoluteUrl.startsWith("data:")||(seen.add(absoluteUrl),results.push({url:absoluteUrl,alt:trimToUndefined2(image2.getAttribute("alt")??image2.getAttribute("title")??void 0)}))}return results}function normalizePublishedAt(value){if(!value)return;let timestamp=Date.parse(value);if(!Number.isNaN(timestamp))return new Date(timestamp).toISOString()}function inferDefaultTitleFromUrl(value){try{let parsed=new URL3(value),segment=parsed.pathname.replace(/\/+$/,"").split("/").filter(Boolean).at(-1)?.trim();return segment&&segment.length>0?decodeURIComponent(segment):parsed.hostname}catch{return}}function stripPageExtension(value){if(value)return value.replace(/\.(html?|xhtml|shtml)$/i,"")}function inferDefaultSlug(args){let candidates=[stripPageExtension(inferDefaultTitleFromUrl(args.resolvedUrl)),stripPageExtension(inferDefaultTitleFromUrl(args.requestedUrl)),args.title];for(let candidate of candidates){let normalized=candidate?.trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,120);if(normalized)return normalized}}function absolutizeRichTextHtml(html,baseUrl){let body=new JSDOM(`<body>${html}</body>`,{url:baseUrl}).window.document.body;for(let anchor of body.querySelectorAll("a[href]")){let href=anchor.getAttribute("href"),absoluteHref=normalizeUrl2(href??void 0,baseUrl);absoluteHref&&anchor.setAttribute("href",absoluteHref)}let firstImageUrl;for(let image2 of body.querySelectorAll("img[src]")){let src=image2.getAttribute("src"),absoluteSrc=normalizeUrl2(src??void 0,baseUrl);absoluteSrc&&(image2.setAttribute("src",absoluteSrc),firstImageUrl??=absoluteSrc)}return{html:body.innerHTML,firstImageUrl}}function sanitizeArticleHtml(html){return sanitizeHtml(html,{allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","blockquote","pre","code","ul","ol","li","strong","em","b","i","del","a","img","table","thead","tbody","tr","th","td"],allowedAttributes:{a:["href","title"],img:["src","alt","title"],code:["class"],pre:["class"]},allowedSchemes:["http","https","mailto"],disallowedTagsMode:"discard"})}async function fetchUrlImportSource(url,fetchImpl=fetch){let response=await fetchImpl(url,{redirect:"follow",headers:{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8","accept-language":"zh-CN,zh;q=0.9,en;q=0.8","cache-control":"no-cache",pragma:"no-cache"}});if(!response.ok)throw new Error(`URL \u6293\u53D6\u5931\u8D25\uFF1AHTTP ${response.status}`);let raw=stripUnsupportedJsonChars(await response.text());if(!trimToUndefined2(raw))throw new Error("URL \u9875\u9762\u5185\u5BB9\u4E3A\u7A7A\u3002");return{requestedUrl:url,resolvedUrl:response.url||url,raw,checksum:computeChecksum3(raw)}}function parseUrlImportHtml(args){let metadataDocument=new JSDOM(args.raw,{url:args.resolvedUrl}).window.document,articleImageCandidates=extractArticleImageCandidates(metadataDocument,args.resolvedUrl),readabilityDom=new JSDOM(args.raw,{url:args.resolvedUrl}),article=new Readability(readabilityDom.window.document).parse();if(!article?.content||!trimToUndefined2(article.textContent))throw new Error("\u672A\u80FD\u4ECE\u9875\u9762\u4E2D\u63D0\u53D6\u6B63\u6587\u3002");let{html:articleHtml,firstImageUrl}=absolutizeRichTextHtml(article.content,args.resolvedUrl),cleanedHtml=sanitizeArticleHtml(articleHtml).trim();if(!cleanedHtml)throw new Error("\u9875\u9762\u6B63\u6587\u5728\u6E05\u6D17\u540E\u4E3A\u7A7A\u3002");let leadImage=articleImageCandidates[0];if(!firstImageUrl&&leadImage){let altText=leadImage.alt?` alt="${escapeHtmlAttribute(leadImage.alt)}"`:' alt=""';cleanedHtml=`<p><img src="${escapeHtmlAttribute(leadImage.url)}"${altText} /></p>${cleanedHtml}`}let title=getMetaContent(metadataDocument,"og:title")??getMetaContent(metadataDocument,"twitter:title")??trimToUndefined2(metadataDocument.title)??trimToUndefined2(article.title)??getFirstText(metadataDocument,["h1"]),summary=getMetaContent(metadataDocument,"og:description")??getMetaContent(metadataDocument,"description")??trimToUndefined2(article.excerpt),metaCoverUrl=normalizeUrl2(getMetaContent(metadataDocument,"og:image"),args.resolvedUrl)??normalizeUrl2(getMetaContent(metadataDocument,"twitter:image"),args.resolvedUrl),bodyCoverUrl=firstImageUrl,coverUrl=leadImage?.url??bodyCoverUrl??metaCoverUrl,coverMimeType=coverUrl===metaCoverUrl?getMetaContent(metadataDocument,"og:image:type")??inferMimeTypeFromUrl2(coverUrl):inferMimeTypeFromUrl2(coverUrl)??getMetaContent(metadataDocument,"og:image:type"),sourceAuthor=getMetaContent(metadataDocument,"article:author")??getMetaContent(metadataDocument,"author")??getMetaContent(metadataDocument,"parsely-author")??getFirstText(metadataDocument,['[rel="author"]','[itemprop="author"]',".author",".ArticleAuthor-name"]),sourceSite=getMetaContent(metadataDocument,"og:site_name")??(()=>{try{return new URL3(args.resolvedUrl).hostname.replace(/^www\./,"")}catch{return}})(),sourcePublishedAt=normalizePublishedAt(getMetaContent(metadataDocument,"article:published_time")??getMetaContent(metadataDocument,"publishdate")??trimToUndefined2(metadataDocument.querySelector("time[datetime]")?.getAttribute("datetime")));return{requestedUrl:args.requestedUrl,resolvedUrl:args.resolvedUrl,title,summary,coverUrl,coverMimeType,sourceAuthor,sourceSite,sourcePublishedAt,body:cleanedHtml,contentFormat:"html",raw:args.raw,checksum:args.checksum??computeChecksum3(args.raw),warnings:[]}}function buildUrlItemPayload(args){let title=args.title??args.parsed.title??inferDefaultTitleFromUrl(args.parsed.resolvedUrl),slug=args.slug??inferDefaultSlug(args.parsed),summary=args.summary??args.parsed.summary,content={body:args.parsed.body,source_url:args.parsed.resolvedUrl};title&&(content.title=title),summary&&(content.summary=summary),args.parsed.sourceAuthor&&(content.source_author=args.parsed.sourceAuthor),args.parsed.sourceSite&&(content.source_site=args.parsed.sourceSite),args.parsed.sourcePublishedAt&&(content.source_published_at=args.parsed.sourcePublishedAt);let cover=resolveImportedUrlCover({parsed:args.parsed,cover:args.cover,title});return cover&&(content.cover=cover),{...args.itemId?{item_id:args.itemId}:{},collection:args.collection,system:{publish_status:args.publishStatus??"draft",...slug?{slug}:{},...args.tags&&args.tags.length>0?{tags:args.tags}:{},...args.categoryId!==void 0?{category_id:args.categoryId}:{},content_format:args.parsed.contentFormat,source:{source_type:"url",source_url:args.parsed.resolvedUrl,source_path:null,source_raw:args.parsed.raw,checksum:args.parsed.checksum,imported_by:args.importedBy??"ide-agent",parser_version:"url-importer.v1"}},content}}function resolveImportedUrlCover(args){if(args.cover?.mode==="asset"||args.cover?.mode==="remote")return args.cover.value;if(args.cover?.mode!=="none"&&args.parsed.coverUrl)return{title:args.title??"Remote cover",...args.parsed.coverMimeType?{mime_type:args.parsed.coverMimeType}:{},original_url:args.parsed.coverUrl}}async function assetizeParsedUrlImages(args){if(!args.includeBody&&!args.includeCover)return{parsed:args.parsed,cover:{mode:"none"},warnings:[]};let assetization=await assetizeExternalImagesInHtml({sdk:args.sdk,html:args.includeBody?args.parsed.body:"",baseUrl:args.parsed.resolvedUrl,coverUrl:args.includeCover?args.parsed.coverUrl:void 0,coverTitle:args.parsed.title,coverMimeType:args.parsed.coverMimeType,bodyTitle:args.parsed.title});return{parsed:{...args.parsed,body:args.includeBody?assetization.html:args.parsed.body},cover:assetization.cover,warnings:assetization.warnings}}function restrictItemPayloadToSchemaFields(payload,fields){let allowedFieldNames=new Set(fields.map(field=>field.name)),nextContent=Object.fromEntries(Object.entries(payload.content).filter(([key])=>allowedFieldNames.has(key))),droppedFields=Object.keys(payload.content).filter(key=>!allowedFieldNames.has(key));return{payload:{...payload,content:nextContent},droppedFields}}import process3 from"node:process";import{existsSync as existsSync21,readFileSync as readFileSync22}from"node:fs";import{join as join17}from"node:path";import{createHash as createHash9}from"node:crypto";import{existsSync as existsSync20,readdirSync as readdirSync8,readFileSync as readFileSync21}from"node:fs";import{basename as basename6,join as join16,relative as relative5}from"node:path";function assertNonEmptyString(value,field){if(typeof value!="string"||value.trim().length===0)throw new Error(`Auth policy field \`${field}\` must be a non-empty string.`);return value.trim()}function normalizePermissions(value){if(!Array.isArray(value))throw new Error("Auth policy field `permissions` must be an array.");let permissions=value.map((item,index)=>assertNonEmptyString(item,`permissions[${index}]`));return[...new Set(permissions)]}function normalizeAuthPolicy(input){if(typeof input!="object"||input===null)throw new Error("Auth policy must be an object.");let record=input;return{version:assertNonEmptyString(record.version,"version"),role:assertNonEmptyString(record.role,"role"),permissions:normalizePermissions(record.permissions)}}function deriveAuthResourceKey(policy,fallbackName){if(typeof policy=="object"&&policy!==null){let record=policy;if(typeof record.role=="string"&&record.role.trim().length>0)return`auth/${record.role.trim()}`;if(typeof record.policy=="string"&&record.policy.trim().length>0)return`auth/${record.policy.trim()}`}return`auth/${fallbackName}`}var DATA_FORM_ACCESS_SCOPES=["public","own","admin"];var DATA_FORM_GENERATED_SOURCE_TAG="data_form_generated";function buildSourceTagComment(source){return`-- source: ${source}`}function renderColumn(column){let parts=[`${column.column_name} ${column.data_type}`];return parts.push(column.nullable?"NULL":"NOT NULL"),column.default_sql!==void 0&&parts.push(`DEFAULT ${column.default_sql}`),parts.join(" ")}function renderCreateTable(tableName,columns){return[`CREATE TABLE IF NOT EXISTS ${tableName} (`,columns.map(column=>` ${renderColumn(column)}`).join(`,
2475
+ `,4);if(closingIndex===-1)return{frontmatter:{},body:raw.trim(),raw,checksum:checksum3};let frontmatterSource=raw.slice(4,closingIndex),body=raw.slice(closingIndex+5).trim(),parsed=YAML3.parse(frontmatterSource);return{frontmatter:isPlainObject(parsed)?parsed:{},body,raw,checksum:checksum3}}function buildMarkdownItemPayload(args){let parsed=parseMarkdownWithFrontmatter(args.markdownContent),frontmatter={...parsed.frontmatter},title=args.title??toOptionalString(frontmatter.title)??inferDefaultTitleFromPath(args.markdownPath),slug=args.slug??toOptionalString(frontmatter.slug)??inferDefaultSlugFromPath(args.markdownPath),summary=args.summary??toOptionalString(frontmatter.summary),tags=args.tags??toStringArray(frontmatter.tags),categoryId=args.categoryId??toOptionalString(frontmatter.category_id)??null,publishStatus=args.publishStatus??toOptionalString(frontmatter.publish_status)??"draft";delete frontmatter.title,delete frontmatter.slug,delete frontmatter.summary,delete frontmatter.tags,delete frontmatter.category_id,delete frontmatter.publish_status;let content={...frontmatter,body:parsed.body};return title&&(content.title=title),summary&&(content.summary=summary),{...args.itemId?{item_id:args.itemId}:{},collection:args.collection,system:{publish_status:publishStatus,...slug?{slug}:{},...tags!==void 0?{tags}:{},...categoryId?{category_id:categoryId}:{},content_format:"markdown",source:{source_type:"markdown",source_url:null,source_path:args.markdownPath,source_raw:parsed.raw,checksum:parsed.checksum,imported_by:args.importedBy??"ide-agent",parser_version:"markdown-importer.v1"}},content}}function resolveMarkdownImportLookupKey(payload){return typeof payload.item_id=="string"&&payload.item_id.trim().length>0?{kind:"item_id",value:payload.item_id}:typeof payload.system.slug=="string"&&payload.system.slug.trim().length>0?{kind:"slug",value:payload.system.slug}:null}function summarizeMarkdownImportResults(items){let importedOrPlanned=0,skipped=0,draft=0,published=0,archived=0;for(let item of items){if(item.state==="skipped"?skipped+=1:importedOrPlanned+=1,item.publish_status==="draft"){draft+=1;continue}if(item.publish_status==="published"){published+=1;continue}item.publish_status==="archived"&&(archived+=1)}return{total:items.length,imported_or_planned:importedOrPlanned,skipped,draft,published,archived}}function normalizeSlugCandidate(value){return value.trim().slice(0,120)}function applySlugSuffix(baseSlug,suffix){let suffixText=`-${suffix}`;return`${baseSlug.slice(0,Math.max(1,120-suffixText.length))}${suffixText}`}async function findTenantCmsItemByExactSlug(args){let normalizedSlug=normalizeSlugCandidate(args.slug);if(!normalizedSlug)return null;let page=1,pageSize=100;for(;;){let response=await args.sdk.listTenantCmsItems({collection:args.collection,page,pageSize,query:normalizedSlug}),matched=response.items.find(item=>item.system.slug===normalizedSlug);if(matched)return matched;if(page*pageSize>=response.total||response.items.length===0)return null;page+=1}}async function resolveUniqueTenantCmsSlug(args){let normalizedSlug=args.slug?normalizeSlugCandidate(args.slug):void 0;if(!normalizedSlug)return{slug:void 0,adjusted:!1};let candidate=normalizedSlug,suffix=2;for(;;){let conflictsInBatch=args.reservedSlugs?.has(candidate)??!1,existing=conflictsInBatch?null:await findTenantCmsItemByExactSlug({sdk:args.sdk,collection:args.collection,slug:candidate});if(!conflictsInBatch&&(!existing||existing.system.id===args.itemId))return{slug:candidate,adjusted:candidate!==normalizedSlug,originalSlug:candidate!==normalizedSlug?normalizedSlug:void 0};candidate=applySlugSuffix(normalizedSlug,suffix),suffix+=1}}import{createHash as createHash7}from"node:crypto";import{URL as URL3}from"node:url";import{Readability}from"@mozilla/readability";import{JSDOM}from"jsdom";import sanitizeHtml from"sanitize-html";function computeChecksum3(input){return`sha256:${createHash7("sha256").update(input).digest("hex")}`}function stripUnsupportedJsonChars(value){return value.replace(/\u0000/g,"")}function trimToUndefined2(value){let normalized=value?.trim();return normalized||void 0}function getMetaContent(document,key){let selectors=[`meta[property="${key}"]`,`meta[name="${key}"]`,`meta[itemprop="${key}"]`];for(let selector of selectors){let value=trimToUndefined2(document.querySelector(selector)?.getAttribute("content"));if(value)return value}}function getFirstText(document,selectors){for(let selector of selectors){let value=trimToUndefined2(document.querySelector(selector)?.textContent);if(value)return value}}function normalizeUrl2(value,baseUrl){if(!value)return;let trimmed=value.trim();if(trimmed)try{return new URL3(trimmed,baseUrl).toString()}catch{return}}function escapeHtmlAttribute(value){return value.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function inferMimeTypeFromUrl2(value){if(!value)return;let pathname=(()=>{try{return new URL3(value).pathname.toLowerCase()}catch{return value.toLowerCase()}})();if(pathname.endsWith(".png"))return"image/png";if(pathname.endsWith(".webp"))return"image/webp";if(pathname.endsWith(".gif"))return"image/gif";if(pathname.endsWith(".svg"))return"image/svg+xml";if(pathname.endsWith(".jpg")||pathname.endsWith(".jpeg"))return"image/jpeg"}function extractArticleImageCandidates(document,baseUrl){let selectors=[".news-detail .image.parbase img",".news-detail .news-img img",".news-detail .richtext img","article img","main img"],results=[],seen=new Set;for(let selector of selectors)for(let image2 of document.querySelectorAll(selector)){let className=image2.getAttribute("class")?.toLowerCase()??"",parentClassName=image2.parentElement?.getAttribute("class")?.toLowerCase()??"";if(className.includes("qrcode")||className.includes("qr-code")||parentClassName.includes("qrcode")||parentClassName.includes("qr-code"))continue;let rawSrc=image2.getAttribute("src")??image2.getAttribute("data-src")??image2.getAttribute("data-original")??image2.getAttribute("data-original-src")??image2.getAttribute("data-lazy-src")??void 0,absoluteUrl=normalizeUrl2(rawSrc??void 0,baseUrl);!absoluteUrl||seen.has(absoluteUrl)||absoluteUrl.startsWith("data:")||(seen.add(absoluteUrl),results.push({url:absoluteUrl,alt:trimToUndefined2(image2.getAttribute("alt")??image2.getAttribute("title")??void 0)}))}return results}function normalizePublishedAt(value){if(!value)return;let timestamp=Date.parse(value);if(!Number.isNaN(timestamp))return new Date(timestamp).toISOString()}function inferDefaultTitleFromUrl(value){try{let parsed=new URL3(value),segment=parsed.pathname.replace(/\/+$/,"").split("/").filter(Boolean).at(-1)?.trim();return segment&&segment.length>0?decodeURIComponent(segment):parsed.hostname}catch{return}}function stripPageExtension(value){if(value)return value.replace(/\.(html?|xhtml|shtml)$/i,"")}function inferDefaultSlug(args){let candidates=[stripPageExtension(inferDefaultTitleFromUrl(args.resolvedUrl)),stripPageExtension(inferDefaultTitleFromUrl(args.requestedUrl)),args.title];for(let candidate of candidates){let normalized=candidate?.trim().toLowerCase().replace(/[\/\\]+/g,"-").replace(/\s+/g,"-").replace(/-+/g,"-").replace(/^-+|-+$/g,"").slice(0,120);if(normalized)return normalized}}function absolutizeRichTextHtml(html,baseUrl){let body=new JSDOM(`<body>${html}</body>`,{url:baseUrl}).window.document.body;for(let anchor of body.querySelectorAll("a[href]")){let href=anchor.getAttribute("href"),absoluteHref=normalizeUrl2(href??void 0,baseUrl);absoluteHref&&anchor.setAttribute("href",absoluteHref)}let firstImageUrl;for(let image2 of body.querySelectorAll("img[src]")){let src=image2.getAttribute("src"),absoluteSrc=normalizeUrl2(src??void 0,baseUrl);absoluteSrc&&(image2.setAttribute("src",absoluteSrc),firstImageUrl??=absoluteSrc)}return{html:body.innerHTML,firstImageUrl}}function sanitizeArticleHtml(html){return sanitizeHtml(html,{allowedTags:["h1","h2","h3","h4","h5","h6","p","br","hr","blockquote","pre","code","ul","ol","li","strong","em","b","i","del","a","img","table","thead","tbody","tr","th","td"],allowedAttributes:{a:["href","title"],img:["src","alt","title"],code:["class"],pre:["class"]},allowedSchemes:["http","https","mailto"],disallowedTagsMode:"discard"})}async function fetchUrlImportSource(url,fetchImpl=fetch){let response=await fetchImpl(url,{redirect:"follow",headers:{"user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36",accept:"text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8","accept-language":"zh-CN,zh;q=0.9,en;q=0.8","cache-control":"no-cache",pragma:"no-cache"}});if(!response.ok)throw new Error(`URL \u6293\u53D6\u5931\u8D25\uFF1AHTTP ${response.status}`);let raw=stripUnsupportedJsonChars(await response.text());if(!trimToUndefined2(raw))throw new Error("URL \u9875\u9762\u5185\u5BB9\u4E3A\u7A7A\u3002");return{requestedUrl:url,resolvedUrl:response.url||url,raw,checksum:computeChecksum3(raw)}}function parseUrlImportHtml(args){let metadataDocument=new JSDOM(args.raw,{url:args.resolvedUrl}).window.document,articleImageCandidates=extractArticleImageCandidates(metadataDocument,args.resolvedUrl),readabilityDom=new JSDOM(args.raw,{url:args.resolvedUrl}),article=new Readability(readabilityDom.window.document).parse();if(!article?.content||!trimToUndefined2(article.textContent))throw new Error("\u672A\u80FD\u4ECE\u9875\u9762\u4E2D\u63D0\u53D6\u6B63\u6587\u3002");let{html:articleHtml,firstImageUrl}=absolutizeRichTextHtml(article.content,args.resolvedUrl),cleanedHtml=sanitizeArticleHtml(articleHtml).trim();if(!cleanedHtml)throw new Error("\u9875\u9762\u6B63\u6587\u5728\u6E05\u6D17\u540E\u4E3A\u7A7A\u3002");let leadImage=articleImageCandidates[0];if(!firstImageUrl&&leadImage){let altText=leadImage.alt?` alt="${escapeHtmlAttribute(leadImage.alt)}"`:' alt=""';cleanedHtml=`<p><img src="${escapeHtmlAttribute(leadImage.url)}"${altText} /></p>${cleanedHtml}`}let title=getMetaContent(metadataDocument,"og:title")??getMetaContent(metadataDocument,"twitter:title")??trimToUndefined2(metadataDocument.title)??trimToUndefined2(article.title)??getFirstText(metadataDocument,["h1"]),summary=getMetaContent(metadataDocument,"og:description")??getMetaContent(metadataDocument,"description")??trimToUndefined2(article.excerpt),metaCoverUrl=normalizeUrl2(getMetaContent(metadataDocument,"og:image"),args.resolvedUrl)??normalizeUrl2(getMetaContent(metadataDocument,"twitter:image"),args.resolvedUrl),bodyCoverUrl=firstImageUrl,coverUrl=leadImage?.url??bodyCoverUrl??metaCoverUrl,coverMimeType=coverUrl===metaCoverUrl?getMetaContent(metadataDocument,"og:image:type")??inferMimeTypeFromUrl2(coverUrl):inferMimeTypeFromUrl2(coverUrl)??getMetaContent(metadataDocument,"og:image:type"),sourceAuthor=getMetaContent(metadataDocument,"article:author")??getMetaContent(metadataDocument,"author")??getMetaContent(metadataDocument,"parsely-author")??getFirstText(metadataDocument,['[rel="author"]','[itemprop="author"]',".author",".ArticleAuthor-name"]),sourceSite=getMetaContent(metadataDocument,"og:site_name")??(()=>{try{return new URL3(args.resolvedUrl).hostname.replace(/^www\./,"")}catch{return}})(),sourcePublishedAt=normalizePublishedAt(getMetaContent(metadataDocument,"article:published_time")??getMetaContent(metadataDocument,"publishdate")??trimToUndefined2(metadataDocument.querySelector("time[datetime]")?.getAttribute("datetime")));return{requestedUrl:args.requestedUrl,resolvedUrl:args.resolvedUrl,title,summary,coverUrl,coverMimeType,sourceAuthor,sourceSite,sourcePublishedAt,body:cleanedHtml,contentFormat:"html",raw:args.raw,checksum:args.checksum??computeChecksum3(args.raw),warnings:[]}}function buildUrlItemPayload(args){let title=args.title??args.parsed.title??inferDefaultTitleFromUrl(args.parsed.resolvedUrl),slug=args.slug??inferDefaultSlug(args.parsed),summary=args.summary??args.parsed.summary,content={body:args.parsed.body,source_url:args.parsed.resolvedUrl};title&&(content.title=title),summary&&(content.summary=summary),args.parsed.sourceAuthor&&(content.source_author=args.parsed.sourceAuthor),args.parsed.sourceSite&&(content.source_site=args.parsed.sourceSite),args.parsed.sourcePublishedAt&&(content.source_published_at=args.parsed.sourcePublishedAt);let cover=resolveImportedUrlCover({parsed:args.parsed,cover:args.cover,title});return cover&&(content.cover=cover),{...args.itemId?{item_id:args.itemId}:{},collection:args.collection,system:{publish_status:args.publishStatus??"draft",...slug?{slug}:{},...args.tags&&args.tags.length>0?{tags:args.tags}:{},...args.categoryId!==void 0?{category_id:args.categoryId}:{},content_format:args.parsed.contentFormat,source:{source_type:"url",source_url:args.parsed.resolvedUrl,source_path:null,source_raw:args.parsed.raw,checksum:args.parsed.checksum,imported_by:args.importedBy??"ide-agent",parser_version:"url-importer.v1"}},content}}function resolveImportedUrlCover(args){if(args.cover?.mode==="asset"||args.cover?.mode==="remote")return args.cover.value;if(args.cover?.mode!=="none"&&args.parsed.coverUrl)return{title:args.title??"Remote cover",...args.parsed.coverMimeType?{mime_type:args.parsed.coverMimeType}:{},original_url:args.parsed.coverUrl}}async function assetizeParsedUrlImages(args){if(!args.includeBody&&!args.includeCover)return{parsed:args.parsed,cover:{mode:"none"},warnings:[]};let assetization=await assetizeExternalImagesInHtml({sdk:args.sdk,html:args.includeBody?args.parsed.body:"",baseUrl:args.parsed.resolvedUrl,coverUrl:args.includeCover?args.parsed.coverUrl:void 0,coverTitle:args.parsed.title,coverMimeType:args.parsed.coverMimeType,bodyTitle:args.parsed.title});return{parsed:{...args.parsed,body:args.includeBody?assetization.html:args.parsed.body},cover:assetization.cover,warnings:assetization.warnings}}function restrictItemPayloadToSchemaFields(payload,fields){let allowedFieldNames=new Set(fields.map(field=>field.name)),nextContent=Object.fromEntries(Object.entries(payload.content).filter(([key])=>allowedFieldNames.has(key))),droppedFields=Object.keys(payload.content).filter(key=>!allowedFieldNames.has(key));return{payload:{...payload,content:nextContent},droppedFields}}import process3 from"node:process";import{existsSync as existsSync21,readFileSync as readFileSync22}from"node:fs";import{join as join17}from"node:path";import{createHash as createHash9}from"node:crypto";import{existsSync as existsSync20,readdirSync as readdirSync8,readFileSync as readFileSync21}from"node:fs";import{basename as basename7,join as join16,relative as relative5}from"node:path";function assertNonEmptyString(value,field){if(typeof value!="string"||value.trim().length===0)throw new Error(`Auth policy field \`${field}\` must be a non-empty string.`);return value.trim()}function normalizePermissions(value){if(!Array.isArray(value))throw new Error("Auth policy field `permissions` must be an array.");let permissions=value.map((item,index)=>assertNonEmptyString(item,`permissions[${index}]`));return[...new Set(permissions)]}function normalizeAuthPolicy(input){if(typeof input!="object"||input===null)throw new Error("Auth policy must be an object.");let record=input;return{version:assertNonEmptyString(record.version,"version"),role:assertNonEmptyString(record.role,"role"),permissions:normalizePermissions(record.permissions)}}function deriveAuthResourceKey(policy,fallbackName){if(typeof policy=="object"&&policy!==null){let record=policy;if(typeof record.role=="string"&&record.role.trim().length>0)return`auth/${record.role.trim()}`;if(typeof record.policy=="string"&&record.policy.trim().length>0)return`auth/${record.policy.trim()}`}return`auth/${fallbackName}`}var DATA_FORM_ACCESS_SCOPES=["public","own","admin"];var DATA_FORM_GENERATED_SOURCE_TAG="data_form_generated";function buildSourceTagComment(source){return`-- source: ${source}`}function renderColumn(column){let parts=[`${column.column_name} ${column.data_type}`];return parts.push(column.nullable?"NULL":"NOT NULL"),column.default_sql!==void 0&&parts.push(`DEFAULT ${column.default_sql}`),parts.join(" ")}function renderCreateTable(tableName,columns){return[`CREATE TABLE IF NOT EXISTS ${tableName} (`,columns.map(column=>` ${renderColumn(column)}`).join(`,
2471
2476
  `),");"].join(`
2472
2477
  `)}function renderAlterColumn(tableName,columnName,nullable,defaultSql){let statements=[];return nullable!==void 0&&statements.push(`ALTER TABLE ${tableName} ALTER COLUMN ${columnName} ${nullable?"DROP NOT NULL":"SET NOT NULL"};`),defaultSql!==void 0&&statements.push(`ALTER TABLE ${tableName} ALTER COLUMN ${columnName} SET DEFAULT ${defaultSql};`),statements}function renderDataFormDiffSql(diff){let statements=[buildSourceTagComment(diff.source),`-- resource_key: ${diff.resource_key}`,`-- table_name: ${diff.table_name}`,""];for(let operation of diff.operations)switch(operation.kind){case"create_table":statements.push(renderCreateTable(operation.table_name,operation.columns));break;case"add_column":statements.push(`ALTER TABLE ${operation.table_name} ADD COLUMN ${renderColumn(operation.column)};`);break;case"alter_column":statements.push(...renderAlterColumn(operation.table_name,operation.column_name,operation.nullable,operation.default_sql));break}return`${statements.filter(item=>item.length>0).join(`
2473
2478
  `)}
@@ -2494,7 +2499,7 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2494
2499
  `)}var DATA_FORM_RUNTIME_ROUTE_PREFIX="/api/public/apps";function buildDataFormRuntimeBasePath(appId){return`${DATA_FORM_RUNTIME_ROUTE_PREFIX}/${encodeURIComponent(appId)}/data-form`}function buildDataFormRuntimeResourcesPath(appId){return`${buildDataFormRuntimeBasePath(appId)}/resources`}function buildDataFormRuntimeRecordsPath(appId,resourceKey){return`${buildDataFormRuntimeResourcesPath(appId)}/${encodeURIComponent(resourceKey)}/records`}function buildDataFormRuntimeRecordPath(appId,resourceKey,recordId){return`${buildDataFormRuntimeRecordsPath(appId,resourceKey)}/${encodeURIComponent(recordId)}`}function normalizeDataFormRuntimeListQuery(query){return{page:normalizePositiveInteger(query.page,1),page_size:normalizePositiveInteger(query.page_size,20),owner_scope:query.owner_scope==="all"?"all":"me",q:typeof query.q=="string"?query.q.trim():""}}function normalizePositiveInteger(value,fallback){if(!Number.isFinite(value)||value===void 0)return fallback;let normalized=Math.floor(value);return normalized>0?normalized:fallback}function buildWorkflowObjectModelSummary(args){let objectTypes=new Set;for(let definition of args.definitions)definition.object_type&&objectTypes.add(definition.object_type);for(let binding of args.bindings)binding.object_type&&objectTypes.add(binding.object_type);return Array.from(objectTypes).sort((left,right)=>left.localeCompare(right)).map(objectType=>{let definitions=args.definitions.filter(item=>item.object_type===objectType),bindings=args.bindings.filter(item=>item.object_type===objectType),bindingDefinitionKeys=Array.from(new Set(bindings.map(item=>item.definition_key))).sort((left,right)=>left.localeCompare(right)),definitionKeys=Array.from(new Set([...definitions.map(item=>item.definition_key),...bindingDefinitionKeys])).sort((left,right)=>left.localeCompare(right)),relatedRoleBindings=args.roleBindings.filter(item=>bindingDefinitionKeys.includes(item.definition_key));return{object_type:objectType,default_definition_key:bindingDefinitionKeys.length===1?bindingDefinitionKeys[0]:definitions.length===1?definitions[0]?.definition_key:void 0,definition_keys:definitionKeys,binding_definition_keys:bindingDefinitionKeys,role_keys:Array.from(new Set(relatedRoleBindings.map(item=>item.role_key))).sort((left,right)=>left.localeCompare(right)),principal_role_keys:Array.from(new Set(relatedRoleBindings.map(item=>item.principal_role_key))).sort((left,right)=>left.localeCompare(right)),target_scopes:Array.from(new Set(bindings.map(item=>item.target_scope))).sort((left,right)=>left.localeCompare(right))}})}async function syncLocalControlPlaneSummary(args){try{let summary=await collectControlPlaneSummary(args);updateSourceContext(args.startDir??process.cwd(),{tenant_id:args.tenantId,app_id:args.appId,control_plane:summary})}catch{}}async function collectControlPlaneSummary(args){let[authInspect,dbPreview,dbProd,workflowDefinitions,workflowBindings,deploymentTimeline,cmsCollections]=await Promise.all([args.sdk.getTenantAppEndUserAuthInspect(args.appId).catch(()=>null),args.sdk.getTenantAppDbInstance(args.appId,"preview").catch(()=>null),args.sdk.getTenantAppDbInstance(args.appId,"prod").catch(()=>null),args.sdk.listWorkflowDefinitions({target_id:args.appId,status:"active"}).catch(()=>[]),args.sdk.listWorkflowBindings({target_id:args.appId}).catch(()=>[]),args.sdk.listTenantAppDeploymentTimeline(args.appId,{limit:10}).catch(()=>({items:[]})),args.sdk.listTenantCmsCollections().catch(()=>({items:[]}))]),previewDeployment=deploymentTimeline.items.find(item=>item.env==="preview"&&item.is_current_release),prodDeployment=deploymentTimeline.items.find(item=>item.env==="prod"&&item.is_current_release),previewAuth=authInspect?.environments.find(item=>item.env==="preview"),prodAuth=authInspect?.environments.find(item=>item.env==="prod"),workflowRoleBindings=(await Promise.all(workflowBindings.map(binding=>args.sdk.listWorkflowRoleBindings({target_scope:binding.target_scope,target_id:binding.target_id,definition_key:binding.definition_key}).catch(()=>[])))).flat(),cmsCollectionDetails=await Promise.all(cmsCollections.items.map(async item=>{let discovered=await args.sdk.discoverTenantCmsCollection(item.collection).catch(()=>null);return{...item,has_active_schema:!!discovered?.active_schema,has_draft_schema:!!discovered?.draft_schema,categories_count:discovered?.categories.length??0}}));return{synced_at:new Date().toISOString(),auth:{inspect_status:authInspect?.inspect_status??null,issues:authInspect?.issues??[],environments:{preview:previewAuth?{status:previewAuth.status,missing_binding_keys:previewAuth.missing_binding_keys,issues:previewAuth.issues}:void 0,prod:prodAuth?{status:prodAuth.status,missing_binding_keys:prodAuth.missing_binding_keys,issues:prodAuth.issues}:void 0}},db:{preview:dbPreview?{bound:dbPreview.bound,status:dbPreview.status,schema_name:dbPreview.schema_name??null,database_name:dbPreview.database_name??null,tables_count:typeof dbPreview.tables_count=="number"?dbPreview.tables_count:null,latest_migration:dbPreview.latest_migration?.migration_path??null}:void 0,prod:dbProd?{bound:dbProd.bound,status:dbProd.status,schema_name:dbProd.schema_name??null,database_name:dbProd.database_name??null,tables_count:typeof dbProd.tables_count=="number"?dbProd.tables_count:null,latest_migration:dbProd.latest_migration?.migration_path??null}:void 0},workflow:{active_definition_count:workflowDefinitions.length,binding_count:workflowBindings.length,definition_keys:workflowDefinitions.map(item=>item.definition_key),definitions:workflowDefinitions.map(item=>({definition_key:item.definition_key,object_type:item.object_type,status:item.status})),bindings:workflowBindings.map(item=>({definition_key:item.definition_key,target_scope:item.target_scope,target_id:item.target_id,object_type:item.object_type,status:item.status,role_binding_count:workflowRoleBindings.filter(binding=>binding.definition_key===item.definition_key&&binding.target_id===item.target_id).length})),role_bindings:workflowRoleBindings.map(item=>({definition_key:item.definition_key,role_key:item.role_key,actor_scope:item.actor_scope,principal_role_key:item.principal_role_key})),object_models:buildWorkflowObjectModelSummary({definitions:workflowDefinitions,bindings:workflowBindings,roleBindings:workflowRoleBindings})},cms:{collection_count:cmsCollectionDetails.length,collections:cmsCollectionDetails.map(item=>({collection:item.collection,label:item.label,template:item.template,collection_status:item.collection_status,item_count:item.item_count,has_draft:item.has_draft,schema_status:item.schema_status,schema_version:item.schema_version,has_active_schema:item.has_active_schema,has_draft_schema:item.has_draft_schema,categories_count:item.categories_count}))},runtime:{preview:previewDeployment?{health:previewDeployment.health??null,source_version_id:previewDeployment.source_version_id??null,preview_url:previewDeployment.preview_url??null}:void 0,prod:prodDeployment?{health:prodDeployment.health??null,source_version_id:prodDeployment.source_version_id??null}:void 0}}}import YAML4 from"yaml";var GENERATED_AUTH_MANIFEST_PATH=".platform/generated/auth/end-user-auth.json",GENERATED_AUTH_POLICY={version:"0.1.0",role:"end-user-auth",permissions:["auth:enabled"]};async function runResourcesCommand(args){let subcommand=args.rest[0];if(subcommand!=="diff"&&subcommand!=="apply"&&subcommand!=="rollback")throw new Error("`platform resources` \u4EC5\u652F\u6301 `diff`\u3001`apply` \u6216 `rollback` \u5B50\u547D\u4EE4\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let appRoot=findAppRoot(process.cwd()),binding=readBinding(appRoot)?.binding,tenantId=readStringOption5(args,"tenant")??binding?.tenant_id,appId=readStringOption5(args,"app")??binding?.app_id,env=readStringOption5(args,"env")??binding?.env??"preview",baseSnapshotId=readStringOption5(args,"base-snapshot"),targetSnapshotId=args.rest[1]??readStringOption5(args,"target-snapshot");if(!tenantId||!appId)throw new Error("`platform resources` \u9700\u8981\u5DF2\u7ED1\u5B9A\u9879\u76EE\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");if(subcommand==="rollback"&&!targetSnapshotId)throw new Error("`platform resources rollback` \u9700\u8981 `<snapshot-id>` \u6216 `--target-snapshot <snapshot-id>`\u3002");let requestedBy=await resolveRequestedBy2({accessToken:selectApiToken(credentials),tenantId});subcommand!=="rollback"&&readAppManifest(appRoot);let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"}),localResources=await collectEffectiveResources(appRoot,{sdk,appId});if(subcommand==="rollback"){let approveId=readStringOption5(args,"approve-id"),rollbackPayload={operation:"rollback",tenant_id:tenantId,app_id:appId,env,target_snapshot_id:targetSnapshotId,requested_by:requestedBy,reason:readStringOption5(args,"reason")??"manual_resource_rollback",...approveId?{approve_id:approveId}:{}},result2=await withPendingFeedback(args.options.json===!0,`\u6B63\u5728\u6267\u884C\u8D44\u6E90\u56DE\u9000: ${appId}/${env} -> ${targetSnapshotId}`,"\u8D44\u6E90\u56DE\u9000\u4ECD\u5728\u8FDB\u884C\uFF0C\u8BF7\u7EE7\u7EED\u7B49\u5F85\u63A7\u5236\u9762\u5B8C\u6210\u5BA1\u6279\u6821\u9A8C\u3001\u5FEB\u7167\u88C5\u8F7D\u4E0E\u8D44\u6E90\u5E94\u7528...",()=>sdk.rollbackResources(rollbackPayload)).catch(error=>{throw formatResourceCommandError({error,appId,env,subcommand,targetSnapshotId,approveId})});if(args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
2495
2500
  `);return}printRollback(result2,appRoot,env);return}let payload={operation:subcommand==="apply"?"apply":"diff",tenant_id:tenantId,app_id:appId,env,requested_by:requestedBy,...subcommand==="apply"&&args.options["dry-run"]===!0?{dry_run:!0}:{},...baseSnapshotId?{base_snapshot_id:baseSnapshotId}:{},local_resources:localResources};if(subcommand==="diff"){let result2=await sdk.diffResources(payload).catch(error=>{throw formatResourceCommandError({error,appId,env,subcommand,baseSnapshotId})});if(await syncLocalControlPlaneSummary({sdk,startDir:appRoot,tenantId,appId}),args.options.json===!0){process.stdout.write(`${JSON.stringify(result2,null,2)}
2496
2501
  `);return}printDiff(result2,appRoot,{baseSnapshotSource:baseSnapshotId?"explicit":"auto"});return}let result=await withPendingFeedback(args.options.json===!0,`\u6B63\u5728\u6267\u884C\u8D44\u6E90\u53D8\u66F4: ${appId}/${env}${baseSnapshotId?`\uFF0C\u57FA\u7EBF ${baseSnapshotId}`:"\uFF0C\u57FA\u7EBF\u5C06\u81EA\u52A8\u89E3\u6790"}`,"\u8D44\u6E90 Apply \u4ECD\u5728\u8FDB\u884C\uFF0C\u8BF7\u7EE7\u7EED\u7B49\u5F85\u63A7\u5236\u9762\u5B8C\u6210\u57FA\u7EBF\u89E3\u6790\u3001diff\u3001\u9501\u6821\u9A8C\u4E0E\u8D44\u6E90\u7F16\u6392...",()=>sdk.applyResources(payload)).catch(error=>{throw formatResourceCommandError({error,appId,env,subcommand,baseSnapshotId})});if(await syncLocalControlPlaneSummary({sdk,startDir:appRoot,tenantId,appId}),args.options.json===!0){process.stdout.write(`${JSON.stringify(result,null,2)}
2497
- `);return}printApply(result,appRoot,{baseSnapshotSource:baseSnapshotId?"explicit":"auto"})}async function resolveRequestedBy2(args){return(await createControlApiSdk({accessToken:args.accessToken,tenantId:args.tenantId,capability:"auth",requestClass:"control"}).getWhoAmI()).subject_id}function readStringOption5(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}async function collectEffectiveResources(appRoot,options){let dbResources=collectDbResources(appRoot),authResources=collectAuthResources(appRoot);if(authResources.length>0||!options?.sdk||!options.appId)return[...dbResources,...authResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path));let bridgedAuthResources=await collectBridgedAuthResources(options.sdk,options.appId);return[...dbResources,...authResources,...bridgedAuthResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path))}function collectDbResources(appRoot){let directory=join16(appRoot,"resources","db","migrations"),sqlResources=existsSync20(directory)?readdirSync8(directory).filter(entry=>entry.endsWith(".sql")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(directory,entry),sql=readFileSync21(filePath,"utf8"),manifestPath=toWorkspaceRelative(appRoot,filePath);return{resource_type:"db",resource_key:`db/${basename6(entry,".sql")}`,manifest_path:manifestPath,checksum:checksum2(sql),spec:{kind:"migration",sql,statements_count:sql.split(";").map(part=>part.trim()).filter(Boolean).length}}}):[],dataFormDirectory=join16(appRoot,"resources","data-forms"),dataFormResources=existsSync20(dataFormDirectory)?readdirSync8(dataFormDirectory).filter(entry=>entry.endsWith(".yaml")||entry.endsWith(".yml")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(dataFormDirectory,entry),raw=YAML4.parse(readFileSync21(filePath,"utf8")),schema=normalizeDataFormResourceSchema(raw),manifestPath=toWorkspaceRelative(appRoot,filePath),artifact=buildDataFormMigrationArtifact({schema,sourceManifestPath:manifestPath});return{resource_type:"db",resource_key:artifact.resource_key,manifest_path:manifestPath,checksum:artifact.checksum,spec:{kind:"migration",sql:artifact.sql,statements_count:artifact.statements_count,source:artifact.source,table_name:artifact.table_name,source_manifest_path:artifact.source_manifest_path,source_of_truth:"data_form_schema",data_form_resource:schema}}}):[];return[...sqlResources,...dataFormResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path))}function collectAuthResources(appRoot){let directory=join16(appRoot,"resources","auth","policies");return existsSync20(directory)?readdirSync8(directory).filter(entry=>entry.endsWith(".json")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(directory,entry),raw=readFileSync21(filePath,"utf8"),policy=normalizeAuthPolicy(JSON.parse(raw)),manifestPath=toWorkspaceRelative(appRoot,filePath);return{resource_type:"auth",resource_key:deriveAuthResourceKey(policy,basename6(entry,".json")),manifest_path:manifestPath,checksum:checksum2(raw),spec:{kind:"policy",policy}}}):[]}async function collectBridgedAuthResources(sdk,appId){if((await sdk.getTenantAppEndUserAuthConfig(appId)).auth_enabled!==!0)return[];let policy=normalizeAuthPolicy(GENERATED_AUTH_POLICY),raw=JSON.stringify(policy,null,2);return[{resource_type:"auth",resource_key:deriveAuthResourceKey(policy,"end-user-auth"),manifest_path:GENERATED_AUTH_MANIFEST_PATH,checksum:checksum2(raw),spec:{kind:"policy",policy}}]}function toWorkspaceRelative(appRoot,filePath){return relative5(appRoot,filePath).split("\\").join("/")}function checksum2(value){return createHash9("sha256").update(value).digest("hex")}function printDiff(result,appRoot,options){let lines=[`\u8D44\u6E90 Diff \u5DF2\u5B8C\u6210\uFF0C\u57FA\u7EBF\u5FEB\u7167: ${result.base_snapshot_id}`,`\u57FA\u7EBF\u6765\u6E90: ${options.baseSnapshotSource==="auto"?"\u81EA\u52A8\u89E3\u6790":"\u624B\u52A8\u6307\u5B9A"}`,`\u672C\u5730\u8D44\u6E90: ${result.resources.local_count}\uFF0C\u8FDC\u7AEF\u8D44\u6E90: ${result.resources.remote_count}`,`\u65B0\u589E ${result.summary.added}\uFF0C\u4FEE\u6539 ${result.summary.modified}\uFF0C\u5220\u9664 ${result.summary.deleted}`];if(result.changes.length>0){lines.push("");for(let change of result.changes)lines.push(`- ${formatChangePrefix(change.change_type)} ${relative5(appRoot,join16(appRoot,change.manifest_path)).split("\\").join("/")}`+(change.previous_checksum?` (${change.previous_checksum} -> ${change.checksum??"deleted"})`:""))}process.stdout.write(`${lines.join(`
2502
+ `);return}printApply(result,appRoot,{baseSnapshotSource:baseSnapshotId?"explicit":"auto"})}async function resolveRequestedBy2(args){return(await createControlApiSdk({accessToken:args.accessToken,tenantId:args.tenantId,capability:"auth",requestClass:"control"}).getWhoAmI()).subject_id}function readStringOption5(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}async function collectEffectiveResources(appRoot,options){let dbResources=collectDbResources(appRoot),authResources=collectAuthResources(appRoot);if(authResources.length>0||!options?.sdk||!options.appId)return[...dbResources,...authResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path));let bridgedAuthResources=await collectBridgedAuthResources(options.sdk,options.appId);return[...dbResources,...authResources,...bridgedAuthResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path))}function collectDbResources(appRoot){let directory=join16(appRoot,"resources","db","migrations"),sqlResources=existsSync20(directory)?readdirSync8(directory).filter(entry=>entry.endsWith(".sql")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(directory,entry),sql=readFileSync21(filePath,"utf8"),manifestPath=toWorkspaceRelative(appRoot,filePath);return{resource_type:"db",resource_key:`db/${basename7(entry,".sql")}`,manifest_path:manifestPath,checksum:checksum2(sql),spec:{kind:"migration",sql,statements_count:sql.split(";").map(part=>part.trim()).filter(Boolean).length}}}):[],dataFormDirectory=join16(appRoot,"resources","data-forms"),dataFormResources=existsSync20(dataFormDirectory)?readdirSync8(dataFormDirectory).filter(entry=>entry.endsWith(".yaml")||entry.endsWith(".yml")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(dataFormDirectory,entry),raw=YAML4.parse(readFileSync21(filePath,"utf8")),schema=normalizeDataFormResourceSchema(raw),manifestPath=toWorkspaceRelative(appRoot,filePath),artifact=buildDataFormMigrationArtifact({schema,sourceManifestPath:manifestPath});return{resource_type:"db",resource_key:artifact.resource_key,manifest_path:manifestPath,checksum:artifact.checksum,spec:{kind:"migration",sql:artifact.sql,statements_count:artifact.statements_count,source:artifact.source,table_name:artifact.table_name,source_manifest_path:artifact.source_manifest_path,source_of_truth:"data_form_schema",data_form_resource:schema}}}):[];return[...sqlResources,...dataFormResources].sort((left,right)=>left.manifest_path.localeCompare(right.manifest_path))}function collectAuthResources(appRoot){let directory=join16(appRoot,"resources","auth","policies");return existsSync20(directory)?readdirSync8(directory).filter(entry=>entry.endsWith(".json")).sort((left,right)=>left.localeCompare(right)).map(entry=>{let filePath=join16(directory,entry),raw=readFileSync21(filePath,"utf8"),policy=normalizeAuthPolicy(JSON.parse(raw)),manifestPath=toWorkspaceRelative(appRoot,filePath);return{resource_type:"auth",resource_key:deriveAuthResourceKey(policy,basename7(entry,".json")),manifest_path:manifestPath,checksum:checksum2(raw),spec:{kind:"policy",policy}}}):[]}async function collectBridgedAuthResources(sdk,appId){if((await sdk.getTenantAppEndUserAuthConfig(appId)).auth_enabled!==!0)return[];let policy=normalizeAuthPolicy(GENERATED_AUTH_POLICY),raw=JSON.stringify(policy,null,2);return[{resource_type:"auth",resource_key:deriveAuthResourceKey(policy,"end-user-auth"),manifest_path:GENERATED_AUTH_MANIFEST_PATH,checksum:checksum2(raw),spec:{kind:"policy",policy}}]}function toWorkspaceRelative(appRoot,filePath){return relative5(appRoot,filePath).split("\\").join("/")}function checksum2(value){return createHash9("sha256").update(value).digest("hex")}function printDiff(result,appRoot,options){let lines=[`\u8D44\u6E90 Diff \u5DF2\u5B8C\u6210\uFF0C\u57FA\u7EBF\u5FEB\u7167: ${result.base_snapshot_id}`,`\u57FA\u7EBF\u6765\u6E90: ${options.baseSnapshotSource==="auto"?"\u81EA\u52A8\u89E3\u6790":"\u624B\u52A8\u6307\u5B9A"}`,`\u672C\u5730\u8D44\u6E90: ${result.resources.local_count}\uFF0C\u8FDC\u7AEF\u8D44\u6E90: ${result.resources.remote_count}`,`\u65B0\u589E ${result.summary.added}\uFF0C\u4FEE\u6539 ${result.summary.modified}\uFF0C\u5220\u9664 ${result.summary.deleted}`];if(result.changes.length>0){lines.push("");for(let change of result.changes)lines.push(`- ${formatChangePrefix(change.change_type)} ${relative5(appRoot,join16(appRoot,change.manifest_path)).split("\\").join("/")}`+(change.previous_checksum?` (${change.previous_checksum} -> ${change.checksum??"deleted"})`:""))}process.stdout.write(`${lines.join(`
2498
2503
  `)}
2499
2504
  `)}function printApply(result,appRoot,options){let lines=[`\u8D44\u6E90 Apply ${result.status==="failed"?"\u5931\u8D25":"\u5B8C\u6210"}${result.dry_run?"\uFF08dry-run\uFF09":""}`,`\u57FA\u7EBF\u5FEB\u7167: ${result.base_snapshot_id}`,`\u57FA\u7EBF\u6765\u6E90: ${options.baseSnapshotSource==="auto"?"\u81EA\u52A8\u89E3\u6790":"\u624B\u52A8\u6307\u5B9A"}`,`status: ${result.status}`,`\u65B0\u589E ${result.summary.added}\uFF0C\u4FEE\u6539 ${result.summary.modified}\uFF0C\u5220\u9664 ${result.summary.deleted}`,`\u6267\u884C\u8D44\u6E90: ${result.summary.applied}\uFF0CDB ${result.summary.db_resources}\uFF0CAuth ${result.summary.auth_resources}`];if(result.result_snapshot_id&&lines.push(`\u7ED3\u679C\u5FEB\u7167: ${result.result_snapshot_id}`),result.db_skill&&lines.push(`DB Skill: ${result.db_skill.binding_key} -> ${result.db_skill.tenant_database_id} (schema=${result.db_skill.schema_name})`),result.auth_skill&&lines.push(`Auth Skill: ${result.auth_skill.binding_key} -> ${result.auth_skill.skill_instance_id}`),result.errors&&result.errors.length>0&&lines.push(`errors: ${result.errors.join(" | ")}`),result.status==="succeeded"&&result.result_snapshot_id&&lines.push(`\u4E0B\u4E00\u6B21 diff/apply \u53EF\u76F4\u63A5\u4F7F\u7528: --base-snapshot ${result.result_snapshot_id}`),result.status==="dry_run"&&lines.push("\u4E0B\u4E00\u6B65: \u786E\u8BA4\u7ED3\u679C\u65E0\u8BEF\u540E\uFF0C\u53BB\u6389 `--dry-run` \u518D\u6267\u884C\u4E00\u6B21 apply\u3002"),result.changes.length>0){lines.push("");for(let change of result.changes)lines.push(`- ${formatChangePrefix(change.change_type)} ${relative5(appRoot,join16(appRoot,change.manifest_path)).split("\\").join("/")}`)}process.stdout.write(`${lines.join(`
2500
2505
  `)}
@@ -2547,13 +2552,13 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2547
2552
  `)+`
2548
2553
  `);return}process.stdout.write(["platform data-form",""," platform data-form validate [--resource <resource-key>] [--json]"," platform data-form compile [--resource <resource-key>] [--json]"," platform data-form inspect [--resource <resource-key>] [--json]"," platform data-form apply [--env preview|prod] [--dry-run] [--json]"," platform data-form records --resource <resource-key> [--record <record-id>] [--env preview|prod] [--page <n>] [--page-size <n>] [--owner-scope me|all] [--q <keyword>] [--json]",""," \u672C\u5730\u6821\u9A8C\u3001\u67E5\u770B\u751F\u6210 migration\u3001\u901A\u8FC7\u73B0\u6709\u8D44\u6E90\u4E3B\u94FE\u5E94\u7528 `resources/data-forms/*.yaml`\uFF0C\u5E76\u901A\u8FC7 runtime API \u67E5\u8BE2\u8BB0\u5F55\u3002"].join(`
2549
2554
  `)+`
2550
- `)}import{spawn as spawn4}from"node:child_process";import net from"node:net";import WebSocket from"ws";async function prepareLocalDevDatabaseBindings(runtimeBindings,options={}){let databaseUrl=runtimeBindings.DATABASE_URL?.trim();if(!databaseUrl)return{bindings:runtimeBindings,warnings:[],cleanup:null};let proxyTransport=runtimeBindings.DATABASE_PROXY_TRANSPORT?.trim(),proxyWsUrl=runtimeBindings.DATABASE_PROXY_WS_URL?.trim();if(proxyTransport==="ws_tunnel"&&proxyWsUrl)return await prepareWebSocketDatabaseTunnel(runtimeBindings,databaseUrl,proxyWsUrl);if(!shouldTunnelDatabaseUrl(databaseUrl))return{bindings:runtimeBindings,warnings:[],cleanup:null};if(!((process.env.PLATFORM_INTERNAL_ENABLE_DB_SSH_TUNNEL||"").trim()==="1"))throw new Error(["dev_runtime_binding_not_available","\u5F53\u524D\u73AF\u5883\u5C1A\u672A\u63D0\u4F9B\u5F00\u53D1\u673A\u53EF\u8FBE\u7684 DB binding\uFF0C`platform dev --remote-bindings` \u5DF2\u62D2\u7EDD\u4F7F\u7528\u79C1\u7F51\u6570\u636E\u5E93\u5730\u5740\u3002","\u8BF7\u5148\u6539\u7528 `platform preview` \u9A8C\u8BC1\u771F\u5B9E\u5199\u5E93\u94FE\u8DEF\uFF1B\u5982\u4E3A\u5E73\u53F0\u7BA1\u7406\u5458\u5185\u90E8\u6392\u969C\uFF0C\u53EF\u663E\u5F0F\u8BBE\u7F6E `PLATFORM_INTERNAL_ENABLE_DB_SSH_TUNNEL=1` \u540E\u91CD\u8BD5\u3002"].join(" "));let sshHost=(options.sshHost||process.env.TEST_ENV_SSH_HOST||"").trim();if(!sshHost)throw new Error("\u5F53\u524D\u5DF2\u663E\u5F0F\u542F\u7528\u5185\u90E8 SSH \u515C\u5E95\uFF0C\u4F46\u672A\u914D\u7F6E TEST_ENV_SSH_HOST\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u672C\u5730 SSH \u96A7\u9053\u3002");let parsed=new URL(databaseUrl),remoteHost=parsed.hostname,remotePort=Number(parsed.port||"5432"),localPort=await allocateLocalPort(),child=spawn4("ssh",["-o","ExitOnForwardFailure=yes","-o","BatchMode=yes","-o","ConnectTimeout=8","-N","-L",`127.0.0.1:${localPort}:${remoteHost}:${remotePort}`,sshHost],{stdio:"ignore"});try{await waitForTunnelReady(localPort,child)}catch(error){throw child.kill("SIGTERM"),await waitForChildExit(child),error}let localUrl=rewriteDatabaseUrlForLocalPort(databaseUrl,localPort);return{bindings:{...runtimeBindings,DATABASE_URL:localUrl},warnings:[`\u68C0\u6D4B\u5230\u79C1\u7F51 DB host\uFF08${remoteHost}:${remotePort}\uFF09\uFF0C\u5DF2\u901A\u8FC7 SSH \u96A7\u9053\u6620\u5C04\u5230\u672C\u5730 127.0.0.1:${localPort}\u3002`],cleanup:async()=>{child.kill("SIGTERM"),await waitForChildExit(child)}}}async function prepareWebSocketDatabaseTunnel(runtimeBindings,databaseUrl,wsUrl){let localPort=await allocateLocalPort(),sockets=new Set,bridges=new Set,server=net.createServer(clientSocket=>{clientSocket.setNoDelay(!0),sockets.add(clientSocket);let bridge=new WebSocket(wsUrl);bridges.add(bridge);let closeBoth=()=>{sockets.delete(clientSocket),bridges.delete(bridge),clientSocket.destroyed||clientSocket.destroy(),(bridge.readyState===WebSocket.OPEN||bridge.readyState===WebSocket.CONNECTING)&&bridge.close()};bridge.on("open",()=>{clientSocket.on("data",chunk=>{bridge.readyState===WebSocket.OPEN&&bridge.send(chunk)}),clientSocket.resume()}),bridge.on("message",payload=>{clientSocket.write(Buffer.isBuffer(payload)?payload:Buffer.from(payload))}),bridge.on("close",closeBoth),bridge.on("error",closeBoth),clientSocket.on("close",closeBoth),clientSocket.on("error",closeBoth),clientSocket.pause()});return await listenLocalServer(server,localPort),{bindings:{...runtimeBindings,DATABASE_URL:rewriteDatabaseUrlForLocalPort(databaseUrl,localPort)},warnings:[`\u68C0\u6D4B\u5230\u6B63\u5F0F dev proxy WebSocket \u6570\u636E\u9762\uFF0C\u5DF2\u6620\u5C04\u5230\u672C\u5730 127.0.0.1:${localPort}\u3002`],cleanup:async()=>{for(let socket of sockets)socket.destroyed||socket.destroy();for(let bridge of bridges)(bridge.readyState===WebSocket.OPEN||bridge.readyState===WebSocket.CONNECTING)&&bridge.close();await closeServer(server)}}}function shouldTunnelDatabaseUrl(databaseUrl){try{let url=new URL(databaseUrl);return shouldTunnelHostname(url.hostname)}catch{return!1}}function rewriteDatabaseUrlForLocalPort(databaseUrl,localPort){let url=new URL(databaseUrl);return url.hostname="127.0.0.1",url.port=String(localPort),url.toString()}function shouldTunnelHostname(hostname){let value=hostname.trim().toLowerCase();return!value||["localhost","127.0.0.1"].includes(value)?!1:!!(["host.docker.internal","host.containers.internal"].includes(value)||isPrivateIpv4(value))}function isPrivateIpv4(hostname){let parts=hostname.split(".");if(parts.length!==4||parts.some(part=>!/^\d+$/.test(part)))return!1;let[a,b]=parts.map(part=>Number(part));return a===10||a===192&&b===168||a===172&&b>=16&&b<=31}async function allocateLocalPort(){return await new Promise((resolve16,reject)=>{let server=net.createServer();server.once("error",reject),server.listen(0,"127.0.0.1",()=>{let address=server.address();if(!address||typeof address=="string"){server.close(()=>reject(new Error("\u65E0\u6CD5\u5206\u914D\u672C\u5730\u7AEF\u53E3\u3002")));return}let port=address.port;server.close(error=>{if(error){reject(error);return}resolve16(port)})})})}async function listenLocalServer(server,port){await new Promise((resolve16,reject)=>{server.once("error",reject),server.listen(port,"127.0.0.1",()=>{server.off("error",reject),resolve16()})})}async function closeServer(server){await new Promise(resolve16=>{server.close(()=>resolve16())})}async function waitForTunnelReady(localPort,child){let startedAt=Date.now();for(;Date.now()-startedAt<1e4;){if(child.exitCode!==null)throw new Error(`SSH \u96A7\u9053\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08code=${child.exitCode}\uFF09\u3002`);if(await canConnect("127.0.0.1",localPort))return;await sleep3(200)}throw new Error(`SSH \u96A7\u9053\u672A\u5728\u9884\u671F\u65F6\u95F4\u5185\u5C31\u7EEA\uFF1A127.0.0.1:${localPort}`)}async function canConnect(host,port){return await new Promise(resolve16=>{let socket=net.createConnection({host,port}),done=value=>{socket.removeAllListeners(),socket.destroyed||socket.destroy(),resolve16(value)};socket.once("connect",()=>done(!0)),socket.once("error",()=>done(!1)),socket.setTimeout(500,()=>done(!1))})}async function waitForChildExit(child){await new Promise(resolve16=>{if(child.exitCode!==null){resolve16();return}child.once("exit",()=>resolve16()),setTimeout(()=>resolve16(),1e3)})}function sleep3(ms){return new Promise(resolve16=>{setTimeout(resolve16,ms)})}import{spawn as spawn5}from"node:child_process";import{watch}from"node:fs";import process4 from"node:process";var IGNORED_PATH_SEGMENTS=new Set(["node_modules",".git",".platform","dist",".next"]),RESTART_DEBOUNCE_MS=250;async function runDevSupervisor(options){let state={child:null,watcher:null,restartTimer:null,stopping:!1,restartPending:!1},stopChild=()=>{!state.child||state.child.killed||state.child.kill("SIGTERM")},cleanup=()=>{state.stopping=!0,state.restartTimer&&(clearTimeout(state.restartTimer),state.restartTimer=null),state.watcher?.close(),state.watcher=null,stopChild()},handleSignal=signal=>{cleanup(),process4.kill(process4.pid,signal)};process4.once("SIGINT",handleSignal),process4.once("SIGTERM",handleSignal);let startChild=()=>{state.child=spawn5(options.command,{cwd:options.cwd,env:options.env,stdio:"inherit",shell:!0}),state.child.on("exit",(code2,signal)=>{let exitedChild=state.child;if(state.child=null,state.stopping){state.resolveRun?.();return}if(state.restartPending){state.restartPending=!1,startChild();return}if(signal){state.rejectRun?.(new Error(`dev \u547D\u4EE4\u88AB\u4FE1\u53F7 ${signal} \u7EC8\u6B62`));return}if(code2&&code2!==0){state.rejectRun?.(new Error(`dev \u547D\u4EE4\u9000\u51FA\uFF0C\u72B6\u6001\u7801 ${code2}`));return}exitedChild&&state.resolveRun?.()}),state.child.on("error",error=>{state.rejectRun?.(error instanceof Error?error:new Error(String(error)))})},scheduleRestart=changedPath=>{let normalized=typeof changedPath=="string"?changedPath:changedPath?.toString("utf8");normalized&&normalized.split(/[\\/]+/u).filter(Boolean).some(segment=>IGNORED_PATH_SEGMENTS.has(segment))||(state.restartTimer&&clearTimeout(state.restartTimer),state.restartTimer=setTimeout(()=>{if(state.restartTimer=null,!state.child){startChild();return}state.restartPending=!0,options.onWatching?.(`\u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4${normalized?`\uFF1A${normalized}`:""}\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B...`),stopChild()},RESTART_DEBOUNCE_MS))};try{state.watcher=watch(options.watchRoot,{recursive:!0},(_eventType,filename)=>{scheduleRestart(filename)}),options.onWatching?.("\u5DF2\u542F\u7528\u6587\u4EF6\u76D1\u542C\uFF1B\u6E90\u7801\u53D8\u66F4\u540E\u5C06\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B\u3002")}catch{options.onWatching?.("\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u9012\u5F52\u6587\u4EF6\u76D1\u542C\uFF1Bdev \u5B50\u8FDB\u7A0B\u5C06\u4FDD\u6301\u5355\u6B21\u542F\u52A8\u3002")}startChild();try{await new Promise((resolve16,reject)=>{state.resolveRun=resolve16,state.rejectRun=reject})}finally{cleanup(),process4.removeListener("SIGINT",handleSignal),process4.removeListener("SIGTERM",handleSignal)}}import{chmodSync as chmodSync2,existsSync as existsSync23,mkdirSync as mkdirSync11,readFileSync as readFileSync24,rmSync as rmSync5,writeFileSync as writeFileSync12}from"node:fs";import{dirname as dirname13,resolve as resolve14}from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import YAML6 from"yaml";var MANAGED_ENV_KEYS=["CONTROL_API_BASE_URL","PUBLIC_API_BASE_URL","RUNTIME_API_BASE_URL","OIDC_ISSUER","OIDC_AUDIENCE","LOGTO_CLI_APP_ID","LOGTO_CLI_REDIRECT_URI","LOGTO_TENANT_APP_ID","LOGTO_TENANT_REDIRECT_URI","TEST_ENV_PROFILE"];function getEnvironmentProfilePath(){return resolveCliStateFilePath("environment.json")}function loadStoredEnvironmentProfile(){let envProfilePath=getEnvironmentProfilePath();return existsSync23(envProfilePath)?JSON.parse(readFileSync24(envProfilePath,"utf8")):null}function persistStoredEnvironmentProfile(input){withCliStateFileWriteFallback({fileName:"environment.json",operation:"\u5199\u5165",write:({filePath,stateDir})=>{mkdirSync11(stateDir,{recursive:!0}),writeFileSync12(filePath,`${JSON.stringify({active_profile:input.active_profile,values:normalizeProfileValues(input.values),updated_at:new Date().toISOString()},null,2)}
2551
- `,"utf8"),chmodSync2(filePath,384)}})}function clearStoredEnvironmentProfile(){let envProfilePath=getEnvironmentProfilePath();existsSync23(envProfilePath)&&rmSync5(envProfilePath)}function applyStoredEnvironmentProfile(env=process.env){let stored=loadStoredEnvironmentProfile();if(!stored)return null;for(let key of MANAGED_ENV_KEYS){let current=env[key];if(typeof current=="string"&&current.trim().length>0)continue;let nextValue=stored.values[key];typeof nextValue=="string"&&nextValue.trim().length>0&&(env[key]=nextValue)}return stored}function listKnownEnvironmentProfiles(startDir=getInvocationCwd()){return loadEnvironmentProfileRegistry(startDir).map(profile=>({name:profile.name,values:resolveProfileValues(profile)}))}function resolveKnownEnvironmentProfile(profileName,startDir=getInvocationCwd()){let matched=loadEnvironmentProfileRegistry(startDir).find(profile=>profile.name===profileName);return matched?{name:matched.name,values:resolveProfileValues(matched)}:null}function normalizeProfileValues(values){let normalized={};for(let key of MANAGED_ENV_KEYS){let value=values[key];if(typeof value!="string")continue;let trimmed=value.trim();trimmed.length>0&&(normalized[key]=trimmed)}return normalized}function resolveProfileValues(profile){let values={},scheme=profile.topology?.scheme?.trim(),controlHost=profile.hosts?.control?.trim(),publicHost=profile.hosts?.public?.trim(),runtimeHost=profile.hosts?.runtime?.trim(),authHost=profile.hosts?.auth?.trim(),tenantHost=profile.hosts?.tenant?.trim(),issuer=profile.auth?.issuer?.trim(),audience=profile.auth?.audience?.trim();return scheme&&controlHost&&(values.CONTROL_API_BASE_URL=`${scheme}://${controlHost}`),scheme&&publicHost&&(values.PUBLIC_API_BASE_URL=`${scheme}://${publicHost}`),scheme&&runtimeHost&&(values.RUNTIME_API_BASE_URL=`${scheme}://${runtimeHost}`),issuer&&(values.OIDC_ISSUER=issuer),audience&&(values.OIDC_AUDIENCE=audience),tenantHost&&scheme&&(values.LOGTO_TENANT_REDIRECT_URI=`${scheme}://${tenantHost}/callback`),authHost&&profile.name==="local"?values.LOGTO_CLI_REDIRECT_URI="http://localhost:7300/callback":authHost&&(values.LOGTO_CLI_REDIRECT_URI="http://127.0.0.1:7300/callback"),values.TEST_ENV_PROFILE=profile.name,values}function loadEnvironmentProfileRegistry(startDir){let registryPath=resolveEnvironmentRegistryPath(startDir);if(!existsSync23(registryPath))return[];let parsed=YAML6.parse(readFileSync24(registryPath,"utf8"));return Array.isArray(parsed?.profiles)?parsed.profiles:[]}function resolveEnvironmentRegistryPath(startDir){let invocationWorkspaceRoot=findWorkspaceRoot(startDir),invocationCandidate=resolve14(invocationWorkspaceRoot,"deploy","registry","environment-profiles.yaml");if(existsSync23(invocationCandidate))return invocationCandidate;let cliModuleRoot=resolve14(dirname13(fileURLToPath5(import.meta.url)),".."),cliWorkspaceRoot=findWorkspaceRoot(cliModuleRoot);return resolve14(cliWorkspaceRoot,"deploy","registry","environment-profiles.yaml")}async function runLogsCommand(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let appRoot=findAppRoot(process.cwd()),binding=readBinding(appRoot)?.binding,tenantId=readStringOption8(args,"tenant")??binding?.tenant_id,appId=readStringOption8(args,"app")??binding?.app_id,env=readStringOption8(args,"env")??binding?.env??"preview",releaseId=readStringOption8(args,"release"),limit=readNumberOption3(args,"limit")??100,follow=args.options.follow===!0,from=readStringOption8(args,"from")??new Date(Date.now()-900*1e3).toISOString(),to=readStringOption8(args,"to")??new Date().toISOString();if(!tenantId||!appId)throw new Error("`platform logs` \u9700\u8981\u5DF2\u7ED1\u5B9A\u9879\u76EE\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"}),payload={tenant_id:tenantId,app_id:appId,env,...releaseId?{release_id:releaseId}:{},from,to,limit,follow};if(!follow){let result=await sdk.queryLogs(payload);printLogs(result,args.options.json===!0);return}let seen=new Set,currentFrom=from;for(;;){let result=await sdk.queryLogs({...payload,from:currentFrom,to:new Date().toISOString(),follow:!0});if(args.options.json===!0)process.stdout.write(`${JSON.stringify(result,null,2)}
2555
+ `)}import{spawn as spawn2}from"node:child_process";import net from"node:net";import WebSocket from"ws";async function prepareLocalDevDatabaseBindings(runtimeBindings,options={}){let databaseUrl=runtimeBindings.DATABASE_URL?.trim();if(!databaseUrl)return{bindings:runtimeBindings,warnings:[],cleanup:null};let proxyTransport=runtimeBindings.DATABASE_PROXY_TRANSPORT?.trim(),proxyWsUrl=runtimeBindings.DATABASE_PROXY_WS_URL?.trim();if(proxyTransport==="ws_tunnel"&&proxyWsUrl)return await prepareWebSocketDatabaseTunnel(runtimeBindings,databaseUrl,proxyWsUrl);if(!shouldTunnelDatabaseUrl(databaseUrl))return{bindings:runtimeBindings,warnings:[],cleanup:null};if(!((process.env.PLATFORM_INTERNAL_ENABLE_DB_SSH_TUNNEL||"").trim()==="1"))throw new Error(["dev_runtime_binding_not_available","\u5F53\u524D\u73AF\u5883\u5C1A\u672A\u63D0\u4F9B\u5F00\u53D1\u673A\u53EF\u8FBE\u7684 DB binding\uFF0C`platform dev --remote-bindings` \u5DF2\u62D2\u7EDD\u4F7F\u7528\u79C1\u7F51\u6570\u636E\u5E93\u5730\u5740\u3002","\u8BF7\u5148\u6539\u7528 `platform preview` \u9A8C\u8BC1\u771F\u5B9E\u5199\u5E93\u94FE\u8DEF\uFF1B\u5982\u4E3A\u5E73\u53F0\u7BA1\u7406\u5458\u5185\u90E8\u6392\u969C\uFF0C\u53EF\u663E\u5F0F\u8BBE\u7F6E `PLATFORM_INTERNAL_ENABLE_DB_SSH_TUNNEL=1` \u540E\u91CD\u8BD5\u3002"].join(" "));let sshHost=(options.sshHost||process.env.TEST_ENV_SSH_HOST||"").trim();if(!sshHost)throw new Error("\u5F53\u524D\u5DF2\u663E\u5F0F\u542F\u7528\u5185\u90E8 SSH \u515C\u5E95\uFF0C\u4F46\u672A\u914D\u7F6E TEST_ENV_SSH_HOST\uFF0C\u65E0\u6CD5\u5EFA\u7ACB\u672C\u5730 SSH \u96A7\u9053\u3002");let parsed=new URL(databaseUrl),remoteHost=parsed.hostname,remotePort=Number(parsed.port||"5432"),localPort=await allocateLocalPort(),child=spawn2("ssh",["-o","ExitOnForwardFailure=yes","-o","BatchMode=yes","-o","ConnectTimeout=8","-N","-L",`127.0.0.1:${localPort}:${remoteHost}:${remotePort}`,sshHost],{stdio:"ignore"});try{await waitForTunnelReady(localPort,child)}catch(error){throw child.kill("SIGTERM"),await waitForChildExit(child),error}let localUrl=rewriteDatabaseUrlForLocalPort(databaseUrl,localPort);return{bindings:{...runtimeBindings,DATABASE_URL:localUrl},warnings:[`\u68C0\u6D4B\u5230\u79C1\u7F51 DB host\uFF08${remoteHost}:${remotePort}\uFF09\uFF0C\u5DF2\u901A\u8FC7 SSH \u96A7\u9053\u6620\u5C04\u5230\u672C\u5730 127.0.0.1:${localPort}\u3002`],cleanup:async()=>{child.kill("SIGTERM"),await waitForChildExit(child)}}}async function prepareWebSocketDatabaseTunnel(runtimeBindings,databaseUrl,wsUrl){let localPort=await allocateLocalPort(),sockets=new Set,bridges=new Set,server=net.createServer(clientSocket=>{clientSocket.setNoDelay(!0),sockets.add(clientSocket);let bridge=new WebSocket(wsUrl);bridges.add(bridge);let closeBoth=()=>{sockets.delete(clientSocket),bridges.delete(bridge),clientSocket.destroyed||clientSocket.destroy(),(bridge.readyState===WebSocket.OPEN||bridge.readyState===WebSocket.CONNECTING)&&bridge.close()};bridge.on("open",()=>{clientSocket.on("data",chunk=>{bridge.readyState===WebSocket.OPEN&&bridge.send(chunk)}),clientSocket.resume()}),bridge.on("message",payload=>{clientSocket.write(Buffer.isBuffer(payload)?payload:Buffer.from(payload))}),bridge.on("close",closeBoth),bridge.on("error",closeBoth),clientSocket.on("close",closeBoth),clientSocket.on("error",closeBoth),clientSocket.pause()});return await listenLocalServer(server,localPort),{bindings:{...runtimeBindings,DATABASE_URL:rewriteDatabaseUrlForLocalPort(databaseUrl,localPort)},warnings:[`\u68C0\u6D4B\u5230\u6B63\u5F0F dev proxy WebSocket \u6570\u636E\u9762\uFF0C\u5DF2\u6620\u5C04\u5230\u672C\u5730 127.0.0.1:${localPort}\u3002`],cleanup:async()=>{for(let socket of sockets)socket.destroyed||socket.destroy();for(let bridge of bridges)(bridge.readyState===WebSocket.OPEN||bridge.readyState===WebSocket.CONNECTING)&&bridge.close();await closeServer(server)}}}function shouldTunnelDatabaseUrl(databaseUrl){try{let url=new URL(databaseUrl);return shouldTunnelHostname(url.hostname)}catch{return!1}}function rewriteDatabaseUrlForLocalPort(databaseUrl,localPort){let url=new URL(databaseUrl);return url.hostname="127.0.0.1",url.port=String(localPort),url.toString()}function shouldTunnelHostname(hostname){let value=hostname.trim().toLowerCase();return!value||["localhost","127.0.0.1"].includes(value)?!1:!!(["host.docker.internal","host.containers.internal"].includes(value)||isPrivateIpv4(value))}function isPrivateIpv4(hostname){let parts=hostname.split(".");if(parts.length!==4||parts.some(part=>!/^\d+$/.test(part)))return!1;let[a,b]=parts.map(part=>Number(part));return a===10||a===192&&b===168||a===172&&b>=16&&b<=31}async function allocateLocalPort(){return await new Promise((resolve17,reject)=>{let server=net.createServer();server.once("error",reject),server.listen(0,"127.0.0.1",()=>{let address=server.address();if(!address||typeof address=="string"){server.close(()=>reject(new Error("\u65E0\u6CD5\u5206\u914D\u672C\u5730\u7AEF\u53E3\u3002")));return}let port=address.port;server.close(error=>{if(error){reject(error);return}resolve17(port)})})})}async function listenLocalServer(server,port){await new Promise((resolve17,reject)=>{server.once("error",reject),server.listen(port,"127.0.0.1",()=>{server.off("error",reject),resolve17()})})}async function closeServer(server){await new Promise(resolve17=>{server.close(()=>resolve17())})}async function waitForTunnelReady(localPort,child){let startedAt=Date.now();for(;Date.now()-startedAt<1e4;){if(child.exitCode!==null)throw new Error(`SSH \u96A7\u9053\u8FDB\u7A0B\u63D0\u524D\u9000\u51FA\uFF08code=${child.exitCode}\uFF09\u3002`);if(await canConnect("127.0.0.1",localPort))return;await sleep3(200)}throw new Error(`SSH \u96A7\u9053\u672A\u5728\u9884\u671F\u65F6\u95F4\u5185\u5C31\u7EEA\uFF1A127.0.0.1:${localPort}`)}async function canConnect(host,port){return await new Promise(resolve17=>{let socket=net.createConnection({host,port}),done=value=>{socket.removeAllListeners(),socket.destroyed||socket.destroy(),resolve17(value)};socket.once("connect",()=>done(!0)),socket.once("error",()=>done(!1)),socket.setTimeout(500,()=>done(!1))})}async function waitForChildExit(child){await new Promise(resolve17=>{if(child.exitCode!==null){resolve17();return}child.once("exit",()=>resolve17()),setTimeout(()=>resolve17(),1e3)})}function sleep3(ms){return new Promise(resolve17=>{setTimeout(resolve17,ms)})}import{spawn as spawn3}from"node:child_process";import{watch}from"node:fs";import process4 from"node:process";var IGNORED_PATH_SEGMENTS=new Set(["node_modules",".git",".platform","dist",".next"]),RESTART_DEBOUNCE_MS=250;async function runDevSupervisor(options){let platform=options.platform??process4.platform,spawnImpl=options.spawnImpl??spawn3,terminateProcessTreeImpl=options.terminateProcessTreeImpl??terminateProcessTree,signalSource=options.signalSource??process4,restartDebounceMs=options.restartDebounceMs??RESTART_DEBOUNCE_MS,expectedStops=new WeakSet,state={child:null,watcher:null,restartTimer:null,stopping:!1,restarting:!1,restartPending:!1,cleanupPromise:null},runPromise=new Promise((resolve17,reject)=>{state.resolveRun=resolve17,state.rejectRun=reject}),stopChild=async()=>{let child=state.child;if(!child)return;expectedStops.add(child);let exitPromise=waitForChildExit2(child);if(typeof child.pid=="number"){try{await terminateProcessTreeImpl(child.pid,{platform})}catch(error){if(child.exitCode===null&&child.signalCode===null)throw error}await exitPromise}else child.kill("SIGTERM");state.child===child&&(state.child=null)},cleanup=()=>(state.cleanupPromise||(state.stopping=!0,state.restartTimer&&(clearTimeout(state.restartTimer),state.restartTimer=null),state.watcher?.close(),state.watcher=null,state.cleanupPromise=stopChild()),state.cleanupPromise),handleSignal=signal=>{cleanup().then(()=>{let exitCode=signal==="SIGINT"?130:143;(options.setExitCode??(code2=>{process4.exitCode=code2}))(exitCode),state.resolveRun?.()}).catch(error=>{state.rejectRun?.(error instanceof Error?error:new Error(String(error)))})},handleSigint=()=>handleSignal("SIGINT"),handleSigterm=()=>handleSignal("SIGTERM");signalSource.once("SIGINT",handleSigint),signalSource.once("SIGTERM",handleSigterm);let startChild=()=>{let child=spawnImpl(options.command,{cwd:options.cwd,env:options.env,stdio:"inherit",shell:!0,detached:platform!=="win32"});state.child=child,child.on("exit",(code2,signal)=>{if(state.child===child&&(state.child=null),!(expectedStops.has(child)||state.stopping||state.restarting)){if(signal){state.rejectRun?.(new Error(`dev \u547D\u4EE4\u88AB\u4FE1\u53F7 ${signal} \u7EC8\u6B62`));return}if(code2&&code2!==0){state.rejectRun?.(new Error(`dev \u547D\u4EE4\u9000\u51FA\uFF0C\u72B6\u6001\u7801 ${code2}`));return}state.resolveRun?.()}}),child.on("error",error=>{state.rejectRun?.(error instanceof Error?error:new Error(String(error)))})},performPendingRestarts=async()=>{if(!(state.restarting||state.stopping)){state.restarting=!0;try{for(;state.restartPending&&!state.stopping;)state.restartPending=!1,await stopChild(),state.stopping||startChild()}finally{state.restarting=!1}}},scheduleRestart=changedPath=>{let normalized=typeof changedPath=="string"?changedPath:changedPath?.toString("utf8");normalized&&normalized.split(/[\\/]+/u).filter(Boolean).some(segment=>IGNORED_PATH_SEGMENTS.has(segment))||(state.restartTimer&&clearTimeout(state.restartTimer),state.restartTimer=setTimeout(()=>{state.restartTimer=null,state.restartPending=!0,options.onWatching?.(`\u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4${normalized?`\uFF1A${normalized}`:""}\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B...`),performPendingRestarts().catch(error=>{state.rejectRun?.(error instanceof Error?error:new Error(String(error)))})},restartDebounceMs))};if(options.watchRoot)try{state.watcher=watch(options.watchRoot,{recursive:!0},(_eventType,filename)=>{scheduleRestart(filename)}),options.onWatching?.("\u5DF2\u542F\u7528\u6587\u4EF6\u76D1\u542C\uFF1B\u6E90\u7801\u53D8\u66F4\u540E\u5C06\u81EA\u52A8\u91CD\u542F dev \u5B50\u8FDB\u7A0B\u3002")}catch{options.onWatching?.("\u5F53\u524D\u8FD0\u884C\u73AF\u5883\u4E0D\u652F\u6301\u9012\u5F52\u6587\u4EF6\u76D1\u542C\uFF1Bdev \u5B50\u8FDB\u7A0B\u5C06\u4FDD\u6301\u5355\u6B21\u542F\u52A8\u3002")}startChild();try{await runPromise}finally{try{await cleanup()}finally{signalSource.removeListener("SIGINT",handleSigint),signalSource.removeListener("SIGTERM",handleSigterm)}}}function waitForChildExit2(child){return child.exitCode!==null||child.signalCode!==null?Promise.resolve():new Promise(resolve17=>{child.once("exit",()=>resolve17())})}import{chmodSync as chmodSync2,existsSync as existsSync23,mkdirSync as mkdirSync11,readFileSync as readFileSync24,rmSync as rmSync6,writeFileSync as writeFileSync12}from"node:fs";import{dirname as dirname13,resolve as resolve15}from"node:path";import{fileURLToPath as fileURLToPath5}from"node:url";import YAML6 from"yaml";var MANAGED_ENV_KEYS=["CONTROL_API_BASE_URL","PUBLIC_API_BASE_URL","RUNTIME_API_BASE_URL","OIDC_ISSUER","OIDC_AUDIENCE","LOGTO_CLI_APP_ID","LOGTO_CLI_REDIRECT_URI","LOGTO_TENANT_APP_ID","LOGTO_TENANT_REDIRECT_URI","TEST_ENV_PROFILE"];function getEnvironmentProfilePath(){return resolveCliStateFilePath("environment.json")}function loadStoredEnvironmentProfile(){let envProfilePath=getEnvironmentProfilePath();return existsSync23(envProfilePath)?JSON.parse(readFileSync24(envProfilePath,"utf8")):null}function persistStoredEnvironmentProfile(input){withCliStateFileWriteFallback({fileName:"environment.json",operation:"\u5199\u5165",write:({filePath,stateDir})=>{mkdirSync11(stateDir,{recursive:!0}),writeFileSync12(filePath,`${JSON.stringify({active_profile:input.active_profile,values:normalizeProfileValues(input.values),updated_at:new Date().toISOString()},null,2)}
2556
+ `,"utf8"),chmodSync2(filePath,384)}})}function clearStoredEnvironmentProfile(){let envProfilePath=getEnvironmentProfilePath();existsSync23(envProfilePath)&&rmSync6(envProfilePath)}function applyStoredEnvironmentProfile(env=process.env){let stored=loadStoredEnvironmentProfile();if(!stored)return null;for(let key of MANAGED_ENV_KEYS){let current=env[key];if(typeof current=="string"&&current.trim().length>0)continue;let nextValue=stored.values[key];typeof nextValue=="string"&&nextValue.trim().length>0&&(env[key]=nextValue)}return stored}function listKnownEnvironmentProfiles(startDir=getInvocationCwd()){return loadEnvironmentProfileRegistry(startDir).map(profile=>({name:profile.name,values:resolveProfileValues(profile)}))}function resolveKnownEnvironmentProfile(profileName,startDir=getInvocationCwd()){let matched=loadEnvironmentProfileRegistry(startDir).find(profile=>profile.name===profileName);return matched?{name:matched.name,values:resolveProfileValues(matched)}:null}function normalizeProfileValues(values){let normalized={};for(let key of MANAGED_ENV_KEYS){let value=values[key];if(typeof value!="string")continue;let trimmed=value.trim();trimmed.length>0&&(normalized[key]=trimmed)}return normalized}function resolveProfileValues(profile){let values={},scheme=profile.topology?.scheme?.trim(),controlHost=profile.hosts?.control?.trim(),publicHost=profile.hosts?.public?.trim(),runtimeHost=profile.hosts?.runtime?.trim(),authHost=profile.hosts?.auth?.trim(),tenantHost=profile.hosts?.tenant?.trim(),issuer=profile.auth?.issuer?.trim(),audience=profile.auth?.audience?.trim();return scheme&&controlHost&&(values.CONTROL_API_BASE_URL=`${scheme}://${controlHost}`),scheme&&publicHost&&(values.PUBLIC_API_BASE_URL=`${scheme}://${publicHost}`),scheme&&runtimeHost&&(values.RUNTIME_API_BASE_URL=`${scheme}://${runtimeHost}`),issuer&&(values.OIDC_ISSUER=issuer),audience&&(values.OIDC_AUDIENCE=audience),tenantHost&&scheme&&(values.LOGTO_TENANT_REDIRECT_URI=`${scheme}://${tenantHost}/callback`),authHost&&profile.name==="local"?values.LOGTO_CLI_REDIRECT_URI="http://localhost:7300/callback":authHost&&(values.LOGTO_CLI_REDIRECT_URI="http://127.0.0.1:7300/callback"),values.TEST_ENV_PROFILE=profile.name,values}function loadEnvironmentProfileRegistry(startDir){let registryPath=resolveEnvironmentRegistryPath(startDir);if(!existsSync23(registryPath))return[];let parsed=YAML6.parse(readFileSync24(registryPath,"utf8"));return Array.isArray(parsed?.profiles)?parsed.profiles:[]}function resolveEnvironmentRegistryPath(startDir){let invocationWorkspaceRoot=findWorkspaceRoot(startDir),invocationCandidate=resolve15(invocationWorkspaceRoot,"deploy","registry","environment-profiles.yaml");if(existsSync23(invocationCandidate))return invocationCandidate;let cliModuleRoot=resolve15(dirname13(fileURLToPath5(import.meta.url)),".."),cliWorkspaceRoot=findWorkspaceRoot(cliModuleRoot);return resolve15(cliWorkspaceRoot,"deploy","registry","environment-profiles.yaml")}async function runLogsCommand(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let appRoot=findAppRoot(process.cwd()),binding=readBinding(appRoot)?.binding,tenantId=readStringOption8(args,"tenant")??binding?.tenant_id,appId=readStringOption8(args,"app")??binding?.app_id,env=readStringOption8(args,"env")??binding?.env??"preview",releaseId=readStringOption8(args,"release"),limit=readNumberOption3(args,"limit")??100,follow=args.options.follow===!0,from=readStringOption8(args,"from")??new Date(Date.now()-900*1e3).toISOString(),to=readStringOption8(args,"to")??new Date().toISOString();if(!tenantId||!appId)throw new Error("`platform logs` \u9700\u8981\u5DF2\u7ED1\u5B9A\u9879\u76EE\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"m1",requestClass:"control"}),payload={tenant_id:tenantId,app_id:appId,env,...releaseId?{release_id:releaseId}:{},from,to,limit,follow};if(!follow){let result=await sdk.queryLogs(payload);printLogs(result,args.options.json===!0);return}let seen=new Set,currentFrom=from;for(;;){let result=await sdk.queryLogs({...payload,from:currentFrom,to:new Date().toISOString(),follow:!0});if(args.options.json===!0)process.stdout.write(`${JSON.stringify(result,null,2)}
2552
2557
  `);else for(let entry of result.entries)seen.has(entry.id)||(seen.add(entry.id),process.stdout.write(`${formatEntry(entry)}
2553
2558
  `));result.entries.length>0&&(currentFrom=result.entries[result.entries.length-1]?.timestamp??currentFrom),await sleep4(2e3)}}function printLogs(result,asJson){if(asJson){process.stdout.write(`${JSON.stringify(result,null,2)}
2554
2559
  `);return}if(result.entries.length===0){process.stdout.write(`\u672A\u67E5\u8BE2\u5230\u65E5\u5FD7\u3002
2555
2560
  `);return}for(let entry of result.entries)process.stdout.write(`${formatEntry(entry)}
2556
- `)}function formatEntry(entry){return`[${entry.timestamp}] ${entry.level.toUpperCase()} ${entry.source}/${entry.stream}: ${entry.message}`}function readStringOption8(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readNumberOption3(args,key){let value=readStringOption8(args,key);if(!value)return;let parsed=Number(value);return Number.isFinite(parsed)?parsed:void 0}function sleep4(ms){return new Promise(resolve16=>{setTimeout(resolve16,ms)})}import process5 from"node:process";async function runNotificationCommand(args){let subcommand=args.rest[0];if(!subcommand||!["inbox","announce","delivery","end-user"].includes(subcommand))throw new Error("`platform notification` \u4EC5\u652F\u6301 `inbox`\u3001`announce`\u3001`delivery` \u6216 `end-user` \u5B50\u547D\u4EE4\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let context=resolveNotificationContext(args),sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId:context.tenantId,capability:"notification",requestClass:"control"});if(subcommand==="inbox"){await runInboxSubcommand(sdk,context,args);return}if(subcommand==="delivery"){if(!context.tenantId)throw new Error("`platform notification delivery` \u9700\u8981\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5148\u9009\u62E9\u79DF\u6237\u6216\u5E94\u7528\u3002");let items=await sdk.listNotificationDeliveries({app_id:readStringOption9(args,"app")??context.appId,status:readStringOption9(args,"status")});process5.stdout.write(`${JSON.stringify(items,null,2)}
2561
+ `)}function formatEntry(entry){return`[${entry.timestamp}] ${entry.level.toUpperCase()} ${entry.source}/${entry.stream}: ${entry.message}`}function readStringOption8(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readNumberOption3(args,key){let value=readStringOption8(args,key);if(!value)return;let parsed=Number(value);return Number.isFinite(parsed)?parsed:void 0}function sleep4(ms){return new Promise(resolve17=>{setTimeout(resolve17,ms)})}import process5 from"node:process";async function runNotificationCommand(args){let subcommand=args.rest[0];if(!subcommand||!["inbox","announce","delivery","end-user"].includes(subcommand))throw new Error("`platform notification` \u4EC5\u652F\u6301 `inbox`\u3001`announce`\u3001`delivery` \u6216 `end-user` \u5B50\u547D\u4EE4\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let context=resolveNotificationContext(args),sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId:context.tenantId,capability:"notification",requestClass:"control"});if(subcommand==="inbox"){await runInboxSubcommand(sdk,context,args);return}if(subcommand==="delivery"){if(!context.tenantId)throw new Error("`platform notification delivery` \u9700\u8981\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5148\u9009\u62E9\u79DF\u6237\u6216\u5E94\u7528\u3002");let items=await sdk.listNotificationDeliveries({app_id:readStringOption9(args,"app")??context.appId,status:readStringOption9(args,"status")});process5.stdout.write(`${JSON.stringify(items,null,2)}
2557
2562
  `);return}if(subcommand==="end-user"){await runEndUserSubcommand(sdk,context,args);return}await runAnnounceSubcommand(sdk,context,args)}async function runInboxSubcommand(sdk,context,args){let action=args.rest[1]??"list";if(action==="list"){if(!context.tenantId)throw new Error("`platform notification inbox list` \u9700\u8981\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5148\u9009\u62E9\u79DF\u6237\u6216\u5E94\u7528\u3002");let response=await sdk.listNotificationInbox({app_id:readStringOption9(args,"app")??context.appId,inbox_type:readStringOption9(args,"type"),status:readStringOption9(args,"status"),limit:readNumberOption4(args,"limit")});process5.stdout.write(`${JSON.stringify(response,null,2)}
2558
2563
  `);return}if(action==="update"){if(!context.tenantId)throw new Error("`platform notification inbox update` \u9700\u8981\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u8BF7\u5148\u9009\u62E9\u79DF\u6237\u6216\u5E94\u7528\u3002");let itemId=readStringOption9(args,"item")??args.rest[2],status=readStringOption9(args,"status");if(!itemId||!status||!isWritableInboxStatus(status))throw new Error("`platform notification inbox update` \u9700\u8981 `<item-id>` \u6216 `--item <id>`\uFF0C\u4EE5\u53CA `--status unread|read|dismissed|archived`\u3002");let item=await sdk.updateNotificationInboxItemStatus(itemId,{status});process5.stdout.write(`${JSON.stringify(item,null,2)}
2559
2564
  `);return}throw new Error("`platform notification inbox` \u76EE\u524D\u4EC5\u652F\u6301 `list` \u6216 `update`\u3002")}async function runAnnounceSubcommand(sdk,context,args){let scope=args.rest[1];if(scope==="platform"){let tenantId=readStringOption9(args,"tenant")??context.tenantId,title=readStringOption9(args,"title");if(!tenantId||!title)throw new Error("`platform notification announce platform` \u9700\u8981 `--tenant <tenant-id>` \u548C `--title <text>`\u3002");let item=await sdk.announcePlatformNotification({tenant_id:tenantId,title,body:readStringOption9(args,"body")??null,level:readStringOption9(args,"level")});process5.stdout.write(`${JSON.stringify(item,null,2)}
@@ -2570,21 +2575,21 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2570
2575
  `));let settings=await context.sdk.updateTenantAppPublishSettings(context.appId,{source_version_id:targetSourceVersionId});if(await syncLocalControlPlaneSummary({sdk:context.sdk,startDir:process.cwd(),tenantId:context.tenantId,appId:context.appId}),args.options.json===!0){process.stdout.write(`${JSON.stringify(settings,null,2)}
2571
2576
  `);return}printPublishSettings(settings,{title:`\u5E94\u7528\u6B63\u5F0F\u7248\u672C\u5DF2\u5207\u56DE: ${context.appId}`})}async function loadPublishContext(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let binding=tryReadCurrentBinding()?.binding,tenantId=readStringOption10(args,"tenant")??binding?.tenant_id,appId=readStringOption10(args,"app")??binding?.app_id;if(!tenantId||!appId)throw new Error("`platform publish` \u9700\u8981\u5DF2\u7ED1\u5B9A\u9879\u76EE\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let apiToken=selectApiToken(credentials);return{tenantId,appId,sdk:createControlApiSdk({accessToken:apiToken,tenantId,capability:"dashboard",requestClass:"control"})}}function tryReadCurrentBinding(){try{return readBinding(findAppRoot(process.cwd()))}catch{return null}}function resolvePublishSubcommand(args){let subcommand=args.rest[0];return subcommand?subcommand==="status"||subcommand==="set"||subcommand==="rollback"?subcommand:null:"status"}function hasHelpFlag5(args){return args.options.help===!0||args.options.h===!0}function readStringOption10(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readPublishStatusOption(args){let value=readStringOption10(args,"status");return value==="published"||value==="unpublished"?value:void 0}function printPublishHelp(){process.stdout.write(["platform publish","","\u7528\u6CD5\uFF1A"," platform publish"," platform publish status"," platform publish set [--source-version <srcver>] [--status published|unpublished]"," platform publish rollback <srcver>","","\u8BF4\u660E\uFF1A"," - `platform publish` \u9ED8\u8BA4\u7B49\u4EF7\u4E8E `platform publish status`"," - `publish status` \u67E5\u770B\u5E94\u7528\u6B63\u5F0F\u53D1\u5E03\u72B6\u6001\u4E0E\u5F53\u524D\u90E8\u7F72\u7248\u672C"," - `publish set` \u4FEE\u6539\u53D1\u5E03\u72B6\u6001\uFF0C\u6216\u5207\u6362\u5F53\u524D\u90E8\u7F72\u7248\u672C"," - `publish rollback` \u5C06\u5F53\u524D\u6B63\u5F0F\u7248\u672C\u5207\u56DE\u6307\u5B9A\u6E90\u7801\u7248\u672C",""].join(`
2572
2577
  `))}function printPublishSettings(settings,context){let candidateLines=settings.candidates.length>0?settings.candidates.map((candidate,index)=>{let label=candidate.message?.trim()||candidate.source_version_id;return`${index+1}. ${label} ${candidate.source_version_id}`}):["- \u65E0\u53EF\u9009\u7248\u672C"];process.stdout.write([context.title,`\u53D1\u5E03\u72B6\u6001: ${settings.publish_status==="published"?"\u5DF2\u53D1\u5E03":"\u672A\u53D1\u5E03"}`,`\u786E\u8BA4\u90E8\u7F72\u5F62\u6001: ${settings.deployment_class_confirmed??"-"}`,`\u5F53\u524D\u90E8\u7F72\u7248\u672C: ${settings.current_source_version_id??"-"}`,`\u5F53\u524D release: ${settings.current_release_id??"-"}`,`\u5F53\u524D deployment: ${settings.current_deployment_id??"-"}`,`\u5F53\u524D\u90E8\u7F72\u5F62\u6001: ${settings.current_deployment_class_used??"-"}`,`\u5F53\u524D\u4EA7\u7269\u7C7B\u578B: ${settings.current_artifact_kind??"-"}`,`\u5F53\u524D\u6267\u884C\u6A21\u5F0F: ${settings.current_execution_mode??"-"}`,`\u8FD0\u884C\u9A71\u52A8: ${settings.current_runtime_driver??"-"}`,`\u8FD0\u884C\u5B9E\u4F8B: ${settings.current_runtime_instance_id??"-"}`,`\u5F53\u524D\u5BF9\u8C61\u524D\u7F00: ${settings.current_object_prefix??"-"}`,`\u516C\u5F00\u6B63\u5F0F\u5165\u53E3: ${settings.public_prod_url??"-"}`,`\u8FD0\u884C\u5065\u5EB7\u68C0\u67E5: ${settings.current_runtime_health_check_url??"-"}`,"\u53EF\u9009\u6B63\u5F0F\u7248\u672C:",...candidateLines,""].join(`
2573
- `))}import{createHash as createHash10}from"node:crypto";import{readFile,stat}from"node:fs/promises";import{join as join19,resolve as resolve15}from"node:path";import{spawn as spawn6}from"node:child_process";function resolvePreviewProjectContext(appRoot,args){let sourceContext=readSourceContext(appRoot)?.sourceContext,binding=readBinding(appRoot)?.binding;return{tenantId:readStringOption11(args,"tenant")??sourceContext?.tenant_id??binding?.tenant_id,appId:readStringOption11(args,"app")??sourceContext?.app_id??binding?.app_id}}var SOURCE_VERSION_REUSE_SCAN_LIMIT=5,BUILD_REUSE_SCAN_LIMIT=20,PREVIEW_BUILD_POLL_TIMEOUT_MS=180*1e3,PREVIEW_BUILD_POLL_INTERVAL_MS=1500;async function runPreviewCommand(args){if(hasHelpFlag6(args)){printPreviewHelp(resolveExplicitPreviewMode(args));return}if(resolvePreviewMode(args)==="open"){await runPreviewOpenCommand(args);return}await runPreviewGenerateCommand(args)}async function runPreviewGenerateCommand(args){let context=await loadPreviewContext(args),requestedBy=await resolveRequestedBy3(context.sdk),fromBuildId=readStringOption11(args,"from-build"),explicitSourceVersionId=readStringOption11(args,"source-version"),noWait=args.options["no-wait"]===!0,forceBuild=args.options["force-build"]===!0,localBuild=args.options["local-build"]===!0||readStringOption11(args,"build-mode")==="local";if(args.options["wait-build-only"]===!0)throw new Error("`platform preview generate --wait-build-only` \u5DF2\u79FB\u9664\uFF1B\u8BF7\u6539\u7528 `platform build run --source-version <srcver> --wait`\u3002");let autoResources=await maybeAutoApplyPreviewResources({args,context,requestedBy,sourceVersionId:explicitSourceVersionId,fromBuildId});if(fromBuildId){let preview=await context.sdk.createTenantAppPreview(context.appId,{build_id:fromBuildId}).catch(async error=>{throw await formatPreviewCommandError(context.sdk,error,{appId:context.appId,buildId:fromBuildId,stage:"preview"})});if(isPreviewBuildPendingResponse(preview))throw new Error(`preview unexpectedly returned build pending for explicit build: ${fromBuildId}`);if(updateSourceContext(context.appRoot,{tenant_id:context.tenantId,app_id:context.appId,env:"preview",last_preview_source_version_id:preview.source_version_id,last_preview_build_id:fromBuildId,last_preview_generated_at:new Date().toISOString()}),await syncLocalControlPlaneSummary({sdk:context.sdk,startDir:context.appRoot,tenantId:context.tenantId,appId:context.appId}),args.options.json===!0){let postCheck3=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,preview);process.stdout.write(`${JSON.stringify({auto_resources:autoResources,preview,post_check:postCheck3},null,2)}
2578
+ `))}import{createHash as createHash10}from"node:crypto";import{readFile as readFile2,stat}from"node:fs/promises";import{join as join19,resolve as resolve16}from"node:path";function resolvePreviewProjectContext(appRoot,args){let sourceContext=readSourceContext(appRoot)?.sourceContext,binding=readBinding(appRoot)?.binding;return{tenantId:readStringOption11(args,"tenant")??sourceContext?.tenant_id??binding?.tenant_id,appId:readStringOption11(args,"app")??sourceContext?.app_id??binding?.app_id}}var SOURCE_VERSION_REUSE_SCAN_LIMIT=5,BUILD_REUSE_SCAN_LIMIT=20,PREVIEW_BUILD_POLL_TIMEOUT_MS=180*1e3,PREVIEW_BUILD_POLL_INTERVAL_MS=1500;async function runPreviewCommand(args){if(hasHelpFlag6(args)){printPreviewHelp(resolveExplicitPreviewMode(args));return}if(resolvePreviewMode(args)==="open"){await runPreviewOpenCommand(args);return}await runPreviewGenerateCommand(args)}async function runPreviewGenerateCommand(args){let context=await loadPreviewContext(args),requestedBy=await resolveRequestedBy3(context.sdk),fromBuildId=readStringOption11(args,"from-build"),explicitSourceVersionId=readStringOption11(args,"source-version"),noWait=args.options["no-wait"]===!0,forceBuild=args.options["force-build"]===!0,localBuild=args.options["local-build"]===!0||readStringOption11(args,"build-mode")==="local";if(args.options["wait-build-only"]===!0)throw new Error("`platform preview generate --wait-build-only` \u5DF2\u79FB\u9664\uFF1B\u8BF7\u6539\u7528 `platform build run --source-version <srcver> --wait`\u3002");let autoResources=await maybeAutoApplyPreviewResources({args,context,requestedBy,sourceVersionId:explicitSourceVersionId,fromBuildId});if(fromBuildId){let preview=await context.sdk.createTenantAppPreview(context.appId,{build_id:fromBuildId}).catch(async error=>{throw await formatPreviewCommandError(context.sdk,error,{appId:context.appId,buildId:fromBuildId,stage:"preview"})});if(isPreviewBuildPendingResponse(preview))throw new Error(`preview unexpectedly returned build pending for explicit build: ${fromBuildId}`);if(updateSourceContext(context.appRoot,{tenant_id:context.tenantId,app_id:context.appId,env:"preview",last_preview_source_version_id:preview.source_version_id,last_preview_build_id:fromBuildId,last_preview_generated_at:new Date().toISOString()}),await syncLocalControlPlaneSummary({sdk:context.sdk,startDir:context.appRoot,tenantId:context.tenantId,appId:context.appId}),args.options.json===!0){let postCheck3=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,preview);process.stdout.write(`${JSON.stringify({auto_resources:autoResources,preview,post_check:postCheck3},null,2)}
2574
2579
  `);return}let postCheck2=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,preview);printPreviewDeployResult(preview,{buildId:fromBuildId,fromBuildId,postCheck:postCheck2});return}let buildConfig=readBuildConfig2(args.options),sourceVersionId=explicitSourceVersionId,createdSourceVersionId,reusedSourceVersionId,localWorkspaceFiles=[];if((!sourceVersionId||localBuild)&&(assertSourceWorkspaceCloudUploadPolicy(context.appRoot,localBuild?"--local-build":"platform preview generate"),localWorkspaceFiles=collectSourceWorkspaceFiles(context.appRoot).files),!sourceVersionId){let sourceVersionResolution=await resolvePreviewSourceVersion({sdk:context.sdk,appId:context.appId,appRoot:context.appRoot,localFiles:localWorkspaceFiles,message:readStringOption11(args,"message")??"preview from local workspace"});sourceVersionId=sourceVersionResolution.sourceVersionId,createdSourceVersionId=sourceVersionResolution.createdSourceVersionId,reusedSourceVersionId=sourceVersionResolution.reusedSourceVersionId}if(localBuild){await runLocalBuildPreviewFlow({args,context,requestedBy,sourceVersionId,localWorkspace:localWorkspaceFiles,autoResources,createdSourceVersionId,reusedSourceVersionId,requestedSourceVersionId:explicitSourceVersionId,buildConfig});return}let previewOutcome=await requestPreviewFromSourceVersion({sdk:context.sdk,appId:context.appId,appRoot:context.appRoot,sourceVersionId,buildConfig,forceBuild});if(previewOutcome.kind==="build_started"){if(!noWait){let continued=await continuePreviewAfterBuild({sdk:context.sdk,appId:context.appId,build:previewOutcome.build});if(updateSourceContext(context.appRoot,{tenant_id:context.tenantId,app_id:context.appId,env:"preview",last_preview_source_version_id:continued.preview.source_version_id,last_preview_build_id:continued.build.id,last_preview_generated_at:new Date().toISOString()}),await syncLocalControlPlaneSummary({sdk:context.sdk,startDir:context.appRoot,tenantId:context.tenantId,appId:context.appId}),args.options.json===!0){let postCheck3=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,continued.preview);process.stdout.write(`${JSON.stringify({stage:"preview_completed",auto_resources:autoResources,build:continued.build,preview:continued.preview,post_check:postCheck3,...reusedSourceVersionId?{reused_source_version_id:reusedSourceVersionId}:{},...createdSourceVersionId?{created_source_version_id:createdSourceVersionId}:{}},null,2)}
2575
2580
  `);return}let postCheck2=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,continued.preview);printPreviewDeployResult(continued.preview,{buildId:continued.build.id,createdSourceVersionId,reusedSourceVersionId,requestedSourceVersionId:explicitSourceVersionId,postCheck:postCheck2});return}if(args.options.json===!0){process.stdout.write(`${JSON.stringify({stage:"build_started",auto_resources:autoResources,build:previewOutcome.build,...reusedSourceVersionId?{reused_source_version_id:reusedSourceVersionId}:{},...createdSourceVersionId?{created_source_version_id:createdSourceVersionId}:{}},null,2)}
2576
2581
  `);return}printPreviewBuildStarted(previewOutcome.build,{createdSourceVersionId,reusedSourceVersionId,requestedSourceVersionId:explicitSourceVersionId});return}if(updateSourceContext(context.appRoot,{tenant_id:context.tenantId,app_id:context.appId,env:"preview",last_preview_source_version_id:previewOutcome.build.source_version_id,last_preview_build_id:previewOutcome.build.id,last_preview_generated_at:new Date().toISOString()}),await syncLocalControlPlaneSummary({sdk:context.sdk,startDir:context.appRoot,tenantId:context.tenantId,appId:context.appId}),args.options.json===!0){let postCheck2=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,previewOutcome.preview);process.stdout.write(`${JSON.stringify({stage:"preview_completed",auto_resources:autoResources,build:previewOutcome.build,preview:previewOutcome.preview,post_check:postCheck2,...reusedSourceVersionId?{reused_source_version_id:reusedSourceVersionId}:{},...createdSourceVersionId?{created_source_version_id:createdSourceVersionId}:{}},null,2)}
2577
2582
  `);return}let postCheck=await buildPreviewSuccessPostCheckPayload(context.sdk,context.appId,previewOutcome.preview);printPreviewDeployResult(previewOutcome.preview,{buildId:previewOutcome.build.id,createdSourceVersionId,reusedSourceVersionId,requestedSourceVersionId:explicitSourceVersionId,postCheck})}async function resolvePreviewSourceVersion(args){let matchedSourceVersionId=await findMatchingLocalSourceVersion(args);if(matchedSourceVersionId)return{sourceVersionId:matchedSourceVersionId,reusedSourceVersionId:matchedSourceVersionId};let submitted=await args.sdk.createTenantAppSourceVersion(args.appId,{files:args.localFiles,message:args.message}).catch(async error=>{throw await formatPreviewCommandError(args.sdk,error,{appId:args.appId,stage:"submit"})});return updateSourceContext(args.appRoot,{tenant_id:submitted.tenant_id,app_id:submitted.app_id,env:"preview",template_key:submitted.template_key,last_submitted_source_version_id:submitted.source_version_id,last_submitted_at:submitted.created_at}),{sourceVersionId:submitted.source_version_id,createdSourceVersionId:submitted.source_version_id}}async function findMatchingLocalSourceVersion(args){let sourceContext=readSourceContext(args.appRoot)?.sourceContext,candidateIds=collectReusableSourceVersionCandidates(sourceContext);for(let sourceVersionId of candidateIds)if(await sourceVersionMatchesLocalWorkspace(args.sdk,args.appId,sourceVersionId,args.localFiles))return sourceVersionId;let listedVersions=await args.sdk.listTenantAppSourceVersions(args.appId).then(response=>response.items.slice(0,SOURCE_VERSION_REUSE_SCAN_LIMIT).map(item=>item.source_version_id)).catch(()=>[]);for(let sourceVersionId of listedVersions)if(!candidateIds.includes(sourceVersionId)&&await sourceVersionMatchesLocalWorkspace(args.sdk,args.appId,sourceVersionId,args.localFiles))return sourceVersionId;return null}async function sourceVersionMatchesLocalWorkspace(sdk,appId,sourceVersionId,localFiles){let workspace=await sdk.getTenantAppSourceWorkspace(appId,{sourceVersionId}).catch(()=>null);return workspace?.source_version_id?sourceWorkspaceFilesEqual(localFiles,workspace.files):!1}async function findReusableSuccessfulBuild(args){let lastPreviewBuildId=readSourceContext(args.appRoot)?.sourceContext?.last_preview_build_id;if(lastPreviewBuildId){let lastPreviewBuild=await args.sdk.getBuild(lastPreviewBuildId).catch(()=>null);if(isReusableSuccessfulBuild(lastPreviewBuild,args.sourceVersionId,args.buildConfig))return lastPreviewBuild}return(await args.sdk.listBuilds(args.appId,{limit:BUILD_REUSE_SCAN_LIMIT}).then(response=>response.items).catch(()=>[])).find(build=>isReusableSuccessfulBuild(build,args.sourceVersionId,args.buildConfig))??null}async function runLocalBuildPreviewFlow(args){assertLocalBuildArgsAllowed(args.args,args.buildConfig),await assertExplicitSourceVersionMatchesWorkspace(args);let localPrecheck=await runLocalBuildSourcePrecheck(args.context.appRoot);if((readAppManifest(args.context.appRoot).manifest.template_key?.trim()||readSourceContext(args.context.appRoot)?.sourceContext.template_key?.trim())!=="frontend-app-vite")throw new Error("`platform preview generate --local-build` \u9996\u7248\u4EC5\u652F\u6301 `frontend-app-vite`\u3002");let buildPrecheck=await args.context.sdk.getBuildPrecheck(args.context.appId,{source_version_id:args.sourceVersionId,build_config:{target:"static"}});if(buildPrecheck.result==="unsupported")throw new Error(["\u5F53\u524D\u6E90\u7801\u7248\u672C\u672A\u901A\u8FC7\u5E73\u53F0\u9759\u6001\u6784\u5EFA\u9884\u68C0\uFF0C\u4E0D\u80FD\u6267\u884C `--local-build`\u3002",...buildPrecheck.issues.map(issue=>`${issue.severity}: ${issue.code} ${issue.message}`)].join(`
2578
2583
  `));let session=await args.context.sdk.createLocalBuildSession({tenant_id:args.context.tenantId,app_id:args.context.appId,source_version_id:args.sourceVersionId,requested_by:args.requestedBy,build_config:{target:"static"}}),archive=await buildLocalStaticBundleArchive(args.context.appRoot);await args.context.sdk.uploadTenantBlobBinary(session.upload.upload_session_id,{content:archive.content,content_type:"application/zip",upload_url:session.upload.upload_url,headers:session.upload.headers});let build=await args.context.sdk.completeLocalBuildSession(session.build.id,{upload_session_id:session.upload.upload_session_id,sha256:archive.sha256Hex,size_bytes:archive.content.byteLength}).catch(async error=>{throw await formatPreviewCommandError(args.context.sdk,error,{appId:args.context.appId,buildId:session.build.id,stage:"build"})}),preview=await args.context.sdk.createTenantAppPreview(args.context.appId,{build_id:build.id}).catch(async error=>{throw await formatPreviewCommandError(args.context.sdk,error,{appId:args.context.appId,buildId:build.id,stage:"preview"})});if(isPreviewBuildPendingResponse(preview))throw new Error(`preview unexpectedly returned build pending for completed local build: ${build.id}`);if(updateSourceContext(args.context.appRoot,{tenant_id:args.context.tenantId,app_id:args.context.appId,env:"preview",last_preview_source_version_id:preview.source_version_id,last_preview_build_id:build.id,last_preview_generated_at:new Date().toISOString()}),await syncLocalControlPlaneSummary({sdk:args.context.sdk,startDir:args.context.appRoot,tenantId:args.context.tenantId,appId:args.context.appId}),args.args.options.json===!0){let postCheck2=await buildPreviewSuccessPostCheckPayload(args.context.sdk,args.context.appId,preview);process.stdout.write(`${JSON.stringify({stage:"preview_completed",mode:"local_build",auto_resources:args.autoResources,local_precheck:localPrecheck,build,preview,post_check:postCheck2,...args.reusedSourceVersionId?{reused_source_version_id:args.reusedSourceVersionId}:{},...args.createdSourceVersionId?{created_source_version_id:args.createdSourceVersionId}:{}},null,2)}
2579
- `);return}let postCheck=await buildPreviewSuccessPostCheckPayload(args.context.sdk,args.context.appId,preview);printPreviewDeployResult(preview,{buildId:build.id,createdSourceVersionId:args.createdSourceVersionId,reusedSourceVersionId:args.reusedSourceVersionId,requestedSourceVersionId:args.requestedSourceVersionId,postCheck})}function assertLocalBuildArgsAllowed(args,buildConfig){if(readStringOption11(args,"from-build"))throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--from-build`\u3002");if(args.options["force-build"]===!0)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--force-build`\uFF1B\u672C\u5730\u6A21\u5F0F\u9ED8\u8BA4\u6BCF\u6B21\u90FD\u91CD\u65B0\u6784\u5EFA\u3002");if(args.options["no-wait"]===!0)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--no-wait`\u3002");if(buildConfig.dockerfile_path||buildConfig.context_subdir)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--dockerfile` \u6216 `--context-subdir`\u3002");if(buildConfig.target&&buildConfig.target!=="static")throw new Error("`platform preview generate --local-build` \u4EC5\u652F\u6301\u9759\u6001\u76EE\u6807\u3002")}async function assertExplicitSourceVersionMatchesWorkspace(args){if(!args.requestedSourceVersionId)return;let workspace=await args.context.sdk.getTenantAppSourceWorkspace(args.context.appId,{sourceVersionId:args.sourceVersionId});if(!sourceWorkspaceFilesEqual(args.localWorkspace,workspace.files))throw new Error("\u663E\u5F0F `--source-version` \u4E0E\u5F53\u524D\u672C\u5730\u5DE5\u4F5C\u533A\u4E0D\u4E00\u81F4\uFF0C\u4E0D\u80FD\u6267\u884C `--local-build`\u3002")}async function runLocalBuildSourcePrecheck(appRoot){let stats=assertSourceWorkspaceCloudUploadPolicy(appRoot,"--local-build");return{source_bytes:stats.sourceBytes,asset_hits:stats.assetHits}}async function buildLocalStaticBundleArchive(appRoot){await runLocalBuildCommand(appRoot);let outputDir=resolve15(appRoot,"dist");if(!await pathExists(join19(outputDir,"index.html")))throw new Error("\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/index.html`\uFF0C\u4E0D\u80FD\u6267\u884C\u4E0A\u4F20\u3002");await validateOptionalLocalBuiltPageRenderBundle(appRoot,outputDir);let zipped=await createZipArchiveBuffer(outputDir),sha256Hex=createHash10("sha256").update(zipped).digest("hex");return{content:zipped,sha256Hex}}async function validateOptionalLocalBuiltPageRenderBundle(appRoot,outputDir){let sourceRegistryPath=join19(appRoot,"page-render","registry.json");if(!await pathExists(sourceRegistryPath))return;let distRegistryPath=join19(outputDir,"page-render","registry.json"),distAssetsManifestPath=join19(outputDir,"page-render","assets-manifest.json");if(!await pathExists(distRegistryPath))throw new Error("\u68C0\u6D4B\u5230 `page-render/registry.json`\uFF0C\u4F46\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/page-render/registry.json`\u3002\u8BF7\u786E\u8BA4 build \u540E\u5904\u7406\u811A\u672C\u5DF2\u6267\u884C\u3002");if(!await pathExists(distAssetsManifestPath))throw new Error("\u68C0\u6D4B\u5230 `page-render/registry.json`\uFF0C\u4F46\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/page-render/assets-manifest.json`\u3002\u8BF7\u786E\u8BA4 build \u540E\u5904\u7406\u811A\u672C\u5DF2\u6267\u884C\u3002");await parseJsonFileOrThrow(distRegistryPath,"dist/page-render/registry.json"),await parseJsonFileOrThrow(distAssetsManifestPath,"dist/page-render/assets-manifest.json")}async function runLocalBuildCommand(appRoot){let packageJson=JSON.parse(await readFile(join19(appRoot,"package.json"),"utf8")),hasPnpmLock=await pathExists(join19(appRoot,"pnpm-lock.yaml")),hasYarnLock=await pathExists(join19(appRoot,"yarn.lock")),packageManager=typeof packageJson.packageManager=="string"?packageJson.packageManager:"",command=packageManager.startsWith("pnpm@")||hasPnpmLock?["corepack","pnpm","run","build"]:packageManager.startsWith("yarn@")||hasYarnLock?["corepack","yarn","run","build"]:["npm","run","build"];await runSubprocess(command[0],command.slice(1),appRoot)}async function runSubprocess(command,commandArgs,cwd){await new Promise((resolvePromise,rejectPromise)=>{let child=spawn6(command,commandArgs,{cwd,stdio:"inherit",env:{...process.env,NODE_ENV:"development",NPM_CONFIG_PRODUCTION:"false",npm_config_production:"false"}});child.on("error",rejectPromise),child.on("exit",code2=>{if(code2===0){resolvePromise();return}rejectPromise(new Error(`\u672C\u5730\u6784\u5EFA\u5931\u8D25: ${command} ${commandArgs.join(" ")} (exit ${code2??"unknown"})`))})})}async function createZipArchiveBuffer(targetDir){return new Promise((resolvePromise,rejectPromise)=>{let child=spawn6("zip",["-qr","-","."],{cwd:targetDir,stdio:["ignore","pipe","pipe"]}),chunks=[],errors=[];child.stdout.on("data",chunk=>chunks.push(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk))),child.stderr.on("data",chunk=>errors.push(Buffer.isBuffer(chunk)?chunk:Buffer.from(chunk))),child.on("error",rejectPromise),child.on("exit",code2=>{if(code2===0){resolvePromise(new Uint8Array(Buffer.concat(chunks)));return}rejectPromise(new Error(`\u9759\u6001\u4EA7\u7269\u6253\u5305\u5931\u8D25: zip -qr - . (exit ${code2??"unknown"}) ${Buffer.concat(errors).toString("utf8")}`))})})}async function pathExists(targetPath){try{return await stat(targetPath),!0}catch{return!1}}async function parseJsonFileOrThrow(filePath,label){let raw=await readFile(filePath,"utf8");try{return JSON.parse(raw)}catch(error){throw new Error(`${label} \u4E0D\u662F\u5408\u6CD5 JSON: ${error instanceof Error?error.message:String(error)}`)}}async function requestPreviewFromSourceVersion(args){try{let preview=await args.sdk.createTenantAppPreview(args.appId,{source_version_id:args.sourceVersionId,...Object.keys(args.buildConfig).length>0?{build_config:args.buildConfig}:{},...args.forceBuild?{force_rebuild:!0}:{}});return isPreviewBuildPendingResponse(preview)?{kind:"build_started",build:await args.sdk.getBuild(preview.build_id).catch(async buildError=>{throw await formatPreviewCommandError(args.sdk,buildError,{appId:args.appId,buildId:preview.build_id,stage:"build"})})}:{kind:"preview_completed",build:preview.build_id?await args.sdk.getBuild(preview.build_id):await loadPreviewBuildBySourceVersion(args),preview}}catch(error){throw await formatPreviewCommandError(args.sdk,error,{appId:args.appId,sourceVersionId:args.sourceVersionId,stage:"preview"})}}async function continuePreviewAfterBuild(args){let completedBuild=await waitForPreviewBuild(args.sdk,args.build.id);if(completedBuild.status==="cancelled"){let reusedBuildId=extractReusedBuildId2(completedBuild);if(reusedBuildId){let reusedBuild=await args.sdk.getBuild(reusedBuildId).catch(async buildError=>{throw await formatPreviewCommandError(args.sdk,buildError,{appId:args.appId,buildId:reusedBuildId,stage:"build"})});return createPreviewFromBuild({sdk:args.sdk,appId:args.appId,build:reusedBuild})}}return createPreviewFromBuild({sdk:args.sdk,appId:args.appId,build:completedBuild})}async function createPreviewFromBuild(args){if(args.build.status!=="succeeded")throw formatPreviewBuildNotReadyError(args.build);let preview=await args.sdk.createTenantAppPreview(args.appId,{build_id:args.build.id}).catch(async error=>{throw await formatPreviewCommandError(args.sdk,error,{appId:args.appId,buildId:args.build.id,stage:"preview"})});if(isPreviewBuildPendingResponse(preview))throw new Error(`preview unexpectedly returned build pending for completed build: ${args.build.id}`);return{build:args.build,preview}}async function waitForPreviewBuild(sdk,buildId,options){let timeoutMs=options?.timeoutMs??PREVIEW_BUILD_POLL_TIMEOUT_MS,intervalMs=options?.intervalMs??PREVIEW_BUILD_POLL_INTERVAL_MS,startedAt=Date.now();for(;;){let build=await sdk.getBuild(buildId);if(isTerminalBuildStatus2(build.status))return build;if(Date.now()-startedAt>=timeoutMs)throw formatPreviewBuildTimeoutError(build,timeoutMs);await sleep5(intervalMs)}}function isTerminalBuildStatus2(status){return status==="succeeded"||status==="failed"||status==="cancelled"}function extractReusedBuildId2(result){return result.error_code!=="build_reused_existing_success"||!result.error_message?null:result.error_message.match(/reused successful build\s+([a-zA-Z0-9-]+)/)?.[1]??null}function formatPreviewBuildNotReadyError(build){let lines=["Preview \u672A\u7EE7\u7EED\u53D1\u5E03\uFF0C\u56E0\u4E3A build \u672A\u6210\u529F\u5B8C\u6210\u3002",`build: ${build.id}`,`status: ${build.status}`,...build.error_code?[`error_code: ${build.error_code}`]:[],...build.error_message?[`error_message: ${build.error_message}`]:[],...build.log_ref?[`log_ref: ${build.log_ref}`]:[],`\u4E0B\u4E00\u6B65: \u6267\u884C \`platform build get ${build.id}\` \u6216 \`platform build events ${build.id}\` \u7EE7\u7EED\u6392\u67E5\u3002`];return new Error(lines.join(`
2584
+ `);return}let postCheck=await buildPreviewSuccessPostCheckPayload(args.context.sdk,args.context.appId,preview);printPreviewDeployResult(preview,{buildId:build.id,createdSourceVersionId:args.createdSourceVersionId,reusedSourceVersionId:args.reusedSourceVersionId,requestedSourceVersionId:args.requestedSourceVersionId,postCheck})}function assertLocalBuildArgsAllowed(args,buildConfig){if(readStringOption11(args,"from-build"))throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--from-build`\u3002");if(args.options["force-build"]===!0)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--force-build`\uFF1B\u672C\u5730\u6A21\u5F0F\u9ED8\u8BA4\u6BCF\u6B21\u90FD\u91CD\u65B0\u6784\u5EFA\u3002");if(args.options["no-wait"]===!0)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--no-wait`\u3002");if(buildConfig.dockerfile_path||buildConfig.context_subdir)throw new Error("`platform preview generate --local-build` \u4E0D\u652F\u6301 `--dockerfile` \u6216 `--context-subdir`\u3002");if(buildConfig.target&&buildConfig.target!=="static")throw new Error("`platform preview generate --local-build` \u4EC5\u652F\u6301\u9759\u6001\u76EE\u6807\u3002")}async function assertExplicitSourceVersionMatchesWorkspace(args){if(!args.requestedSourceVersionId)return;let workspace=await args.context.sdk.getTenantAppSourceWorkspace(args.context.appId,{sourceVersionId:args.sourceVersionId});if(!sourceWorkspaceFilesEqual(args.localWorkspace,workspace.files))throw new Error("\u663E\u5F0F `--source-version` \u4E0E\u5F53\u524D\u672C\u5730\u5DE5\u4F5C\u533A\u4E0D\u4E00\u81F4\uFF0C\u4E0D\u80FD\u6267\u884C `--local-build`\u3002")}async function runLocalBuildSourcePrecheck(appRoot){let stats=assertSourceWorkspaceCloudUploadPolicy(appRoot,"--local-build");return{source_bytes:stats.sourceBytes,asset_hits:stats.assetHits}}async function buildLocalStaticBundleArchive(appRoot){await runLocalBuildCommand(appRoot);let outputDir=resolve16(appRoot,"dist");if(!await pathExists(join19(outputDir,"index.html")))throw new Error("\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/index.html`\uFF0C\u4E0D\u80FD\u6267\u884C\u4E0A\u4F20\u3002");await validateOptionalLocalBuiltPageRenderBundle(appRoot,outputDir);let zipped=await createZipArchiveBuffer(outputDir),sha256Hex=createHash10("sha256").update(zipped).digest("hex");return{content:zipped,sha256Hex}}async function validateOptionalLocalBuiltPageRenderBundle(appRoot,outputDir){let sourceRegistryPath=join19(appRoot,"page-render","registry.json");if(!await pathExists(sourceRegistryPath))return;let distRegistryPath=join19(outputDir,"page-render","registry.json"),distAssetsManifestPath=join19(outputDir,"page-render","assets-manifest.json");if(!await pathExists(distRegistryPath))throw new Error("\u68C0\u6D4B\u5230 `page-render/registry.json`\uFF0C\u4F46\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/page-render/registry.json`\u3002\u8BF7\u786E\u8BA4 build \u540E\u5904\u7406\u811A\u672C\u5DF2\u6267\u884C\u3002");if(!await pathExists(distAssetsManifestPath))throw new Error("\u68C0\u6D4B\u5230 `page-render/registry.json`\uFF0C\u4F46\u672C\u5730\u6784\u5EFA\u4EA7\u7269\u7F3A\u5C11 `dist/page-render/assets-manifest.json`\u3002\u8BF7\u786E\u8BA4 build \u540E\u5904\u7406\u811A\u672C\u5DF2\u6267\u884C\u3002");await parseJsonFileOrThrow(distRegistryPath,"dist/page-render/registry.json"),await parseJsonFileOrThrow(distAssetsManifestPath,"dist/page-render/assets-manifest.json")}async function runLocalBuildCommand(appRoot){let packageJson=JSON.parse(await readFile2(join19(appRoot,"package.json"),"utf8")),hasPnpmLock=await pathExists(join19(appRoot,"pnpm-lock.yaml")),hasYarnLock=await pathExists(join19(appRoot,"yarn.lock")),packageManager=typeof packageJson.packageManager=="string"?packageJson.packageManager:"",command=packageManager.startsWith("pnpm@")||hasPnpmLock?["corepack","pnpm","run","build"]:packageManager.startsWith("yarn@")||hasYarnLock?["corepack","yarn","run","build"]:["npm","run","build"];await runSubprocess(command[0],command.slice(1),appRoot)}async function runSubprocess(command,commandArgs,cwd){await new Promise((resolvePromise,rejectPromise)=>{if(command!=="corepack"&&command!=="npm"){rejectPromise(new Error(`\u4E0D\u652F\u6301\u7684\u672C\u5730\u6784\u5EFA\u547D\u4EE4: ${command}`));return}let child=spawnCrossPlatform(command,commandArgs,{cwd,stdio:"inherit",env:{...process.env,NODE_ENV:"development",NPM_CONFIG_PRODUCTION:"false",npm_config_production:"false"}});child.on("error",rejectPromise),child.on("exit",code2=>{if(code2===0){resolvePromise();return}rejectPromise(new Error(`\u672C\u5730\u6784\u5EFA\u5931\u8D25: ${command} ${commandArgs.join(" ")} (exit ${code2??"unknown"})`))})})}async function createZipArchiveBuffer(targetDir){return createZipBuffer(targetDir)}async function pathExists(targetPath){try{return await stat(targetPath),!0}catch{return!1}}async function parseJsonFileOrThrow(filePath,label){let raw=await readFile2(filePath,"utf8");try{return JSON.parse(raw)}catch(error){throw new Error(`${label} \u4E0D\u662F\u5408\u6CD5 JSON: ${error instanceof Error?error.message:String(error)}`)}}async function requestPreviewFromSourceVersion(args){try{let preview=await args.sdk.createTenantAppPreview(args.appId,{source_version_id:args.sourceVersionId,...Object.keys(args.buildConfig).length>0?{build_config:args.buildConfig}:{},...args.forceBuild?{force_rebuild:!0}:{}});return isPreviewBuildPendingResponse(preview)?{kind:"build_started",build:await args.sdk.getBuild(preview.build_id).catch(async buildError=>{throw await formatPreviewCommandError(args.sdk,buildError,{appId:args.appId,buildId:preview.build_id,stage:"build"})})}:{kind:"preview_completed",build:preview.build_id?await args.sdk.getBuild(preview.build_id):await loadPreviewBuildBySourceVersion(args),preview}}catch(error){throw await formatPreviewCommandError(args.sdk,error,{appId:args.appId,sourceVersionId:args.sourceVersionId,stage:"preview"})}}async function continuePreviewAfterBuild(args){let completedBuild=await waitForPreviewBuild(args.sdk,args.build.id);if(completedBuild.status==="cancelled"){let reusedBuildId=extractReusedBuildId2(completedBuild);if(reusedBuildId){let reusedBuild=await args.sdk.getBuild(reusedBuildId).catch(async buildError=>{throw await formatPreviewCommandError(args.sdk,buildError,{appId:args.appId,buildId:reusedBuildId,stage:"build"})});return createPreviewFromBuild({sdk:args.sdk,appId:args.appId,build:reusedBuild})}}return createPreviewFromBuild({sdk:args.sdk,appId:args.appId,build:completedBuild})}async function createPreviewFromBuild(args){if(args.build.status!=="succeeded")throw formatPreviewBuildNotReadyError(args.build);let preview=await args.sdk.createTenantAppPreview(args.appId,{build_id:args.build.id}).catch(async error=>{throw await formatPreviewCommandError(args.sdk,error,{appId:args.appId,buildId:args.build.id,stage:"preview"})});if(isPreviewBuildPendingResponse(preview))throw new Error(`preview unexpectedly returned build pending for completed build: ${args.build.id}`);return{build:args.build,preview}}async function waitForPreviewBuild(sdk,buildId,options){let timeoutMs=options?.timeoutMs??PREVIEW_BUILD_POLL_TIMEOUT_MS,intervalMs=options?.intervalMs??PREVIEW_BUILD_POLL_INTERVAL_MS,startedAt=Date.now();for(;;){let build=await sdk.getBuild(buildId);if(isTerminalBuildStatus2(build.status))return build;if(Date.now()-startedAt>=timeoutMs)throw formatPreviewBuildTimeoutError(build,timeoutMs);await sleep5(intervalMs)}}function isTerminalBuildStatus2(status){return status==="succeeded"||status==="failed"||status==="cancelled"}function extractReusedBuildId2(result){return result.error_code!=="build_reused_existing_success"||!result.error_message?null:result.error_message.match(/reused successful build\s+([a-zA-Z0-9-]+)/)?.[1]??null}function formatPreviewBuildNotReadyError(build){let lines=["Preview \u672A\u7EE7\u7EED\u53D1\u5E03\uFF0C\u56E0\u4E3A build \u672A\u6210\u529F\u5B8C\u6210\u3002",`build: ${build.id}`,`status: ${build.status}`,...build.error_code?[`error_code: ${build.error_code}`]:[],...build.error_message?[`error_message: ${build.error_message}`]:[],...build.log_ref?[`log_ref: ${build.log_ref}`]:[],`\u4E0B\u4E00\u6B65: \u6267\u884C \`platform build get ${build.id}\` \u6216 \`platform build events ${build.id}\` \u7EE7\u7EED\u6392\u67E5\u3002`];return new Error(lines.join(`
2580
2585
  `))}function formatPreviewBuildTimeoutError(build,timeoutMs){return new Error(["Preview \u7B49\u5F85 build \u8D85\u65F6\uFF0C\u5C1A\u672A\u81EA\u52A8\u7EE7\u7EED\u53D1\u5E03\u3002",`build: ${build.id}`,`status: ${build.status}`,`timeout_ms: ${timeoutMs}`,`\u4E0B\u4E00\u6B65: \u6267\u884C \`platform build get ${build.id}\` \u89C2\u5BDF\u72B6\u6001\uFF1B\u5982\u5DF2\u6210\u529F\uFF0C\u53EF\u6267\u884C \`platform preview generate --from-build ${build.id}\`\u3002`].join(`
2581
- `))}function sleep5(ms){return new Promise(resolve16=>{setTimeout(resolve16,ms)})}async function loadPreviewBuildBySourceVersion(args){let build=await findReusableSuccessfulBuild({sdk:args.sdk,appId:args.appId,appRoot:args.appRoot,sourceVersionId:args.sourceVersionId,buildConfig:args.buildConfig});if(!build)throw new Error(`preview \u5DF2\u521B\u5EFA\uFF0C\u4F46\u672A\u80FD\u5B9A\u4F4D\u5BF9\u5E94 build: ${args.appId}/${args.sourceVersionId}`);return build}function collectReusableSourceVersionCandidates(sourceContext){return Array.from(new Set([sourceContext?.last_preview_source_version_id,sourceContext?.last_submitted_source_version_id,sourceContext?.base_source_version_id].filter(value=>typeof value=="string"&&value.length>0)))}function sourceWorkspaceFilesEqual(localFiles,remoteFiles){if(localFiles.length!==remoteFiles.length)return!1;for(let index=0;index<localFiles.length;index+=1){let local=localFiles[index],remote=remoteFiles[index];if(!remote||local.path!==remote.path||local.content!==remote.content)return!1}return!0}function isReusableSuccessfulBuild(build,sourceVersionId,buildConfig){return!build||build.status!=="succeeded"||build.lifecycle_status&&build.lifecycle_status!=="active"||build.source_version_id!==sourceVersionId?!1:buildConfigEqual(build.build_config,buildConfig)}function buildConfigEqual(left,right){return normalizeBuildConfig(left).key===normalizeBuildConfig(right).key}function normalizeBuildConfig(buildConfig){let normalized={...buildConfig?.dockerfile_path?{dockerfile_path:buildConfig.dockerfile_path}:{},...buildConfig?.context_subdir?{context_subdir:buildConfig.context_subdir}:{},...buildConfig?.target?{target:buildConfig.target}:{}};return{...normalized,key:JSON.stringify(normalized)}}async function maybeAutoApplyPreviewResources(args){let skipReason=resolvePreviewAutoResourcesSkipReason(args.args.options);if(skipReason)return{status:"skipped",reason:skipReason};let localResources=await collectEffectiveResources(args.context.appRoot,{sdk:args.context.sdk,appId:args.context.appId});if(localResources.length===0)return{status:"skipped",reason:"no_local_resources"};let payload={operation:"diff",tenant_id:args.context.tenantId,app_id:args.context.appId,env:"preview",requested_by:args.requestedBy,local_resources:localResources},diff=await args.context.sdk.diffResources(payload).catch(async error=>{throw await formatPreviewAutoResourcesError(args.context.sdk,error,{appId:args.context.appId,env:"preview",stage:"diff"})});if(diff.summary.added===0&&diff.summary.modified===0&&diff.summary.deleted===0)return args.args.options.json!==!0&&process.stderr.write(`preview \u8D44\u6E90\u5DF2\u662F\u6700\u65B0\uFF0C\u8DF3\u8FC7\u81EA\u52A8 apply\u3002\u57FA\u7EBF\u5FEB\u7167: ${diff.base_snapshot_id}
2586
+ `))}function sleep5(ms){return new Promise(resolve17=>{setTimeout(resolve17,ms)})}async function loadPreviewBuildBySourceVersion(args){let build=await findReusableSuccessfulBuild({sdk:args.sdk,appId:args.appId,appRoot:args.appRoot,sourceVersionId:args.sourceVersionId,buildConfig:args.buildConfig});if(!build)throw new Error(`preview \u5DF2\u521B\u5EFA\uFF0C\u4F46\u672A\u80FD\u5B9A\u4F4D\u5BF9\u5E94 build: ${args.appId}/${args.sourceVersionId}`);return build}function collectReusableSourceVersionCandidates(sourceContext){return Array.from(new Set([sourceContext?.last_preview_source_version_id,sourceContext?.last_submitted_source_version_id,sourceContext?.base_source_version_id].filter(value=>typeof value=="string"&&value.length>0)))}function sourceWorkspaceFilesEqual(localFiles,remoteFiles){if(localFiles.length!==remoteFiles.length)return!1;for(let index=0;index<localFiles.length;index+=1){let local=localFiles[index],remote=remoteFiles[index];if(!remote||local.path!==remote.path||local.content!==remote.content)return!1}return!0}function isReusableSuccessfulBuild(build,sourceVersionId,buildConfig){return!build||build.status!=="succeeded"||build.lifecycle_status&&build.lifecycle_status!=="active"||build.source_version_id!==sourceVersionId?!1:buildConfigEqual(build.build_config,buildConfig)}function buildConfigEqual(left,right){return normalizeBuildConfig(left).key===normalizeBuildConfig(right).key}function normalizeBuildConfig(buildConfig){let normalized={...buildConfig?.dockerfile_path?{dockerfile_path:buildConfig.dockerfile_path}:{},...buildConfig?.context_subdir?{context_subdir:buildConfig.context_subdir}:{},...buildConfig?.target?{target:buildConfig.target}:{}};return{...normalized,key:JSON.stringify(normalized)}}async function maybeAutoApplyPreviewResources(args){let skipReason=resolvePreviewAutoResourcesSkipReason(args.args.options);if(skipReason)return{status:"skipped",reason:skipReason};let localResources=await collectEffectiveResources(args.context.appRoot,{sdk:args.context.sdk,appId:args.context.appId});if(localResources.length===0)return{status:"skipped",reason:"no_local_resources"};let payload={operation:"diff",tenant_id:args.context.tenantId,app_id:args.context.appId,env:"preview",requested_by:args.requestedBy,local_resources:localResources},diff=await args.context.sdk.diffResources(payload).catch(async error=>{throw await formatPreviewAutoResourcesError(args.context.sdk,error,{appId:args.context.appId,env:"preview",stage:"diff"})});if(diff.summary.added===0&&diff.summary.modified===0&&diff.summary.deleted===0)return args.args.options.json!==!0&&process.stderr.write(`preview \u8D44\u6E90\u5DF2\u662F\u6700\u65B0\uFF0C\u8DF3\u8FC7\u81EA\u52A8 apply\u3002\u57FA\u7EBF\u5FEB\u7167: ${diff.base_snapshot_id}
2582
2587
  `),{status:"no_changes",base_snapshot_id:diff.base_snapshot_id,summary:diff.summary};let applyPayload={...payload,operation:"apply"},applyResult=await withPendingFeedback2(args.args.options.json===!0,`\u68C0\u6D4B\u5230 preview \u5B58\u5728\u672A\u5E94\u7528\u8D44\u6E90\u53D8\u66F4\uFF0C\u5DF2\u81EA\u52A8\u6267\u884C resources apply: ${args.context.appId}/preview`,"preview \u8D44\u6E90 apply \u4ECD\u5728\u8FDB\u884C\uFF0C\u8BF7\u7EE7\u7EED\u7B49\u5F85\u63A7\u5236\u9762\u5B8C\u6210\u57FA\u7EBF\u89E3\u6790\u3001diff \u4E0E\u8D44\u6E90\u7F16\u6392...",()=>args.context.sdk.applyResources(applyPayload)).catch(async error=>{throw await formatPreviewAutoResourcesError(args.context.sdk,error,{appId:args.context.appId,env:"preview",stage:"apply",baseSnapshotId:diff.base_snapshot_id})});if(applyResult.status!=="succeeded")throw new Error([`preview \u8D44\u6E90\u81EA\u52A8 apply \u672A\u6210\u529F: ${args.context.appId}/preview`,`status: ${applyResult.status}`,`base_snapshot: ${applyResult.base_snapshot_id}`,...applyResult.result_snapshot_id?[`result_snapshot: ${applyResult.result_snapshot_id}`]:[],...applyResult.errors&&applyResult.errors.length>0?[`errors: ${applyResult.errors.join(" | ")}`]:[]].join(`
2583
2588
  `));return args.args.options.json!==!0&&process.stderr.write(`preview \u8D44\u6E90\u5DF2\u81EA\u52A8\u8865\u9F50\uFF1A\u65B0\u589E ${applyResult.summary.added}\uFF0C\u4FEE\u6539 ${applyResult.summary.modified}\uFF0C\u5220\u9664 ${applyResult.summary.deleted}
2584
2589
  `),{status:"applied",base_snapshot_id:applyResult.base_snapshot_id,result_snapshot_id:applyResult.result_snapshot_id,summary:applyResult.summary}}function resolvePreviewAutoResourcesSkipReason(options){return options["no-apply-resources"]===!0?"disabled":null}async function runPreviewOpenCommand(args){let context=await loadPreviewContext(args),sourceVersionId=readStringOption11(args,"source-version"),timeline=await context.sdk.listTenantAppDeploymentTimeline(context.appId,{limit:50}),previewItem=findOpenablePreviewDeployment(timeline.items,sourceVersionId);if(!previewItem?.preview_url)throw sourceVersionId?new Error([`\u672A\u627E\u5230\u53EF\u6253\u5F00\u7684 Preview: ${sourceVersionId}`,"\u8BF4\u660E\uFF1A\u8BE5\u7248\u672C\u5F53\u524D\u6CA1\u6709\u53EF\u7528\u7684 Preview \u5730\u5740\u3002","\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u5148\u6267\u884C `platform preview generate --source-version <srcver>`\u3002"].join(`
2585
2590
  `)):new Error([`\u5E94\u7528 ${context.appId} \u5F53\u524D\u6CA1\u6709\u53EF\u6253\u5F00\u7684 Preview\u3002`,"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u5148\u6267\u884C `platform preview generate`\uFF0C\u6216\u663E\u5F0F\u6307\u5B9A\u5DF2\u6709 Preview \u7684\u6E90\u7801\u7248\u672C\u518D\u6267\u884C `platform preview open --source-version <srcver>`\u3002"].join(`
2586
2591
  `));if(args.options.json===!0){process.stdout.write(`${JSON.stringify({app_id:context.appId,tenant_id:context.tenantId,source_version_id:previewItem.source_version_id??null,deployment_id:previewItem.deployment_id,preview_url:previewItem.preview_url},null,2)}
2587
- `);return}let opened=tryOpenExternalUrl(previewItem.preview_url),lines=["\u5DF2\u5B9A\u4F4D\u5230\u53EF\u7528 Preview\u3002",`source_version: ${previewItem.source_version_id??"-"}`,`deployment: ${previewItem.deployment_id}`,`preview_url: ${previewItem.preview_url}`];lines.push(opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u3002":"\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u590D\u5236 preview_url\u3002"),process.stdout.write(`${lines.join(`
2592
+ `);return}let{opened}=await openExternal(previewItem.preview_url),lines=["\u5DF2\u5B9A\u4F4D\u5230\u53EF\u7528 Preview\u3002",`source_version: ${previewItem.source_version_id??"-"}`,`deployment: ${previewItem.deployment_id}`,`preview_url: ${previewItem.preview_url}`];lines.push(opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u3002":"\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u590D\u5236 preview_url\u3002"),process.stdout.write(`${lines.join(`
2588
2593
  `)}
2589
2594
  `)}async function loadPreviewContext(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let appRoot=findAppRoot(getInvocationCwd()),{tenantId,appId}=resolvePreviewProjectContext(appRoot,args);if(!tenantId||!appId)throw new Error("`platform preview` \u9700\u8981\u5DF2\u7ED1\u5B9A\u9879\u76EE\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let apiToken=selectApiToken(credentials);return{tenantId,appId,appRoot,sdk:createControlApiSdk({accessToken:apiToken,tenantId,capability:"dashboard",requestClass:"control"})}}async function resolveRequestedBy3(sdk){return(await sdk.getWhoAmI()).subject_id}function readStringOption11(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function hasHelpFlag6(args){return args.options.help===!0||args.options.h===!0}function printPreviewHelp(mode){if(mode==="generate"){printPreviewGenerateHelp();return}if(mode==="open"){printPreviewOpenHelp();return}process.stdout.write(["platform preview","","\u7528\u6CD5\uFF1A"," platform preview"," platform preview open [--source-version <srcver>]"," platform preview generate [--source-version <srcver>]","","\u8BF4\u660E\uFF1A"," - `platform preview` \u9ED8\u8BA4\u7B49\u4EF7\u4E8E `platform preview open`"," - `platform preview open` \u53EA\u6253\u5F00\u5DF2\u6709 Preview\uFF0C\u4E0D\u89E6\u53D1\u6784\u5EFA\u548C\u90E8\u7F72"," - `platform preview generate` \u624D\u4F1A\u63D0\u4EA4\u7248\u672C\u3001\u6784\u5EFA\u5E76\u751F\u6210 Preview"," - `platform preview generate` \u53EA\u4F5C\u7528\u4E8E preview \u73AF\u5883\uFF0C\u4E0D\u4F1A\u53D1\u5E03 prod"," - prod \u7248\u672C\u5207\u6362\u4E0E\u6B63\u5F0F\u4E0A\u7EBF\u8BF7\u6539\u7528 `platform publish set ...`",""].join(`
2590
2595
  `))}function printPreviewGenerateHelp(){process.stdout.write(["platform preview generate","","\u7528\u6CD5\uFF1A"," platform preview generate"," platform preview generate --source-version <srcver>"," platform preview generate --from-build <build-id>"," platform preview generate --local-build"," platform preview generate --no-wait"," platform preview generate --force-build"," platform preview generate --no-apply-resources","","\u9ED8\u8BA4\u884C\u4E3A\uFF1A"," - \u82E5\u5F53\u524D workspace \u7684 preview \u8D44\u6E90\u5B58\u5728\u672A\u5E94\u7528\u53D8\u66F4\uFF0C\u4F1A\u5148\u81EA\u52A8\u6267\u884C resources apply"," - \u82E5\u672A\u63D0\u4F9B `--source-version`\uFF0C\u5148\u68C0\u67E5\u5F53\u524D\u76EE\u5F55\u662F\u5426\u4E0E\u5DF2\u6709\u6E90\u7801\u7248\u672C\u4E00\u81F4"," - \u82E5\u5B58\u5728\u5339\u914D\u6E90\u7801\u7248\u672C\uFF0C\u4F18\u5148\u590D\u7528\uFF1B\u5426\u5219\u624D\u63D0\u4EA4\u65B0\u7684\u6E90\u7801\u7248\u672C"," - \u82E5\u5DF2\u5B58\u5728\u5339\u914D\u7684\u6210\u529F build\uFF0C\u4F18\u5148\u590D\u7528\u8BE5 build\uFF1B\u5426\u5219\u53D1\u8D77\u5E73\u53F0\u539F\u751F\u6784\u5EFA"," - \u82E5\u663E\u5F0F\u4F20 `--force-build`\uFF0C\u4ECD\u53EF\u590D\u7528\u6E90\u7801\u7248\u672C\uFF0C\u4F46\u4F1A\u8DF3\u8FC7 build \u590D\u7528\u5E76\u5F3A\u5236\u65B0\u5EFA build"," - \u9ED8\u8BA4\u5148\u53D1\u8D77 build\uFF1B\u82E5\u9700\u8981\u7B49\u5F85\uFF0CCLI \u4F1A\u5728 build \u6210\u529F\u540E\u81EA\u52A8\u7EE7\u7EED\u4ECE build \u521B\u5EFA preview"," - \u82E5\u4F20 `--local-build`\uFF0CCLI \u4F1A\u5148\u505A\u6E90\u7801/\u7D20\u6750\u9884\u68C0\uFF0C\u518D\u672C\u5730\u6784\u5EFA\u5E76\u4E0A\u4F20\u9759\u6001\u4EA7\u7269"," - \u5373\u4F7F\u663E\u5F0F\u63D0\u4F9B `--source-version` \u6216 `--from-build`\uFF0C\u9ED8\u8BA4\u4ECD\u4F1A\u5C1D\u8BD5\u81EA\u52A8\u8865\u9F50 preview \u8D44\u6E90"," - \u82E5\u53EA\u60F3\u663E\u5F0F\u6267\u884C build\uFF0C\u8BF7\u6539\u7528 `platform build run --source-version <srcver> --wait`"," - \u8BE5\u547D\u4EE4\u4E0D\u4F1A\u4FEE\u6539 prod\uFF1B\u6B63\u5F0F\u4E0A\u7EBF\u8BF7\u5355\u72EC\u6267\u884C `platform publish set --source-version <srcver> --status published`","","\u5931\u8D25\u5206\u6D41\uFF1A"," - build \u5931\u8D25\uFF1A\u8F93\u51FA build id\u3001error\u3001log_ref\uFF0C\u5E76\u5EFA\u8BAE\u67E5\u770B build events"," - preview \u5931\u8D25\uFF1A\u8F93\u51FA release/deployment\uFF0C\u5E76\u4F18\u5148\u7ED9\u51FA\u8BCA\u65AD\u9875\u94FE\u63A5",""].join(`
@@ -2594,7 +2599,7 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2594
2599
  `)}function printPreviewDeployResult(preview,context){let lines=[preview.status==="active"?"Preview \u5DF2\u521B\u5EFA\u3002":"\u6784\u5EFA\u5DF2\u5B8C\u6210\uFF0C\u4F46 preview \u521B\u5EFA\u5931\u8D25\u3002",`build: ${context.buildId}`,`preview_status: ${preview.status}`,`release: ${preview.release_id??"-"}`,`deployment: ${preview.deployment_id??"-"}`,`current_release: ${preview.current_release_id??"-"}`,`source_version: ${preview.source_version_id??"-"}`,`${formatPreviewExecutionLabel(preview.runtime.execution_mode)}: ${preview.runtime.deployment_status} / ${preview.runtime.health} / ${preview.runtime.execution_mode}`];context.fromBuildId?lines.unshift(`\u5F53\u524D\u94FE\u8DEF: \u663E\u5F0F\u590D\u7528\u5DF2\u6709 build ${context.fromBuildId}`):context.requestedSourceVersionId?lines.unshift(`\u5F53\u524D\u94FE\u8DEF: \u57FA\u4E8E\u663E\u5F0F source version ${context.requestedSourceVersionId} \u751F\u6210 preview`):lines.unshift("\u5F53\u524D\u94FE\u8DEF: \u57FA\u4E8E\u672C\u5730\u5DE5\u4F5C\u533A\u751F\u6210 preview"),context.createdSourceVersionId&&lines.unshift(`\u5DF2\u81EA\u52A8\u63D0\u4EA4\u65B0\u7684\u6E90\u7801\u7248\u672C: ${context.createdSourceVersionId}`),context.reusedSourceVersionId&&lines.unshift(`\u5DF2\u590D\u7528\u672C\u5730\u5339\u914D\u7684\u6E90\u7801\u7248\u672C: ${context.reusedSourceVersionId}`),preview.runtime.preview_url&&lines.push(`preview_url: ${preview.runtime.preview_url}`),preview.runtime.health_check_url&&lines.push(`health_check_url: ${preview.runtime.health_check_url}`),preview.runtime.object_prefix&&lines.push(`object_prefix: ${preview.runtime.object_prefix}`),preview.runtime.message&&lines.push(`message: ${preview.runtime.message}`),preview.runtime.failure_reason&&lines.push(`failure_reason: ${preview.runtime.failure_reason}`),preview.runtime.diagnostic_url&&lines.push(`diagnostic_url: ${preview.runtime.diagnostic_url}`),preview.errors&&preview.errors.length>0&&lines.push(`errors: ${preview.errors.join(" | ")}`),preview.status!=="active"&&lines.push("\u4E0B\u4E00\u6B65: \u4F18\u5148\u6253\u5F00 diagnostic_url\uFF1B\u82E5\u6CA1\u6709\u8BCA\u65AD\u9875\uFF0C\u518D\u67E5 release/deployment \u5BF9\u5E94\u65E5\u5FD7\u3002"),preview.runtime.execution_mode==="static"&&lines.push("\u8BF4\u660E: \u5F53\u524D Preview \u8D70\u9759\u6001\u53D1\u5E03\u94FE\u8DEF\uFF0C\u4E0D\u6D89\u53CA K8s readiness\u3002\u82E5\u9875\u9762\u53EF\u6253\u5F00\uFF0C\u4F18\u5148\u68C0\u67E5\u9759\u6001\u8D44\u6E90\u4E0E object_prefix\u3002"),lines.push("\u8BF4\u660E: preview \u751F\u6210\u5B8C\u6210\u540E\uFF0C\u5982\u9700\u4E0A\u7EBF\u6B63\u5F0F\u73AF\u5883\uFF0C\u8BF7\u5355\u72EC\u6267\u884C `platform publish set --source-version <srcver> --status published`\u3002"),context.postCheck?.status==="warning"&&context.postCheck.lines.length>0&&(lines.push(""),lines.push("[Post-check]"),lines.push(...context.postCheck.lines)),process.stdout.write(`${lines.join(`
2595
2600
  `)}
2596
2601
  `)}function formatPreviewExecutionLabel(executionMode){return executionMode==="static"?"delivery":"runtime"}async function formatPreviewCommandError(sdk,error,context){if(!(error instanceof PlatformApiError))return error instanceof Error?error:new Error("preview \u547D\u4EE4\u6267\u884C\u5931\u8D25");let lines=[`platform preview ${context.stage} \u5931\u8D25: ${context.appId}`,`code: ${error.code}`,`message: ${error.message}`];return context.sourceVersionId&&lines.push(`source_version: ${context.sourceVersionId}`),context.buildId&&lines.push(`build: ${context.buildId}`),error.requestId&&lines.push(`request_id: ${error.requestId}`),error.detail&&lines.push(`detail: ${JSON.stringify(error.detail)}`),lines.push(...await buildPreviewBindingHintLines(sdk,context.appId,"preview")),lines.push("\u5EFA\u8BAE\u5148\u6267\u884C `platform app diagnose --env preview`\uFF0C\u786E\u8BA4 Auth / DB / Workflow / preview readiness\u3002"),lines.push("\u6CE8\u610F: `platform preview generate` \u53EA\u5F71\u54CD preview\uFF1B\u5982\u9700\u66F4\u65B0 prod\uFF0C\u8BF7\u6539\u7528 `platform publish set ...`\u3002"),new Error(lines.join(`
2597
- `))}function resolveExplicitPreviewMode(args){let subcommand=args.rest[0];if(subcommand==="generate"||subcommand==="open")return subcommand}function resolvePreviewMode(args){let explicitMode=resolveExplicitPreviewMode(args);return explicitMode||(hasGenerateOnlyOptions(args.options)?"generate":"open")}function hasGenerateOnlyOptions(options){return["from-build","no-wait","no-apply-resources","dockerfile","context-subdir","target","local-build","build-mode","force-build","message"].some(key=>key in options)}function isPreviewBuildPendingResponse(value){return!value||typeof value!="object"?!1:"operation"in value&&value.operation==="deploy"&&"env"in value&&value.env==="preview"&&"status"in value&&value.status==="building"&&"build_id"in value&&typeof value.build_id=="string"&&value.build_id.length>0}function findOpenablePreviewDeployment(items,sourceVersionId){for(let item of items)if(item.env==="preview"&&item.preview_url&&item.deployment_status==="succeeded"&&!(sourceVersionId&&item.source_version_id!==sourceVersionId))return item;return null}function tryOpenExternalUrl(url){let normalizedUrl=url.trim();if(!normalizedUrl)return!1;try{return process.platform==="darwin"?(spawn6("open",[normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0):process.platform==="win32"?(spawn6("cmd",["/c","start","",normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0):(spawn6("xdg-open",[normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0)}catch{return!1}}async function withPendingFeedback2(jsonOutput,startMessage,waitingMessage,action){if(jsonOutput)return action();process.stderr.write(`${startMessage}
2602
+ `))}function resolveExplicitPreviewMode(args){let subcommand=args.rest[0];if(subcommand==="generate"||subcommand==="open")return subcommand}function resolvePreviewMode(args){let explicitMode=resolveExplicitPreviewMode(args);return explicitMode||(hasGenerateOnlyOptions(args.options)?"generate":"open")}function hasGenerateOnlyOptions(options){return["from-build","no-wait","no-apply-resources","dockerfile","context-subdir","target","local-build","build-mode","force-build","message"].some(key=>key in options)}function isPreviewBuildPendingResponse(value){return!value||typeof value!="object"?!1:"operation"in value&&value.operation==="deploy"&&"env"in value&&value.env==="preview"&&"status"in value&&value.status==="building"&&"build_id"in value&&typeof value.build_id=="string"&&value.build_id.length>0}function findOpenablePreviewDeployment(items,sourceVersionId){for(let item of items)if(item.env==="preview"&&item.preview_url&&item.deployment_status==="succeeded"&&!(sourceVersionId&&item.source_version_id!==sourceVersionId))return item;return null}async function withPendingFeedback2(jsonOutput,startMessage,waitingMessage,action){if(jsonOutput)return action();process.stderr.write(`${startMessage}
2598
2603
  `);let timer=setTimeout(()=>{process.stderr.write(`${waitingMessage}
2599
2604
  `)},1500);try{return await action()}finally{clearTimeout(timer)}}async function formatPreviewAutoResourcesError(sdk,error,context){if(!(error instanceof PlatformApiError))return error instanceof Error?error:new Error("preview \u81EA\u52A8\u8D44\u6E90 apply \u5931\u8D25");let lines=[`preview \u81EA\u52A8\u8D44\u6E90 ${context.stage} \u5931\u8D25: ${context.appId}/${context.env}`,`code: ${error.code}`,`message: ${error.message}`];return context.baseSnapshotId&&lines.push(`base_snapshot: ${context.baseSnapshotId}`),error.requestId&&lines.push(`request_id: ${error.requestId}`),error.detail&&lines.push(`detail: ${JSON.stringify(error.detail)}`),lines.push(...await buildPreviewBindingHintLines(sdk,context.appId,context.env)),lines.push("\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u53EF\u6539\u7528 `platform preview generate --no-apply-resources` \u8DF3\u8FC7\u81EA\u52A8 apply\uFF0C\u6216\u5148\u624B\u52A8\u6267\u884C `platform resources diff/apply --env preview`\u3002"),lines.push("\u8865\u5145\u5EFA\u8BAE\uFF1A\u6267\u884C `platform app diagnose --env preview`\uFF0C\u786E\u8BA4\u5F53\u524D preview \u662F\u5426\u5DF2\u7ECF ready for runtime validation\u3002"),new Error(lines.join(`
2600
2605
  `))}async function buildPreviewBindingHintLines(sdk,appId,env){let authInspect=await sdk.getTenantAppEndUserAuthInspect(appId).catch(()=>null),dbInstance=await sdk.getTenantAppDbInstance(appId,env).catch(()=>null),authEnv=authInspect?.environments.find(item=>item.env===env)??null;return buildPreviewBindingHintLinesFromState({appId,env,authInspect,authEnv,dbInstance})}function buildPreviewBindingHintLinesFromState(args){let lines=[];if(args.authEnv&&args.authInspect){lines.push(`runtime_hint.auth.${args.env}: ${args.authEnv.status} missing=[${args.authEnv.missing_binding_keys.join(", ")||"-"}] issues=[${args.authEnv.issues.join(", ")||"-"}]`);let authActions=formatPreviewAuthSuggestedActions(args.appId,args.env,args.authInspect,args.authEnv);authActions.length>0&&lines.push(`runtime_hint.auth_actions: ${authActions.join(" | ")}`)}return args.dbInstance&&!args.dbInstance.bound&&(lines.push(`runtime_hint.db.${args.env}: ${args.dbInstance.status??"not_bound"}`),lines.push(`runtime_hint.db_actions: platform resources apply --env ${args.env}`)),lines}async function buildPreviewSuccessPostCheckPayload(sdk,appId,preview){if(preview.status!=="active")return{status:"ready",lines:[]};let runtimeHintLines=await buildPreviewBindingHintLines(sdk,appId,"preview");return runtimeHintLines.length===0&&preview.runtime.health==="healthy"?{status:"ready",lines:[]}:{status:"warning",lines:["Preview \u5DF2\u751F\u6210\uFF0C\u4F46\u8FD0\u884C\u65F6\u540E\u7F6E\u68C0\u67E5\u4ECD\u6709\u7F3A\u53E3\u3002",`runtime_health: ${preview.runtime.health}`,...runtimeHintLines,"\u5EFA\u8BAE: \u5148\u6267\u884C `platform app diagnose --env preview`\uFF0C\u518D\u51B3\u5B9A\u662F\u5426\u7EE7\u7EED\u9875\u9762\u8054\u8C03\u3002"]}}function formatPreviewAuthSuggestedActions(appId,env,inspect,authEnv){let actions=new Set;for(let action of inspect.suggested_actions??[])switch(action){case"enable_auth":actions.add(`platform auth configure --app ${appId} --enable`);break;case"bind_user_store":actions.add(`platform auth bind --app ${appId} --action bind --user-store-id <user-store-id>`);break;case"reapply_auth_resources":actions.add(`platform resources apply --env ${env}`);break;case"check_runtime_bindings":actions.add(`platform auth inspect --app ${appId}`);break;default:break}return authEnv.status!=="ready"&&actions.add(`platform auth inspect --app ${appId}`),(authEnv.missing_binding_keys.length>0||authEnv.issues.includes("binding_missing"))&&actions.add(`platform resources apply --env ${env}`),Array.from(actions)}import{join as join20}from"node:path";function isReauthRequiredPlatformError(error){return error instanceof PlatformApiError&&[401,403].includes(error.status)}function requiresLoginRecovery(error){return error instanceof CliSessionExpiredError||isReauthRequiredPlatformError(error)?!0:error instanceof Error?[/未找到本地凭据/u,/当前凭据已过期且不支持自动刷新/u,/当前 PAT 登录已超过 7 天有效期/u,/当前凭据缺少 refresh_token/u,/当前 PAT 凭据缺少 subject_token/u,/请重新执行 `platform login/u].some(pattern=>pattern.test(error.message)):!1}function formatReauthHint(options={}){let lines=["\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A",`1. \u6267\u884C \`${options.credentialMode==="pat_exchange"?"platform login --pat <token>":"platform login"}\` \u6062\u590D CLI \u767B\u5F55\u6001`,"2. \u6267\u884C `platform whoami` \u786E\u8BA4\u51ED\u636E\u5DF2\u6062\u590D","3. \u518D\u91CD\u8BD5\u521A\u624D\u7684\u547D\u4EE4"];return options.credentialPath&&lines.push(`\u5F53\u524D\u51ED\u636E\u6587\u4EF6: ${options.credentialPath}`),lines.join(`
@@ -2629,24 +2634,22 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2629
2634
  `)}async function runWorkflowBindingSubcommand(sdk,context,args){let action=args.rest[1];if(action==="list"){let items=await sdk.listWorkflowBindings({target_id:readStringOption13(args,"target-id")??readStringOption13(args,"app")??context.appId,definition_key:readStringOption13(args,"definition")??readStringOption13(args,"definition-key")});process6.stdout.write(`${JSON.stringify(items,null,2)}
2630
2635
  `);return}if(action==="inspect"){let definitionKey=readStringOption13(args,"definition")??readStringOption13(args,"definition-key")??readStringOption13(args,"binding"),targetScope=readStringOption13(args,"target-scope")??"tenant_app",targetId=readStringOption13(args,"target-id")??readStringOption13(args,"app")??context.appId;if(!definitionKey||!targetId)throw new Error("`platform workflow binding inspect` \u9700\u8981 `--definition <key>` \u548C `--target-id <id>`\uFF1B\u5728\u8F7B\u5E94\u7528\u4E0A\u4E0B\u6587\u91CC\u53EF\u7701\u7565 `--target-id`\u3002");let item=(await sdk.listWorkflowBindings({target_id:targetId,definition_key:definitionKey})).find(candidate=>candidate.definition_key===definitionKey&&candidate.target_id===targetId);if(!item)throw new Error(`\u672A\u627E\u5230 Workflow binding: ${definitionKey} @ ${targetId}`);let[override,roleBindings]=await Promise.all([sdk.getWorkflowBindingOverride({target_scope:targetScope,target_id:targetId,definition_key:definitionKey}),sdk.listWorkflowRoleBindings({target_scope:targetScope,target_id:targetId,definition_key:definitionKey})]);process6.stdout.write(`${JSON.stringify({binding:item,override,role_bindings:roleBindings},null,2)}
2631
2636
  `);return}if(action==="update"){let file=readStringOption13(args,"file"),payloadFromFile=file?readJsonFile(file):null,definitionKey=readStringOption13(args,"definition")??readStringOption13(args,"definition-key")??readString(payloadFromFile,"definition_key"),targetScope=readStringOption13(args,"target-scope")??readString(payloadFromFile,"target_scope")??"tenant_app",targetId=readStringOption13(args,"target-id")??readStringOption13(args,"app")??context.appId??readString(payloadFromFile,"target_id");if(!file||!definitionKey||!targetId)throw new Error("`platform workflow binding update` \u9700\u8981 `--file <override.json>`\u3001`--definition <key>`\uFF0C\u4EE5\u53CA `--target-id <id>`\uFF1B\u5728\u8F7B\u5E94\u7528\u4E0A\u4E0B\u6587\u91CC\u53EF\u7701\u7565 `--target-id`\u3002");let item=await sdk.saveWorkflowBindingOverride({tenant_id:context.tenantId,definition_key:definitionKey,target_scope:targetScope,target_id:targetId,state_overrides:payloadFromFile?.state_overrides??[],action_overrides:payloadFromFile?.action_overrides??[]});targetScope==="tenant_app"&&await syncLocalControlPlaneSummary({sdk,startDir:process6.cwd(),tenantId:context.tenantId,appId:targetId}),process6.stdout.write(`${JSON.stringify(item,null,2)}
2632
- `);return}throw new Error("`platform workflow binding` \u76EE\u524D\u4EC5\u652F\u6301 `list`\u3001`inspect` \u6216 `update`\u3002")}function resolveWorkflowContext(args){let storedContext=loadStoredCliContext(),binding;try{binding=readBinding(findAppRoot(process6.cwd()))?.binding}catch{binding=void 0}return{tenantId:readStringOption13(args,"tenant")??binding?.tenant_id??storedContext?.selected_app_tenant_id,appId:readStringOption13(args,"app")??binding?.app_id??storedContext?.selected_app_id}}function readStringOption13(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readJsonOption(args,key){let value=readStringOption13(args,key);if(value)return JSON.parse(value)}function readJsonFile(path){return JSON.parse(readFileSync25(path,"utf8"))}function readString(record,key){let value=record?.[key];return typeof value=="string"?value:void 0}function readNullableString(record,key){let value=record?.[key];return value===null?null:typeof value=="string"?value:void 0}function getDevHelpLines(){return["platform dev","","\u7B2C\u4E00\u9636\u6BB5\u53EF\u7528\u5165\u53E3\uFF1A"," platform dev"," platform dev --remote-bindings"," platform dev --remote-bindings=db"," platform dev push"," platform dev preview generate"," platform dev preview open","","\u8BF4\u660E\uFF1A"," - `platform dev` \u7EE7\u7EED\u4F5C\u4E3A\u672C\u5730\u8F7B\u91CF\u5F00\u53D1\u5165\u53E3\uFF0C\u5B9E\u9645\u6267\u884C app.yaml \u4E2D\u7684 `entry.command`"," - `platform dev` \u9ED8\u8BA4\u5355\u6B21\u542F\u52A8 `entry.command`\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F"," - \u82E5 app.yaml \u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\uFF0CCLI \u624D\u4F1A\u76D1\u542C\u6E90\u7801\u53D8\u66F4\u5E76\u81EA\u52A8\u91CD\u542F\u672C\u5730 dev \u5B50\u8FDB\u7A0B"," - `platform dev --remote-bindings` \u9ED8\u8BA4\u6309 `auto` \u6A21\u5F0F\u8FD0\u884C\uFF1A\u53EA\u5C1D\u8BD5\u6CE8\u5165\u5F53\u524D\u5DE5\u4F5C\u533A\u5DF2\u58F0\u660E\u7684\u8FDC\u7AEF binding"," - \u82E5\u5F53\u524D\u5DE5\u4F5C\u533A\u672A\u68C0\u6D4B\u5230\u771F\u5B9E DB migration\uFF0C`platform dev --remote-bindings` \u4F1A\u8DF3\u8FC7 DB binding\uFF0C\u4E0D\u963B\u65AD\u672C\u5730\u542F\u52A8"," - \u82E5\u4F60\u786E\u8BA4\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u53EF\u663E\u5F0F\u6267\u884C `platform dev --remote-bindings=db`"," - `platform dev` \u8F93\u51FA\u7684\u662F\u672C\u5730\u9884\u89C8\u5730\u5740\uFF1B\u4E91\u7AEF\u53EF\u5206\u4EAB\u7684 Preview \u9700\u8981\u5355\u72EC\u6267\u884C `platform preview generate` \u6216 `platform dev preview generate`"," - `platform dev push` \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u8986\u76D6\u63A8\u9001\u5230\u4E91\u7AEF Dev Workspace"," - `platform dev preview generate/open` \u53EA\u64CD\u4F5C\u5DE5\u4F5C\u533A Preview"," - \u6B63\u5F0F\u7248\u672C\u751F\u6210\u7EE7\u7EED\u4F7F\u7528 `platform app submit`"," - \u7B2C\u4E00\u9636\u6BB5\u4E0D\u5F15\u5165 `platform dev save`","","\u793A\u4F8B\uFF1A"," platform dev"," platform dev --remote-bindings"," platform dev --remote-bindings=db"," platform dev push"," platform dev preview generate"," platform dev preview open",' platform app submit --message "formal version"',""]}function getDevPreviewHelpLines(){return["platform dev preview","","\u53EF\u7528\u5B50\u547D\u4EE4\uFF1A"," platform dev preview generate"," platform dev preview open","","\u8BF4\u660E\uFF1A"," - `generate` \u57FA\u4E8E\u4E91\u7AEF Dev Workspace \u751F\u6210\u5DE5\u4F5C\u533A Preview"," - `open` \u6253\u5F00\u5F53\u524D\u5DE5\u4F5C\u533A Preview"," - \u5DE5\u4F5C\u533A Preview \u4E0E\u7248\u672C Preview \u5171\u7528 app \u7684 Preview \u69FD\u4F4D",""]}function getDevSaveUnsupportedMessage(){return["`platform dev save` \u5728\u7B2C\u4E00\u9636\u6BB5\u672A\u5F00\u653E\u3002","\u5F53\u524D\u6B63\u5F0F\u7248\u672C\u751F\u6210\u7EE7\u7EED\u6CBF\u7528\u73B0\u6709\u6B63\u5F0F\u7248\u672C\u94FE\u8DEF\u3002",'\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u4F7F\u7528 `platform app submit --message "..."` \u751F\u6210\u65B0\u7684\u6B63\u5F0F\u7248\u672C\u3002'].join(`
2633
- `)}import{spawn as spawn7}from"node:child_process";var implementedWorkers=new Set(["preview-retention"]);async function runWorkerCommand(args){let worker=args.rest[0]??"help";if(worker==="help"||args.options.help===!0||args.options.h===!0){printWorkerHelp();return}if(!implementedWorkers.has(worker)){let payload={ok:!1,code:"worker_not_implemented",worker,implemented_workers:[...implementedWorkers]};args.options.json===!0?process.stderr.write(`${JSON.stringify(payload,null,2)}
2637
+ `);return}throw new Error("`platform workflow binding` \u76EE\u524D\u4EC5\u652F\u6301 `list`\u3001`inspect` \u6216 `update`\u3002")}function resolveWorkflowContext(args){let storedContext=loadStoredCliContext(),binding;try{binding=readBinding(findAppRoot(process6.cwd()))?.binding}catch{binding=void 0}return{tenantId:readStringOption13(args,"tenant")??binding?.tenant_id??storedContext?.selected_app_tenant_id,appId:readStringOption13(args,"app")??binding?.app_id??storedContext?.selected_app_id}}function readStringOption13(args,key){let value=args.options[key];return typeof value=="string"?value:void 0}function readJsonOption(args,key){let value=readStringOption13(args,key);if(value)return JSON.parse(value)}function readJsonFile(path2){return JSON.parse(readFileSync25(path2,"utf8"))}function readString(record,key){let value=record?.[key];return typeof value=="string"?value:void 0}function readNullableString(record,key){let value=record?.[key];return value===null?null:typeof value=="string"?value:void 0}function getDevHelpLines(){return["platform dev","","\u7B2C\u4E00\u9636\u6BB5\u53EF\u7528\u5165\u53E3\uFF1A"," platform dev"," platform dev --remote-bindings"," platform dev --remote-bindings=db"," platform dev push"," platform dev preview generate"," platform dev preview open","","\u8BF4\u660E\uFF1A"," - `platform dev` \u7EE7\u7EED\u4F5C\u4E3A\u672C\u5730\u8F7B\u91CF\u5F00\u53D1\u5165\u53E3\uFF0C\u5B9E\u9645\u6267\u884C app.yaml \u4E2D\u7684 `entry.command`"," - `platform dev` \u9ED8\u8BA4\u5355\u6B21\u542F\u52A8 `entry.command`\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u91CD\u542F"," - \u82E5 app.yaml \u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\uFF0CCLI \u624D\u4F1A\u76D1\u542C\u6E90\u7801\u53D8\u66F4\u5E76\u81EA\u52A8\u91CD\u542F\u672C\u5730 dev \u5B50\u8FDB\u7A0B"," - `platform dev --remote-bindings` \u9ED8\u8BA4\u6309 `auto` \u6A21\u5F0F\u8FD0\u884C\uFF1A\u53EA\u5C1D\u8BD5\u6CE8\u5165\u5F53\u524D\u5DE5\u4F5C\u533A\u5DF2\u58F0\u660E\u7684\u8FDC\u7AEF binding"," - \u82E5\u5F53\u524D\u5DE5\u4F5C\u533A\u672A\u68C0\u6D4B\u5230\u771F\u5B9E DB migration\uFF0C`platform dev --remote-bindings` \u4F1A\u8DF3\u8FC7 DB binding\uFF0C\u4E0D\u963B\u65AD\u672C\u5730\u542F\u52A8"," - \u82E5\u4F60\u786E\u8BA4\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u53EF\u663E\u5F0F\u6267\u884C `platform dev --remote-bindings=db`"," - `platform dev` \u8F93\u51FA\u7684\u662F\u672C\u5730\u9884\u89C8\u5730\u5740\uFF1B\u4E91\u7AEF\u53EF\u5206\u4EAB\u7684 Preview \u9700\u8981\u5355\u72EC\u6267\u884C `platform preview generate` \u6216 `platform dev preview generate`"," - `platform dev push` \u5C06\u5F53\u524D\u672C\u5730\u6E90\u7801\u8986\u76D6\u63A8\u9001\u5230\u4E91\u7AEF Dev Workspace"," - `platform dev preview generate/open` \u53EA\u64CD\u4F5C\u5DE5\u4F5C\u533A Preview"," - \u6B63\u5F0F\u7248\u672C\u751F\u6210\u7EE7\u7EED\u4F7F\u7528 `platform app submit`"," - \u7B2C\u4E00\u9636\u6BB5\u4E0D\u5F15\u5165 `platform dev save`","","\u793A\u4F8B\uFF1A"," platform dev"," platform dev --remote-bindings"," platform dev --remote-bindings=db"," platform dev push"," platform dev preview generate"," platform dev preview open",' platform app submit --message "formal version"',""]}function getDevPreviewHelpLines(){return["platform dev preview","","\u53EF\u7528\u5B50\u547D\u4EE4\uFF1A"," platform dev preview generate"," platform dev preview open","","\u8BF4\u660E\uFF1A"," - `generate` \u57FA\u4E8E\u4E91\u7AEF Dev Workspace \u751F\u6210\u5DE5\u4F5C\u533A Preview"," - `open` \u6253\u5F00\u5F53\u524D\u5DE5\u4F5C\u533A Preview"," - \u5DE5\u4F5C\u533A Preview \u4E0E\u7248\u672C Preview \u5171\u7528 app \u7684 Preview \u69FD\u4F4D",""]}function getDevSaveUnsupportedMessage(){return["`platform dev save` \u5728\u7B2C\u4E00\u9636\u6BB5\u672A\u5F00\u653E\u3002","\u5F53\u524D\u6B63\u5F0F\u7248\u672C\u751F\u6210\u7EE7\u7EED\u6CBF\u7528\u73B0\u6709\u6B63\u5F0F\u7248\u672C\u94FE\u8DEF\u3002",'\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u4F7F\u7528 `platform app submit --message "..."` \u751F\u6210\u65B0\u7684\u6B63\u5F0F\u7248\u672C\u3002'].join(`
2638
+ `)}import{spawn as spawn4}from"node:child_process";var implementedWorkers=new Set(["preview-retention"]);async function runWorkerCommand(args){let worker=args.rest[0]??"help";if(worker==="help"||args.options.help===!0||args.options.h===!0){printWorkerHelp();return}if(!implementedWorkers.has(worker)){let payload={ok:!1,code:"worker_not_implemented",worker,implemented_workers:[...implementedWorkers]};args.options.json===!0?process.stderr.write(`${JSON.stringify(payload,null,2)}
2634
2639
  `):process.stderr.write(`worker \u672A\u5B9E\u73B0: ${worker}
2635
2640
  \u5F53\u524D\u5DF2\u5B9E\u73B0: ${[...implementedWorkers].join(", ")}
2636
2641
  `),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(`
2637
- `))}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((resolve16,reject)=>{let child=spawn7("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),resolve16()})})}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"," 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 endpoint / readiness\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 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(`
2642
+ `))}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((resolve17,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),resolve17()})})}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"," 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 endpoint / readiness\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 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(`
2638
2643
  `))}function printVersion(){process7.stdout.write(`v${cliPackageVersion}
2639
- `)}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 tryOpenBrowser2(url){let normalizedUrl=url.trim();if(!normalizedUrl)return!1;try{return process7.platform==="darwin"?(spawn8("open",[normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0):process7.platform==="win32"?(spawn8("cmd",["/c","start","",normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0):(spawn8("xdg-open",[normalizedUrl],{stdio:"ignore",detached:!0}).unref(),!0)}catch{return!1}}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]","","\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","","\u73AF\u5883\u53D8\u91CF\uFF1A"," CONTROL_API_BASE_URL"," RUNTIME_API_BASE_URL"," PUBLIC_API_BASE_URL"," CONTROL_API_RUNTIME_ENDPOINT_CAPABILITIES",""].join(`
2644
+ `)}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]","","\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","","\u73AF\u5883\u53D8\u91CF\uFF1A"," CONTROL_API_BASE_URL"," RUNTIME_API_BASE_URL"," PUBLIC_API_BASE_URL"," CONTROL_API_RUNTIME_ENDPOINT_CAPABILITIES",""].join(`
2640
2645
  `))}async function runDiagnostics(args){let subcommand=args.rest[0]??"help";if(hasFlag2(args,"help")||hasFlag2(args,"h")||subcommand==="help"){printDiagnosticsHelp();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)}
2641
2646
  `);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==="-"?readFileSync26(0,"utf8"):readFileSync26(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){let linked;try{linked=readBinding(currentInvocationDir())}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(`
2642
2647
  `));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")}async function runLogin(args){let issuer=readRequiredEnv("OIDC_ISSUER"),audience=process7.env.OIDC_AUDIENCE?.trim(),scopes=(process7.env.LOGTO_CLI_SCOPES??"openid profile offline_access").split(/\s+/u).filter(Boolean),cliClientId=readAuthConfigValue(AUTH_CLI_CLIENT_ID_KEYS),browserLoginConfig=resolveBrowserLoginConfig(),pat=readOption2(args,"pat")?.trim(),credentials;if(pat){if(!cliClientId)throw new Error("`platform login --pat` \u9700\u8981\u5DF2\u914D\u7F6E `AUTH_CLI_CLIENT_ID`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_APP_ID`\uFF09\u3002");credentials=await performPatTokenExchangeLogin({issuer,clientId:cliClientId,audience,scopes,subjectToken:pat}),persistCredentials(credentials),process7.stdout.write(["PAT \u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5DF2\u5199\u5165: ${getCredentialPath()}`,"\u8BF4\u660E: \u5F53\u524D\u4E3A\u673A\u5668\u51ED\u636E\u6A21\u5F0F\uFF0CCLI \u4F1A\u5728 7 \u5929\u7A97\u53E3\u5185\u81EA\u52A8\u91CD\u65B0\u4EA4\u6362 access token\u3002","\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami"," 2. \u5982\u9700\u957F\u671F\u4EBA\u5DE5\u5F00\u53D1\uFF0C\u4F18\u5148\u6539\u7528 `platform login` \u6D4F\u89C8\u5668\u767B\u5F55",""].join(`
2643
- `));return}if(cliClientId)try{credentials=await performDeviceCodeLogin({issuer,clientId:cliClientId,audience,scopes,onPrompt:({verificationUri,userCode,expiresIn})=>{let opened=tryOpenBrowser2(verificationUri);process7.stdout.write((opened?["\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",""]:["\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",`\u9A8C\u8BC1\u5730\u5740: ${verificationUri}`,`User Code: ${userCode}`,`\u6709\u6548\u671F: ${expiresIn} \u79D2`,""]).join(`
2648
+ `));return}if(cliClientId)try{credentials=await performDeviceCodeLogin({issuer,clientId:cliClientId,audience,scopes,onPrompt:async({verificationUri,userCode,expiresIn})=>{let{opened}=await openExternal(verificationUri);process7.stdout.write((opened?["\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",""]:["\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u767B\u5F55\u6388\u6743\u3002",`\u9A8C\u8BC1\u5730\u5740: ${verificationUri}`,`User Code: ${userCode}`,`\u6709\u6548\u671F: ${expiresIn} \u79D2`,""]).join(`
2644
2649
  `))}})}catch(error){if(!shouldFallbackToBrowserLogin(error))throw error;if(process7.stdout.write(`\u5F53\u524D\u73AF\u5883\u4E0D\u53EF\u7528 Device Flow\uFF0C\u81EA\u52A8\u5207\u6362\u5230\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\u3002
2645
- `),!browserLoginConfig)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11\u53EF\u7528\u4E8E\u6D4F\u89C8\u5668\u767B\u5F55\u7684\u914D\u7F6E\uFF0C\u8BF7\u8865\u9F50 `AUTH_CLI_REDIRECT_URI`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_REDIRECT_URI`\uFF09\uFF0C\u6216\u63D0\u4F9B `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:({authorizationUrl,redirectUri})=>{let opened=tryOpenBrowser2(authorizationUrl);process7.stdout.write((opened?["\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",""]:[browserLoginConfig.source==="cli-app"?"\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002":"\u4F7F\u7528 workbench \u914D\u7F6E\u56DE\u9000\u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u5F3A\u5236 prompt=login consent \u4EE5\u907F\u514D\u590D\u7528\u9519\u8BEF SSO \u4F1A\u8BDD\u5E76\u6362\u53D6 refresh token\u3002","\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",`\u6388\u6743\u5730\u5740: ${authorizationUrl}`,`\u56DE\u8C03\u5730\u5740: ${redirectUri}`,browserLoginConfig.source==="workbench-fallback"?"\u82E5\u56DE\u8C03\u7AEF\u53E3\u88AB\u672C\u5730 workbench \u5360\u7528\uFF0C\u8BF7\u5148\u6682\u65F6\u505C\u6B62\u5BF9\u5E94\u670D\u52A1\u540E\u91CD\u8BD5\u3002":"\u8BF7\u786E\u8BA4\u8BE5\u56DE\u8C03\u5730\u5740\u5DF2\u5728\u4E13\u7528 CLI App \u4E2D\u6CE8\u518C\u3002",""]).join(`
2646
- `))}})}else{if(!browserLoginConfig)throw new Error("\u7F3A\u5C11\u6D4F\u89C8\u5668\u767B\u5F55\u914D\u7F6E\uFF1A\u8BF7\u4F18\u5148\u8865\u9F50 `AUTH_CLI_CLIENT_ID / AUTH_CLI_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_*`\uFF09\uFF1B\u82E5\u6682\u65F6\u65E0\u6CD5\u63D0\u4F9B\uFF0C\u518D\u8865\u9F50 `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");process7.stdout.write(browserLoginConfig.source==="cli-app"?`\u5F53\u524D\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002
2650
+ `),!browserLoginConfig)throw new Error("\u5F53\u524D\u73AF\u5883\u7F3A\u5C11\u53EF\u7528\u4E8E\u6D4F\u89C8\u5668\u767B\u5F55\u7684\u914D\u7F6E\uFF0C\u8BF7\u8865\u9F50 `AUTH_CLI_REDIRECT_URI`\uFF08\u6216\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_REDIRECT_URI`\uFF09\uFF0C\u6216\u63D0\u4F9B `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}else{if(!browserLoginConfig)throw new Error("\u7F3A\u5C11\u6D4F\u89C8\u5668\u767B\u5F55\u914D\u7F6E\uFF1A\u8BF7\u4F18\u5148\u8865\u9F50 `AUTH_CLI_CLIENT_ID / AUTH_CLI_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_CLI_*`\uFF09\uFF1B\u82E5\u6682\u65F6\u65E0\u6CD5\u63D0\u4F9B\uFF0C\u518D\u8865\u9F50 `AUTH_TENANT_CLIENT_ID / AUTH_TENANT_REDIRECT_URI`\uFF08\u517C\u5BB9\u65E7\u540D `LOGTO_TENANT_*`\uFF09\u4F5C\u4E3A\u56DE\u9000\u3002");process7.stdout.write(browserLoginConfig.source==="cli-app"?`\u5F53\u524D\u4F7F\u7528\u4E13\u7528 CLI App \u6267\u884C\u6D4F\u89C8\u5668\u6388\u6743\u7801\u767B\u5F55\uFF0C\u5E76\u81EA\u52A8\u9644\u5E26 consent \u4EE5\u6362\u53D6 refresh token\u3002
2647
2651
  `:`\u672A\u914D\u7F6E\u5B8C\u6574\u4E13\u7528 CLI \u6D4F\u89C8\u5668\u767B\u5F55\u53C2\u6570\uFF0C\u81EA\u52A8\u56DE\u9000\u590D\u7528 workbench \u767B\u5F55\u914D\u7F6E\uFF0C\u5E76\u5F3A\u5236 prompt=login consent\u3002
2648
- `),credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:({authorizationUrl,redirectUri})=>{let opened=tryOpenBrowser2(authorizationUrl);process7.stdout.write((opened?["\u5DF2\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",""]:["\u8BF7\u5728\u6D4F\u89C8\u5668\u5B8C\u6210\u6388\u6743\u7801\u767B\u5F55\u3002",`\u6388\u6743\u5730\u5740: ${authorizationUrl}`,`\u56DE\u8C03\u5730\u5740: ${redirectUri}`,browserLoginConfig.source==="workbench-fallback"?"\u5F53\u524D\u4E3A workbench \u56DE\u9000\u767B\u5F55\uFF0C\u5DF2\u5F3A\u5236 prompt=login consent\uFF1B\u82E5\u56DE\u8C03\u7AEF\u53E3\u88AB\u5360\u7528\uFF0C\u8BF7\u5148\u6682\u65F6\u505C\u6B62\u5BF9\u5E94\u670D\u52A1\u540E\u91CD\u8BD5\u3002":"\u8BF7\u786E\u8BA4\u8BE5\u56DE\u8C03\u5730\u5740\u5DF2\u5728\u4E13\u7528 CLI App \u4E2D\u6CE8\u518C\u3002",""]).join(`
2649
- `))}})}persistCredentials({...credentials,credential_mode:"interactive"});let autoSelectedTenant=null,autoSelectionNote=null;try{let workspaces=await listTenantWorkspaces({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials)});autoSelectedTenant=chooseDefaultTenantWorkspace(workspaces.items),autoSelectedTenant?persistActiveTenantSelection(autoSelectedTenant):workspaces.items.length>1&&(autoSelectionNote="\u68C0\u6D4B\u5230\u591A\u4E2A\u53EF\u7528\u79DF\u6237\uFF0C\u672A\u81EA\u52A8\u5207\u6362\u9ED8\u8BA4\u79DF\u6237\uFF1B\u8BF7\u6267\u884C `platform tenant use <tenant-id>`\u3002")}catch(error){autoSelectionNote=`\u9ED8\u8BA4\u79DF\u6237\u81EA\u52A8\u9009\u62E9\u5931\u8D25\uFF1A${error.message}`}process7.stdout.write(["\u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5DF2\u5199\u5165: ${getCredentialPath()}`,...autoSelectedTenant?[`\u9ED8\u8BA4\u79DF\u6237\u5DF2\u81EA\u52A8\u8BBE\u7F6E: ${autoSelectedTenant.tenant_id} (${autoSelectedTenant.name})`,`\u4E0A\u4E0B\u6587\u5DF2\u5199\u5165: ${getCliContextPath()}`]:autoSelectionNote?[autoSelectionNote]:[],"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami",' 2. \u65B0\u5EFA\u5E94\u7528\uFF1Aplatform app create --tenant <tenant-id> --name "<app-name>" --dir <project-name>'," 3. \u7F16\u8F91\u5DF2\u6709\u5E94\u7528\uFF1Aplatform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," 4. cd <project-name> && platform dev"," 5. \u9ED8\u8BA4\u5148\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1B\u771F\u5B9E build / preview \u8054\u8C03\u5C5E\u4E8E\u9AD8\u7EA7\u8DEF\u5F84",""].join(`
2652
+ `),credentials=await performAuthorizationCodeLogin({issuer,clientId:browserLoginConfig.clientId,redirectUri:browserLoginConfig.redirectUri,audience,scopes,prompt:"login",onPrompt:async({authorizationUrl,redirectUri})=>{let{opened}=await openExternal(authorizationUrl);process7.stdout.write(formatAuthorizationCodeLoginPrompt({opened,authorizationUrl,redirectUri,source:browserLoginConfig.source}))}})}persistCredentials({...credentials,credential_mode:"interactive"});let autoSelectedTenant=null,autoSelectionNote=null;try{let workspaces=await listTenantWorkspaces({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials)});autoSelectedTenant=chooseDefaultTenantWorkspace(workspaces.items),autoSelectedTenant?persistActiveTenantSelection(autoSelectedTenant):workspaces.items.length>1&&(autoSelectionNote="\u68C0\u6D4B\u5230\u591A\u4E2A\u53EF\u7528\u79DF\u6237\uFF0C\u672A\u81EA\u52A8\u5207\u6362\u9ED8\u8BA4\u79DF\u6237\uFF1B\u8BF7\u6267\u884C `platform tenant use <tenant-id>`\u3002")}catch(error){autoSelectionNote=`\u9ED8\u8BA4\u79DF\u6237\u81EA\u52A8\u9009\u62E9\u5931\u8D25\uFF1A${error.message}`}process7.stdout.write(["\u767B\u5F55\u5DF2\u5B8C\u6210\u3002",`\u51ED\u636E\u5DF2\u5199\u5165: ${getCredentialPath()}`,...autoSelectedTenant?[`\u9ED8\u8BA4\u79DF\u6237\u5DF2\u81EA\u52A8\u8BBE\u7F6E: ${autoSelectedTenant.tenant_id} (${autoSelectedTenant.name})`,`\u4E0A\u4E0B\u6587\u5DF2\u5199\u5165: ${getCliContextPath()}`]:autoSelectionNote?[autoSelectionNote]:[],"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. platform whoami",' 2. \u65B0\u5EFA\u5E94\u7528\uFF1Aplatform app create --tenant <tenant-id> --name "<app-name>" --dir <project-name>'," 3. \u7F16\u8F91\u5DF2\u6709\u5E94\u7528\uFF1Aplatform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>"," 4. cd <project-name> && platform dev"," 5. \u9ED8\u8BA4\u5148\u8D70\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF1B\u771F\u5B9E build / preview \u8054\u8C03\u5C5E\u4E8E\u9AD8\u7EA7\u8DEF\u5F84",""].join(`
2650
2653
  `))}async function runWhoAmI(args){let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let tenantId=resolveTenantContext(args),payload=await fetchWhoAmI({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials),tenantId});process7.stdout.write(`${JSON.stringify(payload,null,2)}
2651
2654
  `)}async function runTenant(args){let subcommand=args.rest[0]??"current";if(subcommand==="current"){let context=loadStoredCliContext();if(!context?.active_tenant_id){process7.stdout.write(`\u5F53\u524D\u672A\u8BBE\u7F6E\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\u3002
2652
2655
  `);return}process7.stdout.write([`\u5F53\u524D\u9ED8\u8BA4\u79DF\u6237: ${context.active_tenant_id}`,`\u79DF\u6237\u540D\u79F0: ${context.active_tenant_name??"-"}`,`\u66F4\u65B0\u65F6\u95F4: ${context.updated_at}`,`\u4E0A\u4E0B\u6587\u6587\u4EF6: ${getCliContextPath()}`,""].join(`
@@ -2669,7 +2672,7 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2669
2672
  - `)}`:"\u65B0\u5EFA\u6587\u4EF6: -",result.updatedFiles.length>0?`\u66F4\u65B0\u6587\u4EF6:
2670
2673
  - ${result.updatedFiles.join(`
2671
2674
  - `)}`:"\u66F4\u65B0\u6587\u4EF6: -",`\u8BBF\u95EE\u8DEF\u5F84: ${result.routePath}`,"\u8BF4\u660E: \u8FD9\u662F\u6309\u9700\u8054\u8C03\u7528\u811A\u624B\u67B6\uFF0C\u4E0D\u4F1A\u81EA\u52A8\u51FA\u73B0\u5728\u6B63\u5F0F\u4E1A\u52A1\u9875\u91CC\u3002",""].join(`
2672
- `));return}if(subcommand==="sync-platform-blocks"){let rollback=hasFlag2(args,"rollback"),last=hasFlag2(args,"last");if(rollback&&!last)throw new Error("`platform app sync-platform-blocks --rollback` \u76EE\u524D\u53EA\u652F\u6301 `--last`\u3002");if(hasFlag2(args,"verify")&&!rollback&&!hasFlag2(args,"apply"))throw new Error("`platform app sync-platform-blocks --verify` \u76EE\u524D\u53EA\u652F\u6301\u4E0E `--apply` \u4E00\u8D77\u4F7F\u7528\u3002");let result=runAppSyncPlatformBlocksCommand({cwd:readOption2(args,"dir")??currentInvocationDir(),apply:hasFlag2(args,"apply"),adopt:hasFlag2(args,"adopt"),rollbackLast:rollback&&last,verify:hasFlag2(args,"verify")});process7.stdout.write(formatAppSyncPlatformBlocksResult(result));return}let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId:resolveTenantContext(args),capability:"dashboard",requestClass:"control"});if(subcommand==="create"){let tenantId2=resolveTenantContext(args),displayName=readOption2(args,"name")??args.rest[1];if(!tenantId2||!displayName?.trim())throw new Error("`platform app create` \u9700\u8981 `--tenant` \u6216\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u53CA `--name`\u3002");let templateKey=normalizeAppTemplateOption(readOption2(args,"template"))??DEFAULT_APP_TEMPLATE_KEY,created=await sdk.createTenantApp({name:displayName.trim(),slug:readOption2(args,"slug"),template_key:templateKey});persistCliContext({active_tenant_id:created.tenant_id,selected_app_tenant_id:created.tenant_id,selected_app_id:created.app_id,selected_app_env:"preview",selected_app_name:created.name,selected_app_display_name:created.display_name});let checkout=await checkoutAppWorkspace({sdk,tenantId:created.tenant_id,appId:created.app_id,env:"preview",targetDir:readOption2(args,"dir")});process7.stdout.write([`\u4E91\u7AEF\u5E94\u7528\u5DF2\u521B\u5EFA\uFF1A${created.display_name} (${created.app_id})`,`\u6A21\u677F\uFF1A${created.template_key}`,"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A",` 1. cd ${checkout.targetDir}`," 2. platform dev",""].join(`
2675
+ `));return}if(subcommand==="sync-platform-blocks"){let rollback=hasFlag2(args,"rollback"),last=hasFlag2(args,"last");if(rollback&&!last)throw new Error("`platform app sync-platform-blocks --rollback` \u76EE\u524D\u53EA\u652F\u6301 `--last`\u3002");if(hasFlag2(args,"verify")&&!rollback&&!hasFlag2(args,"apply"))throw new Error("`platform app sync-platform-blocks --verify` \u76EE\u524D\u53EA\u652F\u6301\u4E0E `--apply` \u4E00\u8D77\u4F7F\u7528\u3002");let result=runAppSyncPlatformBlocksCommand({cwd:readOption2(args,"dir")??currentInvocationDir(),apply:hasFlag2(args,"apply"),adopt:hasFlag2(args,"adopt"),rollbackLast:rollback&&last,verify:hasFlag2(args,"verify")});process7.stdout.write(formatAppSyncPlatformBlocksResult(result));return}let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\u3002");let sdk=createControlApiSdk({accessToken:selectApiToken(credentials),tenantId:resolveTenantContext(args),capability:"dashboard",requestClass:"control"});if(subcommand==="create"){let tenantId2=resolveTenantContext(args),displayName=readOption2(args,"name")??args.rest[1];if(!tenantId2||!displayName?.trim())throw new Error("`platform app create` \u9700\u8981 `--tenant` \u6216\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u53CA `--name`\u3002");let templateKey=normalizeAppTemplateOption(readOption2(args,"template"))??DEFAULT_APP_TEMPLATE_KEY,created=await sdk.createTenantApp({name:displayName.trim(),slug:readOption2(args,"slug"),template_key:templateKey});persistCliContext({active_tenant_id:created.tenant_id,selected_app_tenant_id:created.tenant_id,selected_app_id:created.app_id,selected_app_env:"preview",selected_app_name:created.name,selected_app_display_name:created.display_name});let requestedTargetDir=readOption2(args,"dir"),checkout;try{checkout=await checkoutAppWorkspace({sdk,tenantId:created.tenant_id,appId:created.app_id,env:"preview",targetDir:requestedTargetDir})}catch(error){throw formatAppCreateCheckoutError({cause:error,tenantId:created.tenant_id,appId:created.app_id,targetDir:requestedTargetDir})}process7.stdout.write([`\u4E91\u7AEF\u5E94\u7528\u5DF2\u521B\u5EFA\uFF1A${created.display_name} (${created.app_id})`,`\u6A21\u677F\uFF1A${created.template_key}`,"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A",` 1. cd ${checkout.targetDir}`," 2. platform dev",""].join(`
2673
2676
  `));return}if(subcommand==="checkout"){let tenantId2=resolveTenantContext(args),appId2=readOption2(args,"app")??args.rest[1],env2=readOption2(args,"env")??"preview",sourceVersionId=readOption2(args,"source-version");if(!tenantId2||!appId2)throw new Error("`platform app checkout` \u9700\u8981 `--tenant` \u6216\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u53CA `--app`\u3002");persistCliContext({active_tenant_id:tenantId2,selected_app_tenant_id:tenantId2,selected_app_id:appId2,selected_app_env:env2,selected_app_name:appId2});let checkout=await checkoutAppWorkspace({sdk,tenantId:tenantId2,appId:appId2,env:env2,targetDir:readOption2(args,"dir"),sourceVersionId});process7.stdout.write(["\u4E91\u7AEF\u6E90\u7801\u526F\u672C\u5DF2 checkout \u5230\u672C\u5730\u65B0\u76EE\u5F55\u3002","\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A",` 1. cd ${checkout.targetDir}`," 2. platform dev",""].join(`
2674
2677
  `));return}if(subcommand==="submit"){let binding=tryReadCurrentBinding2()?.binding,tenantId2=readOption2(args,"tenant")??binding?.tenant_id??resolveTenantContext(args),appId2=readOption2(args,"app")??binding?.app_id;if(!tenantId2||!appId2)throw new Error("`platform app submit` \u9700\u8981\u5728\u5DF2\u7ED1\u5B9A\u7684\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let checkedAppRoot=findAppRoot(currentInvocationDir());assertSourceWorkspaceCloudUploadPolicy(checkedAppRoot,"platform app submit");let{files,appRoot}=collectSourceWorkspaceFiles(checkedAppRoot),pathBaseViolations=detectPathBaseRuntimeViolations(files);if(readOption2(args,"template"))throw new Error("`platform app submit` \u4E0D\u652F\u6301 `--template`\u3002\u82E5\u4F60\u8981\u57FA\u4E8E\u65B0\u6A21\u677F\u521B\u5EFA\u7248\u672C\uFF0C\u8BF7\u6539\u7528 `platform app version create --template <template-key>`\u3002");if(pathBaseViolations.length>0){let examples=pathBaseViolations.slice(0,8).map(item=>`- ${item.path}:${item.line} ${item.snippet}`).join(`
2675
2678
  `);throw new Error(["\u68C0\u6D4B\u5230 path-base \u9AD8\u98CE\u9669\u5199\u6CD5\uFF0C\u5DF2\u963B\u6B62\u63D0\u4EA4\u3002",'preview/prod \u9ED8\u8BA4\u4EE5\u8DEF\u5F84\u524D\u7F00\u90E8\u7F72\uFF0C\u6D4F\u89C8\u5668\u4FA7\u4E0D\u8981\u76F4\u63A5\u5199\u6839\u76F8\u5BF9\u8DEF\u5F84\uFF0C\u4F8B\u5982 `fetch(\'/api/...\')`\u3001`href="/..."`\u3001`src="/..."`\u3002',"\u8BF7\u6539\u7528 `buildRuntimePath(...)`\u3001`buildAuthUrl(...)`\uFF0C\u6216\u76F8\u5BF9\u8DEF\u5F84 `./api/...`\u3002","\u547D\u4E2D\u793A\u4F8B\uFF1A",examples].join(`
@@ -2695,7 +2698,7 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2695
2698
  `));return;default:process7.stdout.write(["platform app","","\u53EF\u7528\u5B50\u547D\u4EE4\uFF1A"," platform app create"," platform app checkout"," platform app submit"," platform app versions"," platform app status"," platform app diagnose"," platform app preflight"," platform app import preprocess"," platform app import stage"," platform app import merge"," platform app scaffold"," platform app use"," platform app current",""].join(`
2696
2699
  `))}}function printDevHelp(){process7.stdout.write(getDevHelpLines().join(`
2697
2700
  `))}function printLinkHelp(){process7.stdout.write(["platform link","","\u7528\u6CD5\uFF1A"," platform link --tenant <tenant-id> --app <app-id> [--env preview|prod]","","\u9002\u7528\u573A\u666F\uFF1A"," - \u5F53\u524D\u76EE\u5F55\u5DF2\u7ECF\u662F\u4E00\u4E2A\u5E94\u7528\u5DE5\u7A0B\uFF08\u5B58\u5728 `app.yaml`\uFF09\uFF0C\u4F46\u7F3A\u5C11 `.platform/source-context.json`"," - \u4F60\u628A\u5DF2 checkout / \u5DF2\u521D\u59CB\u5316\u7684\u672C\u5730\u5DE5\u7A0B\u79FB\u52A8\u5230\u65B0\u76EE\u5F55\u540E\uFF0C\u9700\u8981\u91CD\u65B0\u7ED1\u5B9A tenant/app/env"," - \u4F60\u8981\u5728\u73B0\u6709\u5DE5\u7A0B\u76EE\u5F55\u4E0A\u624B\u52A8\u5207\u6362\u5230\u53E6\u4E00\u4E2A app \u4E0A\u4E0B\u6587","","\u4E0D\u9002\u7528\u573A\u666F\uFF1A"," - \u5F53\u524D\u76EE\u5F55\u8FD8\u4E0D\u662F\u5E94\u7528\u5DE5\u7A0B\uFF1A\u8BF7\u5148\u6267\u884C `platform app checkout ...` \u6216 `platform init <project-name>`","","\u8BF4\u660E\uFF1A"," - `platform link` \u53EA\u8D1F\u8D23\u628A tenant/app/env \u7ED1\u5B9A\u5230\u5F53\u524D\u5E94\u7528\u76EE\u5F55"," - \u7ED1\u5B9A\u6210\u529F\u540E\u4F1A\u5199\u5165 `.platform/source-context.json`"," - \u7ED1\u5B9A\u5B8C\u6210\u540E\u53EF\u76F4\u63A5\u6267\u884C `platform dev`","","\u793A\u4F8B\uFF1A"," platform link --tenant t-default --app app-demo --env preview",""].join(`
2698
- `))}async function checkoutAppWorkspace(args){let sourceWorkspace=await args.sdk.getTenantAppSourceWorkspace(args.appId,{sourceVersionId:args.sourceVersionId});persistCliContext({active_tenant_id:args.tenantId,selected_app_tenant_id:sourceWorkspace.tenant_id,selected_app_id:sourceWorkspace.app_id,selected_app_env:args.env,selected_app_name:sourceWorkspace.name,selected_app_display_name:sourceWorkspace.display_name});let targetDir=args.targetDir??sourceWorkspace.default_directory,writtenFiles=checkoutSourceWorkspace(targetDir,sourceWorkspace.files,{tenant_id:sourceWorkspace.tenant_id,app_id:sourceWorkspace.app_id,env:args.env,workspace_name:loadStoredCliContext()?.active_tenant_name,app_name:sourceWorkspace.name,app_display_name:sourceWorkspace.display_name,validated_at:new Date().toISOString()});return updateSourceContext(targetDir,{tenant_id:sourceWorkspace.tenant_id,app_id:sourceWorkspace.app_id,env:args.env,workspace_name:loadStoredCliContext()?.active_tenant_name,app_name:sourceWorkspace.name,app_display_name:sourceWorkspace.display_name,template_key:sourceWorkspace.template_key,default_directory:sourceWorkspace.default_directory,generated_from_template:sourceWorkspace.generated_from_template,base_source_version_id:sourceWorkspace.source_version_id,checked_out_at:new Date().toISOString()}),process7.stdout.write([`\u6E90\u7801\u76EE\u5F55: ${targetDir}`,`tenant/app/env: ${sourceWorkspace.tenant_id}/${sourceWorkspace.app_id}/${args.env}`,`\u6A21\u677F: ${sourceWorkspace.template_key}`,`\u6765\u6E90: ${sourceWorkspace.generated_from_template?"template scaffold":`source version ${sourceWorkspace.source_version_id}`}`,`\u5DF2\u5199\u5165\u6587\u4EF6: ${writtenFiles.length}`,""].join(`
2701
+ `))}async function checkoutAppWorkspace(args){let sourceWorkspace=await args.sdk.getTenantAppSourceWorkspace(args.appId,{sourceVersionId:args.sourceVersionId});persistCliContext({active_tenant_id:args.tenantId,selected_app_tenant_id:sourceWorkspace.tenant_id,selected_app_id:sourceWorkspace.app_id,selected_app_env:args.env,selected_app_name:sourceWorkspace.name,selected_app_display_name:sourceWorkspace.display_name});let targetDir=args.targetDir??sourceWorkspace.default_directory,checkedOutAt=new Date().toISOString(),writtenFiles=checkoutSourceWorkspace(targetDir,sourceWorkspace.files,{tenant_id:sourceWorkspace.tenant_id,app_id:sourceWorkspace.app_id,env:args.env,workspace_name:loadStoredCliContext()?.active_tenant_name,app_name:sourceWorkspace.name,app_display_name:sourceWorkspace.display_name,validated_at:checkedOutAt,template_key:sourceWorkspace.template_key,default_directory:sourceWorkspace.default_directory,generated_from_template:sourceWorkspace.generated_from_template,base_source_version_id:sourceWorkspace.source_version_id,checked_out_at:checkedOutAt});return process7.stdout.write([`\u6E90\u7801\u76EE\u5F55: ${targetDir}`,`tenant/app/env: ${sourceWorkspace.tenant_id}/${sourceWorkspace.app_id}/${args.env}`,`\u6A21\u677F: ${sourceWorkspace.template_key}`,`\u6765\u6E90: ${sourceWorkspace.generated_from_template?"template scaffold":`source version ${sourceWorkspace.source_version_id}`}`,`\u5DF2\u5199\u5165\u6587\u4EF6: ${writtenFiles.length}`,""].join(`
2699
2702
  `)),{targetDir}}function runInit(args){let name=args.rest[0]??readOption2(args,"name")??"demo-app",targetDir=readOption2(args,"dir")??name,templateKey=normalizeAppTemplateOption(readOption2(args,"template"))??DEFAULT_APP_TEMPLATE_KEY,createdFiles=initProject(targetDir,name,templateKey),context=loadStoredCliContext(),bindingMessage="\u672A\u68C0\u6D4B\u5230\u5DF2\u9009\u5E94\u7528\u3002\u5F53\u524D\u66F4\u63A8\u8350\u901A\u8FC7 `platform app create ...` \u6216 `platform app checkout --tenant <tenant-id> --app <app-id> --dir <project-name>` \u83B7\u5F97\u5DF2\u7ED1\u5B9A\u76EE\u5F55\uFF1B\u53EA\u6709\u4F60\u660E\u786E\u8981\u5728\u5F53\u524D\u76EE\u5F55\u7EE7\u7EED\u517C\u5BB9\u8DEF\u5F84\u65F6\uFF0C\u518D\u6267\u884C `platform app use --tenant <tenant-id> --app <app-id> --env preview` \u6216\u624B\u52A8 `platform link`\u3002";if(context?.selected_app_tenant_id&&context.selected_app_id){let result=writeBinding(targetDir,{tenant_id:context.selected_app_tenant_id,app_id:context.selected_app_id,env:context.selected_app_env??"preview",workspace_name:context.active_tenant_name,app_name:context.selected_app_name??context.selected_app_id,app_display_name:context.selected_app_display_name,validated_at:new Date().toISOString()});bindingMessage=`\u5DF2\u81EA\u52A8\u7ED1\u5B9A\u5230: ${context.selected_app_tenant_id}/${context.selected_app_id}/${context.selected_app_env??"preview"} (${result.path})`}process7.stdout.write([`\u5DF2\u521D\u59CB\u5316 \`${templateKey}\` \u9879\u76EE\u9AA8\u67B6:`,`- ${createdFiles.join(`
2700
2703
  - `)}`,"",bindingMessage,"","\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A"," 1. \u68C0\u67E5 `.env.example` \u5E76\u8865\u5145\u672C\u5730\u53D8\u91CF"," 2. \u6267\u884C `platform dev` \u8FDB\u5165\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F"," 3. \u82E5\u9700\u5207\u6362\u5E94\u7528\uFF0C\u518D\u6267\u884C `platform app use ...` \u540E\u91CD\u65B0 `platform init` \u6216\u624B\u52A8 `platform link`",""].join(`
2701
2704
  `))}async function runLink(args){if(hasFlag2(args,"help")||hasFlag2(args,"h")){printLinkHelp();return}let tenantId=resolveTenantContext(args),appId=readOption2(args,"app"),env=readOption2(args,"env")??"preview";if(!tenantId||!appId)throw new Error("`platform link` \u9700\u8981 `--app`\uFF0C\u5E76\u4E14\u9700\u8981\u901A\u8FC7 `--tenant`\u3001\u5F53\u524D\u7ED1\u5B9A\u6216 `platform tenant use` \u63D0\u4F9B\u79DF\u6237\u4E0A\u4E0B\u6587\u3002");let credentials=await loadStoredCredentialsEnsuringFresh();if(!credentials)throw new Error("\u672A\u627E\u5230\u672C\u5730\u51ED\u636E\uFF0C\u8BF7\u5148\u6267\u884C `platform login`\uFF0C\u518D\u7ED1\u5B9A\u5F53\u524D\u9879\u76EE\u3002");let overview=await fetchTenantOverview({baseUrl:getControlApiBaseUrl(),accessToken:selectApiToken(credentials),tenantId}),matchedApp=overview.apps.find(item=>item.id===appId);if(!matchedApp)throw new Error(`\u5728\u79DF\u6237 ${tenantId} \u4E0B\u672A\u627E\u5230\u5E94\u7528 ${appId}\uFF0C\u8BF7\u5148\u5728 tenant-workbench \u521B\u5EFA\u5E94\u7528\uFF0C\u6216\u6267\u884C \`platform whoami --tenant ${tenantId}\` \u68C0\u67E5\u5F53\u524D\u4E0A\u4E0B\u6587\u3002`);await createControlApiSdk({accessToken:selectApiToken(credentials),tenantId,capability:"auth",requestClass:"control"}).getWhoAmI();let result=writeBinding(currentInvocationDir(),{tenant_id:tenantId,app_id:appId,env,workspace_name:overview.workspace?.name,app_name:appId,app_display_name:matchedApp.name,validated_at:new Date().toISOString()});process7.stdout.write([`\u7ED1\u5B9A\u5DF2\u5199\u5165: ${result.path}`,`\u5DF2\u7ED1\u5B9A\u5230: ${tenantId}/${appId}/${env}`,`\u5E94\u7528\u5C55\u793A\u540D: ${matchedApp.name}`,"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u6267\u884C `platform dev` \u542F\u52A8\u672C\u5730\u5F00\u53D1\u6001\uFF1B\u771F\u5B9E build / preview \u8054\u8C03\u5C5E\u4E8E\u9AD8\u7EA7\u6A21\u5F0F\u3002",""].join(`
@@ -2703,15 +2706,15 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2703
2706
  `));return}if(subcommand==="preview"){let action=args.rest[1];if(!action||action==="help"){process7.stdout.write(getDevPreviewHelpLines().join(`
2704
2707
  `));return}if(action==="generate"){let credentials=await loadStoredCredentialsEnsuringFresh(),binding=tryReadCurrentBinding2()?.binding,tenantId=readOption2(args,"tenant")??binding?.tenant_id??resolveTenantContext(args),appId=readOption2(args,"app")??binding?.app_id??resolveAppIdFromContext(args,3);if(!tenantId||!appId)throw new Error("`platform dev preview generate` \u9700\u8981\u5728\u5DF2\u7ED1\u5B9A\u7684\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let sdk=createTenantScopedSdk(credentials,tenantId,{capability:"dashboard"}),response=await sdk.createTenantAppDevWorkspacePreview(appId,{...hasFlag2(args,"force-build")?{force_rebuild:!0}:{},...hasFlag2(args,"no-wait")?{}:{wait_for_build:!0}});if("status"in response&&response.status==="building"){process7.stdout.write([...formatDevPreviewLines({title:"\u5DE5\u4F5C\u533A Preview \u6784\u5EFA\u5DF2\u542F\u52A8\u3002",tenantId,appId,buildId:response.build_id,sourceVersionId:response.source_version_id??null}),`status: ${response.build_status}`,response.message,`\u4E0B\u4E00\u6B65: \u6267\u884C \`platform build get ${response.build_id}\` \u8DDF\u8E2A\u6784\u5EFA\uFF1B\u5B8C\u6210\u540E\u53EF\u6267\u884C \`platform dev preview open\`\u3002`,""].join(`
2705
2708
  `));return}let timeline=await sdk.listTenantAppDeploymentTimeline(appId,{limit:10}).catch(()=>({items:[]})),previewItem=findDevPreviewTimelineItem(timeline.items,{deploymentId:response.deployment_id,releaseId:response.release_id});process7.stdout.write([...formatDevPreviewLines({title:"\u5DE5\u4F5C\u533A Preview \u5DF2\u751F\u6210\u3002",tenantId,appId,releaseId:response.release_id,deploymentId:response.deployment_id,buildId:previewItem?.build_id??response.build_id??null,sourceVersionId:previewItem?.source_version_id??response.source_version_id??null,previewUrl:previewItem?.preview_url??response.runtime.preview_url??null,health:previewItem?.health??response.runtime.health??null,healthCheckUrl:previewItem?.health_check_url??null,message:previewItem?.message??response.runtime.message??null,failureReason:previewItem?.failure_reason??response.runtime.failure_reason??null,diagnosticUrl:previewItem?.diagnostic_url??response.runtime.diagnostic_url??null}),"\u4E0B\u4E00\u6B65: \u82E5\u9875\u9762\u5F02\u5E38\uFF0C\u4F18\u5148\u8BB0\u5F55 build/release/deployment/source version\uFF0C\u518D\u6392\u67E5\u5BF9\u5E94\u8BCA\u65AD\u4E0E\u65E5\u5FD7\u3002",""].join(`
2706
- `));return}if(action==="open"){let credentials=await loadStoredCredentialsEnsuringFresh(),binding=tryReadCurrentBinding2()?.binding,tenantId=readOption2(args,"tenant")??binding?.tenant_id??resolveTenantContext(args),appId=readOption2(args,"app")??binding?.app_id??resolveAppIdFromContext(args,3);if(!tenantId||!appId)throw new Error("`platform dev preview open` \u9700\u8981\u5728\u5DF2\u7ED1\u5B9A\u7684\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let sdk=createTenantScopedSdk(credentials,tenantId,{capability:"dashboard"});try{let preview=await sdk.getTenantAppDevWorkspacePreview(appId),timeline=await sdk.listTenantAppDeploymentTimeline(appId,{limit:10}).catch(()=>({items:[]})),previewItem=findDevPreviewTimelineItem(timeline.items,{deploymentId:preview.deployment_id,releaseId:preview.release_id}),opened=tryOpenBrowser2(preview.preview_url);process7.stdout.write([...formatDevPreviewLines({title:"\u5DE5\u4F5C\u533A Preview \u5DF2\u5B9A\u4F4D\u3002",tenantId:preview.tenant_id,appId:preview.app_id,releaseId:preview.release_id,deploymentId:preview.deployment_id,buildId:previewItem?.build_id??preview.build_id??null,sourceVersionId:previewItem?.source_version_id??preview.source_version_id??null,previewUrl:preview.preview_url,health:previewItem?.health??preview.health??null,healthCheckUrl:previewItem?.health_check_url??null,message:previewItem?.message??null,failureReason:previewItem?.failure_reason??null,diagnosticUrl:previewItem?.diagnostic_url??null}),opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u3002":"\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u590D\u5236 preview_url\u3002",""].join(`
2709
+ `));return}if(action==="open"){let credentials=await loadStoredCredentialsEnsuringFresh(),binding=tryReadCurrentBinding2()?.binding,tenantId=readOption2(args,"tenant")??binding?.tenant_id??resolveTenantContext(args),appId=readOption2(args,"app")??binding?.app_id??resolveAppIdFromContext(args,3);if(!tenantId||!appId)throw new Error("`platform dev preview open` \u9700\u8981\u5728\u5DF2\u7ED1\u5B9A\u7684\u5E94\u7528\u76EE\u5F55\u6267\u884C\uFF0C\u6216\u663E\u5F0F\u4F20\u5165 `--tenant` \u4E0E `--app`\u3002");let sdk=createTenantScopedSdk(credentials,tenantId,{capability:"dashboard"});try{let preview=await sdk.getTenantAppDevWorkspacePreview(appId),timeline=await sdk.listTenantAppDeploymentTimeline(appId,{limit:10}).catch(()=>({items:[]})),previewItem=findDevPreviewTimelineItem(timeline.items,{deploymentId:preview.deployment_id,releaseId:preview.release_id}),{opened}=await openExternal(preview.preview_url);process7.stdout.write([...formatDevPreviewLines({title:"\u5DE5\u4F5C\u533A Preview \u5DF2\u5B9A\u4F4D\u3002",tenantId:preview.tenant_id,appId:preview.app_id,releaseId:preview.release_id,deploymentId:preview.deployment_id,buildId:previewItem?.build_id??preview.build_id??null,sourceVersionId:previewItem?.source_version_id??preview.source_version_id??null,previewUrl:preview.preview_url,health:previewItem?.health??preview.health??null,healthCheckUrl:previewItem?.health_check_url??null,message:previewItem?.message??null,failureReason:previewItem?.failure_reason??null,diagnosticUrl:previewItem?.diagnostic_url??null}),opened?"\u5DF2\u5C1D\u8BD5\u5728\u9ED8\u8BA4\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u3002":"\u672A\u80FD\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u8BF7\u624B\u52A8\u590D\u5236 preview_url\u3002",""].join(`
2707
2710
  `))}catch(error){throw error instanceof PlatformApiError&&(error.code==="dev_workspace_preview_not_found"||error.code==="dev_workspace_preview_not_current"||error.code==="dev_workspace_preview_not_ready")?new Error([error.message,"\u4E0B\u4E00\u6B65\u5EFA\u8BAE\uFF1A\u5148\u6267\u884C `platform dev preview generate`\uFF1B\u5982\u679C\u5F53\u524D Preview \u5DF2\u88AB\u6B63\u5F0F\u7248\u672C\u66FF\u6362\uFF0C\u9700\u8981\u91CD\u65B0\u751F\u6210\u5DE5\u4F5C\u533A Preview\u3002"].join(`
2708
2711
  `)):error}return}throw new Error(`\u672A\u77E5 dev preview \u5B50\u547D\u4EE4: ${action}`)}let target=readOption2(args,"target"),initialRuntime=collectDevPreflight(process7.cwd(),target),runtimeBindings={},bindingWarnings=[],cleanupRemoteBindings=null,remoteBindingsValue=args.options["remote-bindings"],enableRemoteBindings=remoteBindingsValue===!0||typeof remoteBindingsValue=="string",requestedRemoteBindings=enableRemoteBindings?resolveRequestedRemoteBindings(args):null;if(enableRemoteBindings)if((requestedRemoteBindings?.capabilities.length??0)===0)bindingWarnings.push(requestedRemoteBindings?.mode==="auto"?"\u5DF2\u542F\u7528 `--remote-bindings`\uFF0C\u4F46\u5F53\u524D\u5DE5\u4F5C\u533A\u672A\u68C0\u6D4B\u5230\u771F\u5B9E DB migration\uFF1B\u672C\u6B21\u8DF3\u8FC7\u8FDC\u7AEF DB binding\u3002\u82E5\u4F60\u786E\u8BA4\u9700\u8981\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u53EF\u663E\u5F0F\u6267\u884C `platform dev --remote-bindings=db`\u3002":"\u5DF2\u542F\u7528 `--remote-bindings`\uFF0C\u4F46\u5F53\u524D\u672A\u8BF7\u6C42\u4EFB\u4F55\u53EF\u7528\u7684\u8FDC\u7AEF binding\u3002");else try{let remoteBindings=await loadRemoteDbRuntimeBindings(initialRuntime.binding,requestedRemoteBindings.capabilities);runtimeBindings=remoteBindings.values;let preparedBindings=await prepareLocalDevDatabaseBindings(runtimeBindings,{sshHost:process7.env.TEST_ENV_SSH_HOST});runtimeBindings=preparedBindings.bindings,cleanupRemoteBindings=async()=>{await preparedBindings.cleanup?.(),await remoteBindings.cleanup?.()},bindingWarnings.push(...preparedBindings.warnings)}catch(error){bindingWarnings.push(error instanceof Error?`\u8FDC\u7AEF DB binding \u62C9\u53D6\u5931\u8D25\uFF0C\u5C06\u56DE\u9000\u5230\u672C\u5730\u73AF\u5883\u53D8\u91CF\uFF1A${error.message}`:"\u8FDC\u7AEF DB binding \u62C9\u53D6\u5931\u8D25\uFF0C\u5C06\u56DE\u9000\u5230\u672C\u5730\u73AF\u5883\u53D8\u91CF\u3002")}else bindingWarnings.push("\u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\u9ED8\u8BA4\u4E0D\u4E3B\u52A8\u62C9\u53D6\u8FDC\u7AEF binding\uFF1B\u5982\u9700\u6309\u5DE5\u4F5C\u533A\u58F0\u660E\u81EA\u52A8\u5C1D\u8BD5\u8FDC\u7AEF\u80FD\u529B\uFF0C\u8BF7\u6267\u884C `platform dev --remote-bindings`\uFF1B\u5982\u9700\u663E\u5F0F\u8054\u8C03\u5E73\u53F0 DB\uFF0C\u8BF7\u6267\u884C `platform dev --remote-bindings=db`\u3002");let runtime=collectDevPreflight(process7.cwd(),target,runtimeBindings),autoRestartEnabled=runtime.manifest.dev.auto_restart===!0,hasLocalPageRenderRegistry=existsSync24(`${runtime.cwd}/page-render/registry.json`),recommendedDevCommand=enableRemoteBindings?null:recommendDevCommandForTemplate(runtime.templateKey,{requestedRemoteBindings:requestedRemoteBindings?.capabilities??[]}),dependencyInstallWarning=await ensureLocalDevDependencies(runtime.cwd),explicitPort=typeof process7.env.PORT=="string"&&process7.env.PORT.trim().length>0,explicitBaseUrl=typeof process7.env.PUBLIC_APP_BASE_URL=="string"&&process7.env.PUBLIC_APP_BASE_URL.trim().length>0||typeof runtimeBindings.PUBLIC_APP_BASE_URL=="string"&&runtimeBindings.PUBLIC_APP_BASE_URL.trim().length>0;if(!explicitPort&&!explicitBaseUrl){let preferredPort=Number(runtime.manifest.entry.port||3e3),resolvedPort=await resolveAvailableLocalDevPort(preferredPort);resolvedPort.reusedPreferred||(runtime.env.PORT=String(resolvedPort.port),runtime.env.PUBLIC_APP_BASE_URL=`http://127.0.0.1:${resolvedPort.port}`,runtime.healthcheckUrl=`http://localhost:${resolvedPort.port}${runtime.manifest.entry.health_check||"/healthz"}`,runtime.warnings=runtime.warnings.map(warning=>warning.startsWith("\u672A\u663E\u5F0F\u914D\u7F6E PUBLIC_APP_BASE_URL\uFF1B\u672C\u5730 dev \u5DF2\u4E34\u65F6\u56DE\u9000\u4E3A ")?`\u672A\u663E\u5F0F\u914D\u7F6E PUBLIC_APP_BASE_URL\uFF1B\u672C\u5730 dev \u5DF2\u4E34\u65F6\u56DE\u9000\u4E3A ${runtime.env.PUBLIC_APP_BASE_URL}\u3002`:warning),runtime.warnings.unshift(`\u68C0\u6D4B\u5230\u672C\u5730\u7AEF\u53E3 ${preferredPort} \u5DF2\u88AB\u5360\u7528\uFF1BCLI \u5DF2\u81EA\u52A8\u56DE\u9000\u5230\u53EF\u7528\u7AEF\u53E3 ${resolvedPort.port}\u3002\u82E5\u4F60\u8981\u56FA\u5B9A\u7AEF\u53E3\uFF0C\u8BF7\u663E\u5F0F\u8BBE\u7F6E \`PORT\` \u4E0E \`PUBLIC_APP_BASE_URL\`\u3002`))}hasLocalPageRenderRegistry&&(runtime.warnings.unshift("\u68C0\u6D4B\u5230 `page-render/registry.json`\uFF1A\u672C\u5730 `platform dev` \u4E0B\uFF0C\u5DF2\u6CE8\u518C\u9875\u9762\u8DEF\u7531\u4F1A\u4F18\u5148\u6620\u5C04\u5230\u672C\u5730 HTML \u6A21\u677F\uFF0C\u7528\u4E8E\u7ED3\u6784/\u6837\u5F0F/\u57FA\u7840\u4EA4\u4E92\u9884\u89C8\uFF1B\u6B63\u5F0F\u9996\u5C4F HTML \u4ECD\u4EE5 preview / prod \u7684\u5E73\u53F0\u9875\u9762\u6E32\u67D3\u7ED3\u679C\u4E3A\u51C6\u3002"),enableRemoteBindings&&runtime.warnings.unshift("`platform dev --remote-bindings` \u53EA\u589E\u5F3A\u5E73\u53F0 API / Auth / CMS / DB \u7B49\u8054\u8C03\u80FD\u529B\uFF0C\u4E0D\u4F1A\u628A\u672C\u5730 dev \u5207\u6362\u6210\u5E73\u53F0\u670D\u52A1\u7AEF HTML \u6E32\u67D3\u3002")),enableRemoteBindings&&(bindingWarnings.push(`\u5DF2\u542F\u7528 \`--remote-bindings\`\uFF1ACLI \u4F1A\u6CE8\u5165\u771F\u5B9E\u5E73\u53F0\u7ED1\u5B9A\uFF0C\u5E76\u6CBF\u7528\u4E0E \`platform dev\` \u76F8\u540C\u7684${autoRestartEnabled?"\u81EA\u52A8\u91CD\u542F":"\u5355\u6B21\u542F\u52A8"}\u6A21\u5F0F\u3002`),bindingWarnings.push("\u82E5\u8054\u8C03 CMS / DB / Auth \u4ECD\u5F02\u5E38\uFF0C\u4F18\u5148\u6267\u884C `platform app diagnose --env preview` \u786E\u8BA4\u76EE\u6807\u5E94\u7528\u5F53\u524D\u72B6\u6001\u3002")),runtime.warnings.unshift(...bindingWarnings),dependencyInstallWarning&&runtime.warnings.unshift(dependencyInstallWarning);let hasLocalCredentials=!!loadStoredCredentials();process7.stdout.write(["dev preflight \u901A\u8FC7\u3002","\u6A21\u5F0F: \u8F7B\u91CF\u5F00\u53D1\u6A21\u5F0F\uFF08\u9ED8\u8BA4\uFF09",`tenant/app/env: ${runtime.binding.tenant_id}/${runtime.binding.app_id}/${runtime.binding.env}`,"\u4E0A\u4E0B\u6587\u6765\u6E90: \u5F53\u524D\u76EE\u5F55 .platform/source-context.json",`CLI \u767B\u5F55\u6001: ${hasLocalCredentials?"\u5DF2\u68C0\u6D4B\u5230\u672C\u5730\u51ED\u636E":"\u672A\u68C0\u6D4B\u5230\u672C\u5730\u51ED\u636E\uFF08\u4EC5\u672C\u5730\u9875\u9762\u5F00\u53D1\u53EF\u7EE7\u7EED\uFF1B\u82E5\u9700\u63A7\u5236\u9762\u80FD\u529B\u8BF7\u5148\u6267\u884C `platform login`\uFF09"}`,`\u5DE5\u4F5C\u76EE\u5F55: ${runtime.cwd}`,`\u542F\u52A8\u547D\u4EE4: ${runtime.command}`,`\u5EFA\u8BAE\u547D\u4EE4: ${recommendedDevCommand||"\u4FDD\u6301\u5F53\u524D `platform dev` \u5373\u53EF"}`,autoRestartEnabled?`\u6587\u4EF6\u76D1\u542C\u76EE\u5F55: ${runtime.cwd}`:"\u6587\u4EF6\u76D1\u542C\u76EE\u5F55: \u672A\u542F\u7528\uFF08\u9700\u5728 app.yaml \u4E2D\u663E\u5F0F\u914D\u7F6E `dev.auto_restart: true`\uFF09",runtime.previewAddressMayChange?`\u672C\u5730\u9884\u89C8\u5730\u5740: \u542F\u52A8\u540E\u4EE5 dev server \u5B9E\u9645\u8F93\u51FA\u4E3A\u51C6\uFF08\u5F53\u524D\u9884\u671F ${runtime.env.PUBLIC_APP_BASE_URL||"-"}\uFF09`:`\u672C\u5730\u9884\u89C8\u5730\u5740: ${runtime.env.PUBLIC_APP_BASE_URL||"-"}`,`\u5065\u5EB7\u68C0\u67E5: ${runtime.healthcheckUrl}`,"\u4E91\u7AEF Preview: \u5982\u9700\u751F\u6210\u4E91\u7AEF\u53EF\u5206\u4EAB\u5730\u5740\uFF0C\u8BF7\u6267\u884C `platform preview generate`\uFF1B\u82E5\u4F60\u8D70\u7684\u662F Dev Workspace \u8054\u8C03\u94FE\u8DEF\uFF0C\u518D\u6267\u884C `platform dev preview generate`\u3002",runtime.warnings.length>0?`\u63D0\u793A:
2709
2712
  - ${runtime.warnings.join(`
2710
2713
  - `)}`:`\u63D0\u793A:
2711
2714
  - \u65E0`,"\u9AD8\u7EA7\u6A21\u5F0F\u63D0\u793A: \u82E5\u4F60\u8981\u9A8C\u8BC1\u5E73\u53F0\u539F\u751F\u6784\u5EFA\u3001\u771F\u5B9E preview\u3001rollback\uFF0C\u8BF7\u6539\u8D70\u5B8C\u6574\u8054\u8C03\u73AF\u5883\u3002",""].join(`
2712
2715
  `));try{autoRestartEnabled?await runDevSupervisor({command:runtime.command,cwd:runtime.cwd,env:runtime.env,watchRoot:runtime.cwd,onWatching:message=>{process7.stdout.write(`[dev] ${message}
2713
- `)}}):await runSingleDevProcess(runtime.command,runtime.cwd,runtime.env)}finally{await cleanupRemoteBindings?.()}}async function runSingleDevProcess(command,cwd,env){await new Promise((resolve16,reject)=>{let child=spawn8(command,{cwd,env,stdio:"inherit",shell:!0});child.on("error",error=>{reject(error instanceof Error?error:new Error(String(error)))}),child.on("exit",(code2,signal)=>{if(signal){reject(new Error(`dev \u547D\u4EE4\u88AB\u4FE1\u53F7 ${signal} \u7EC8\u6B62`));return}if(code2&&code2!==0){reject(new Error(`dev \u547D\u4EE4\u9000\u51FA\uFF0C\u72B6\u6001\u7801 ${code2}`));return}resolve16()})})}async function ensureLocalDevDependencies(cwd){let installPlan=detectLocalDependencyInstallPlan(cwd);if(!installPlan)return null;let renderedCommand=[installPlan.command,...installPlan.args].join(" ");return process7.stdout.write(`\u68C0\u6D4B\u5230\u5F53\u524D\u5DE5\u4F5C\u533A\u7F3A\u5C11 node_modules\uFF1B\u6B63\u5728\u6309 ${installPlan.lockfile} \u6267\u884C\u4F9D\u8D56\u5B89\u88C5\uFF1A${renderedCommand}
2714
- `),await new Promise((resolve16,reject)=>{let child=spawn8(installPlan.command,installPlan.args,{cwd,env:process7.env,stdio:"inherit",shell:!1});child.on("error",error=>{reject(error instanceof Error?error:new Error(String(error)))}),child.on("exit",(code2,signal)=>{if(signal){reject(new Error(`\u4F9D\u8D56\u5B89\u88C5\u88AB\u4FE1\u53F7 ${signal} \u7EC8\u6B62`));return}if(code2&&code2!==0){reject(new Error(`\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u72B6\u6001\u7801 ${code2}`));return}resolve16()})}),`\u68C0\u6D4B\u5230\u5F53\u524D\u5DE5\u4F5C\u533A\u7F3A\u5C11 node_modules\uFF1BCLI \u5DF2\u6309 ${installPlan.lockfile} \u81EA\u52A8\u5B8C\u6210\u4F9D\u8D56\u5B89\u88C5\u3002`}async function runAuth(args){let subcommand=args.rest[0]??"discover";if(hasFlag2(args,"help")||hasFlag2(args,"h")){printAuthHelp(args.rest[0]??"");return}if(!["discover","configure","bind","inspect","role","user-role"].includes(subcommand))throw new Error(`\u672A\u77E5 auth \u5B50\u547D\u4EE4: ${subcommand}`);let credentials=await loadStoredCredentialsEnsuringFresh(),tenantId=resolveTenantContext(args),appId=resolveAppIdFromContext(args);if(!tenantId||!appId)throw new Error("`platform auth` \u9700\u8981 `--tenant` \u6216\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u53CA `--app`\u3001\u5F53\u524D\u76EE\u5F55\u7ED1\u5B9A\u6216\u5DF2\u9009\u5E94\u7528\u4E0A\u4E0B\u6587\u3002");let sdk=createTenantScopedSdk(credentials,tenantId,{capability:"end_user_auth"}),jsonMode=args.options.json===!0;if(subcommand==="role"){let action2=args.rest[1]??"list";if(!["list","create","inspect","update"].includes(action2))throw new Error(`\u672A\u77E5 auth role \u5B50\u547D\u4EE4: ${action2}`);if(action2==="list"){let response3=await sdk.listTenantAppEndUserRoles(appId);if(jsonMode){process7.stdout.write(`${JSON.stringify(response3,null,2)}
2716
+ `)}}):await runSingleDevProcess(runtime.command,runtime.cwd,runtime.env)}finally{await cleanupRemoteBindings?.()}}async function runSingleDevProcess(command,cwd,env){await runDevSupervisor({command,cwd,env})}async function ensureLocalDevDependencies(cwd){let installPlan=detectLocalDependencyInstallPlan(cwd);if(!installPlan)return null;let renderedCommand=[installPlan.command,...installPlan.args].join(" ");return process7.stdout.write(`\u68C0\u6D4B\u5230\u5F53\u524D\u5DE5\u4F5C\u533A\u7F3A\u5C11 node_modules\uFF1B\u6B63\u5728\u6309 ${installPlan.lockfile} \u6267\u884C\u4F9D\u8D56\u5B89\u88C5\uFF1A${renderedCommand}
2717
+ `),await new Promise((resolve17,reject)=>{let child=spawn5(installPlan.command,installPlan.args,{cwd,env:process7.env,stdio:"inherit",shell:!1});child.on("error",error=>{reject(error instanceof Error?error:new Error(String(error)))}),child.on("exit",(code2,signal)=>{if(signal){reject(new Error(`\u4F9D\u8D56\u5B89\u88C5\u88AB\u4FE1\u53F7 ${signal} \u7EC8\u6B62`));return}if(code2&&code2!==0){reject(new Error(`\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25\uFF0C\u72B6\u6001\u7801 ${code2}`));return}resolve17()})}),`\u68C0\u6D4B\u5230\u5F53\u524D\u5DE5\u4F5C\u533A\u7F3A\u5C11 node_modules\uFF1BCLI \u5DF2\u6309 ${installPlan.lockfile} \u81EA\u52A8\u5B8C\u6210\u4F9D\u8D56\u5B89\u88C5\u3002`}async function runAuth(args){let subcommand=args.rest[0]??"discover";if(hasFlag2(args,"help")||hasFlag2(args,"h")){printAuthHelp(args.rest[0]??"");return}if(!["discover","configure","bind","inspect","role","user-role"].includes(subcommand))throw new Error(`\u672A\u77E5 auth \u5B50\u547D\u4EE4: ${subcommand}`);let credentials=await loadStoredCredentialsEnsuringFresh(),tenantId=resolveTenantContext(args),appId=resolveAppIdFromContext(args);if(!tenantId||!appId)throw new Error("`platform auth` \u9700\u8981 `--tenant` \u6216\u9ED8\u8BA4\u79DF\u6237\u4E0A\u4E0B\u6587\uFF0C\u4EE5\u53CA `--app`\u3001\u5F53\u524D\u76EE\u5F55\u7ED1\u5B9A\u6216\u5DF2\u9009\u5E94\u7528\u4E0A\u4E0B\u6587\u3002");let sdk=createTenantScopedSdk(credentials,tenantId,{capability:"end_user_auth"}),jsonMode=args.options.json===!0;if(subcommand==="role"){let action2=args.rest[1]??"list";if(!["list","create","inspect","update"].includes(action2))throw new Error(`\u672A\u77E5 auth role \u5B50\u547D\u4EE4: ${action2}`);if(action2==="list"){let response3=await sdk.listTenantAppEndUserRoles(appId);if(jsonMode){process7.stdout.write(`${JSON.stringify(response3,null,2)}
2715
2718
  `);return}printAppRoleList(response3.items);return}if(action2==="create"){let roleKey2=readOption2(args,"key"),displayName=readOption2(args,"name");if(!roleKey2||!displayName)throw new Error("`platform auth role create` \u9700\u8981 `--key <role-key>` \u548C `--name <display-name>`\u3002");let response3=await sdk.createTenantAppEndUserRole(appId,{role_key:roleKey2,display_name:displayName,description:readOption2(args,"description"),status:normalizeAppRoleStatus(readOption2(args,"status"))});if(jsonMode){process7.stdout.write(`${JSON.stringify(response3,null,2)}
2716
2719
  `);return}printAppRoleDetail(response3);return}let roleKey=readOption2(args,"role");if(!roleKey)throw new Error("`platform auth role inspect/update` \u9700\u8981 `--role <role-key>`\u3002");if(action2==="inspect"){let response3=await sdk.getTenantAppEndUserRole(appId,roleKey);if(jsonMode){process7.stdout.write(`${JSON.stringify(response3,null,2)}
2717
2720
  `);return}printAppRoleDetail(response3);return}let hasDescription=Object.prototype.hasOwnProperty.call(args.options,"description"),clearDescription=hasFlag2(args,"clear-description"),payload={display_name:readOption2(args,"name"),description:clearDescription?null:hasDescription?readOption2(args,"description")??null:void 0,status:normalizeAppRoleStatus(readOption2(args,"status"))};if(payload.display_name===void 0&&payload.description===void 0&&payload.status===void 0)throw new Error("`platform auth role update` \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u53D8\u66F4\u53C2\u6570\uFF1A`--name`\u3001`--description`\u3001`--clear-description` \u6216 `--status`\u3002");let response2=await sdk.updateTenantAppEndUserRole(appId,roleKey,payload);if(jsonMode){process7.stdout.write(`${JSON.stringify(response2,null,2)}
@@ -2730,8 +2733,8 @@ ${normalized}`}function countExecutableSqlStatements(sql){return stripSqlComment
2730
2733
  `);return}printCmsImportUrlOutput(importPayload);return}let markdownPath=args.rest[2];if(!markdownPath)throw new Error("`platform cms import markdown` \u9700\u8981 <file-or-dir-path>\u3002");let collection=readOption2(args,"collection")??"article",itemIdOption=readOption2(args,"item-id"),itemIdPrefixOption=readOption2(args,"item-id-prefix"),categoryIdOption=readOption2(args,"category-id"),categoryPathOption=readOption2(args,"category-path"),tagsOption=readOption2(args,"tags"),coverAssetIdOption=readOption2(args,"cover-asset-id"),dryRun=hasFlag2(args,"dry-run"),skipExisting=hasFlag2(args,"skip-existing"),publishShortcut=hasFlag2(args,"publish");if(categoryIdOption&&categoryPathOption)throw new Error("`platform cms import markdown` \u4E0D\u80FD\u540C\u65F6\u6307\u5B9A `--category-id` \u548C `--category-path`\u3002");if(itemIdOption&&itemIdPrefixOption)throw new Error("`platform cms import markdown` \u4E0D\u80FD\u540C\u65F6\u6307\u5B9A `--item-id` \u548C `--item-id-prefix`\u3002");if(publishShortcut&&readOption2(args,"publish-status")!==void 0)throw new Error("`platform cms import markdown` \u4E0D\u80FD\u540C\u65F6\u6307\u5B9A `--publish` \u548C `--publish-status`\u3002");let publishStatus=(()=>{let status=readOption2(args,"publish-status");if(status!==void 0){if(status==="draft"||status==="published"||status==="archived")return status;throw new Error("\u65E0\u6548\u7684 `--publish-status`\uFF0C\u4EC5\u652F\u6301 `draft`\u3001`published`\u3001`archived`\u3002")}})(),sources=collectMarkdownImportSources(markdownPath,hasFlag2(args,"recursive"));if(sources.length===0)throw new Error(`\u672A\u5728\u76EE\u6807\u8DEF\u5F84\u4E2D\u627E\u5230 Markdown \u6587\u4EF6\uFF1A${markdownPath}`);let isBatch=sources.length>1;if(isBatch){let disallowedOptions=["item-id","title","slug","summary"].filter(key=>readOption2(args,key)!==void 0);if(disallowedOptions.length>0)throw new Error(`\u76EE\u5F55\u6279\u91CF\u5BFC\u5165\u4E0D\u652F\u6301\u8FD9\u4E9B\u5355\u6761\u8986\u76D6\u53C2\u6570\uFF1A${disallowedOptions.map(key=>`--${key}`).join("\u3001")}\u3002`)}let resolvedCategoryId=categoryIdOption??null,categoryPlan=null,ensureCategoryId=null;if(categoryPathOption){let discover=await sdk.discoverTenantCmsCollection(collection),segments=parseCmsCategoryPath(categoryPathOption);dryRun?(categoryPlan=planCmsCategoryPath({categories:discover.categories,segments}),resolvedCategoryId=categoryPlan.finalNode?.id??null):ensureCategoryId=async()=>(await ensureCmsCategoryPath({categories:discover.categories,segments,createCategory:async(segment,parentId)=>sdk.configureTenantCmsCategory({collection,node:{name:segment.name,slug:segment.slug,parent_id:parentId}})})).finalNode.id}let coverFieldName="cover",coverField=null,coverAssetResponse=null,schemaFields=null;if(coverAssetIdOption){let[schemaResponse,assetResponse]=await Promise.all([sdk.inspectTenantCmsSchema(collection),sdk.getTenantAsset(coverAssetIdOption)]),schema=schemaResponse.draft_schema??schemaResponse.active_schema;if(!schema)throw new Error(`Collection \`${collection}\` has no schema.`);if(coverField=resolveCmsAttachAssetField(schema.fields,coverFieldName),coverField.type!=="image")throw new Error("`platform cms import markdown --cover-asset-id` \u5F53\u524D\u4EC5\u652F\u6301\u6302\u5230\u5355\u56FE `cover` \u5B57\u6BB5\u3002");if(assetResponse.asset.media_type!=="image")throw new Error("`platform cms import markdown --cover-asset-id` \u5F53\u524D\u4EC5\u652F\u6301\u56FE\u7247\u7D20\u6750\u3002");schemaFields=schema.fields,coverAssetResponse=assetResponse}let preparedItems=sources.map(source=>{let itemId=itemIdOption??(itemIdPrefixOption?inferItemIdFromPrefix(itemIdPrefixOption,source.sourcePath):void 0),payload=buildMarkdownItemPayload({collection,markdownPath:source.sourcePath,markdownContent:readFileSync26(source.absolutePath,"utf8"),itemId,title:isBatch?void 0:readOption2(args,"title"),slug:isBatch?void 0:readOption2(args,"slug"),summary:isBatch?void 0:readOption2(args,"summary"),tags:tagsOption===void 0?void 0:readCsvOption3(args,"tags"),categoryId:resolvedCategoryId,publishStatus:publishShortcut?"draft":publishStatus,importedBy:readOption2(args,"imported-by")??"ide-agent"});return{source,payload,lookup:resolveMarkdownImportLookupKey(payload),warnings:[]}}),existingMatches=new Map;if(skipExisting)for(let preparedItem of preparedItems){let existing=await findExistingTenantCmsItemForImport({sdk,collection,lookup:preparedItem.lookup});existing&&existingMatches.set(preparedItem.source.sourcePath,existing)}if(!dryRun&&ensureCategoryId&&preparedItems.some(preparedItem=>!existingMatches.has(preparedItem.source.sourcePath))){resolvedCategoryId=await ensureCategoryId();for(let preparedItem of preparedItems)preparedItem.payload.system.category_id=resolvedCategoryId}let reservedSlugs=new Set;for(let preparedItem of preparedItems){let existing=existingMatches.get(preparedItem.source.sourcePath);if(existing){existing.item.system.slug&&reservedSlugs.add(existing.item.system.slug);continue}if(!preparedItem.payload.system.slug)continue;let resolvedSlug=await resolveUniqueTenantCmsSlug({sdk,collection,slug:preparedItem.payload.system.slug,itemId:preparedItem.payload.item_id,reservedSlugs});resolvedSlug.slug&&(resolvedSlug.adjusted&&preparedItem.warnings.push(`slug \`${resolvedSlug.originalSlug}\` \u5DF2\u5B58\u5728\uFF0C\u5DF2\u81EA\u52A8\u8C03\u6574\u4E3A \`${resolvedSlug.slug}\``),preparedItem.payload.system.slug=resolvedSlug.slug,reservedSlugs.add(resolvedSlug.slug))}if(dryRun){let plannedItems=preparedItems.map(({source,payload,warnings})=>{let existing=existingMatches.get(source.sourcePath),skipped=!!existing,state=skipped?"skipped":"planned";return{source_path:source.sourcePath,item_id:existing?.item.system.id??payload.item_id??null,item_id_source:skipped?existing.matchedBy:payload.item_id?"cli":"server-generated",slug:payload.system.slug??null,title:typeof payload.content.title=="string"?payload.content.title:null,publish_status:skipped?existing?.item.system.publish_status??payload.system.publish_status:publishShortcut?"published":payload.system.publish_status,tags:payload.system.tags??[],category_id:payload.system.category_id??null,state,matched_by:existing?.matchedBy??null,warnings,actions:skipped?["skip_existing"]:["configure_item",...coverField&&coverAssetResponse?["attach_cover_asset"]:[],...publishShortcut?["publish"]:[]]}}),dryRunOutput=isBatch?{dry_run:!0,mode:"batch",import:{source_type:"markdown",source_path:markdownPath,recursive:hasFlag2(args,"recursive"),collection},category_path_plan:categoryPathOption?{path:categoryPathOption,final_category_id:categoryPlan?.finalNode?.id??null,nodes:categoryPlan?.plannedNodes??[]}:null,cover_attachment:coverField&&coverAssetResponse?{field:coverField.name,asset_id:coverAssetResponse.asset.asset_id,title:coverAssetResponse.asset.title,mode:"replace"}:null,skip_existing:skipExisting,publish_after_import:publishShortcut,summary:summarizeMarkdownImportResults(plannedItems),items:plannedItems}:{dry_run:!0,import:{source_type:"markdown",source_path:plannedItems[0].source_path,collection},category_path_plan:categoryPathOption?{path:categoryPathOption,final_category_id:categoryPlan?.finalNode?.id??null,nodes:categoryPlan?.plannedNodes??[]}:null,cover_attachment:coverField&&coverAssetResponse?{field:coverField.name,asset_id:coverAssetResponse.asset.asset_id,title:coverAssetResponse.asset.title,mode:"replace"}:null,skip_existing:skipExisting,publish_after_import:publishShortcut,item:plannedItems[0]};if(jsonMode){process7.stdout.write(`${JSON.stringify(dryRunOutput,null,2)}
2731
2734
  `);return}if(isBatch){printCmsImportMarkdownDryRunBatchOutput({collection,sourcePath:markdownPath,total:plannedItems.length,summary:summarizeMarkdownImportResults(plannedItems),items:plannedItems,skipExisting,publishShortcut,categoryPath:categoryPathOption,categoryPlan,coverFieldName:coverField?.name,coverAssetTitle:coverAssetResponse?.asset.title});return}printCmsImportMarkdownDryRunOutput({collection,sourcePath:plannedItems[0].source_path,itemId:plannedItems[0].item_id,itemIdSource:plannedItems[0].item_id_source,slug:plannedItems[0].slug,title:plannedItems[0].title,publishStatus:plannedItems[0].publish_status,tags:plannedItems[0].tags,categoryId:plannedItems[0].category_id,state:plannedItems[0].state,matchedBy:plannedItems[0].matched_by,categoryPath:categoryPathOption,categoryPlan,coverFieldName:coverField?.name,coverAssetTitle:coverAssetResponse?.asset.title,warnings:plannedItems[0].warnings});return}let importedItems=[];for(let{source,payload,warnings}of preparedItems){let existing=existingMatches.get(source.sourcePath);if(existing){importedItems.push({source_path:source.sourcePath,item_id:existing.item.system.id??payload.item_id??"(existing-item)",slug:existing.item.system.slug??payload.system.slug??null,publish_status:existing.item.system.publish_status??payload.system.publish_status,state:"skipped",matched_by:existing.matchedBy,warnings});continue}let response=await sdk.configureTenantCmsItem(payload);if(coverField&&coverAssetResponse&&schemaFields){let itemResponse=await sdk.getTenantCmsItem({collection,id:response.item_id}),assetPayload=buildCmsAttachAssetPayload({item:itemResponse,fields:schemaFields,field:coverField,assets:[coverAssetResponse],replace:!0});await sdk.configureTenantCmsItem({...assetPayload,item_id:response.item_id})}let finalPublishStatus=publishShortcut?(await sdk.applyTenantCmsPublish({collection,item_id:response.item_id,target_status:"published"})).publish_status:response.publish_status;importedItems.push({source_path:source.sourcePath,item_id:response.item_id,slug:payload.system.slug??null,publish_status:finalPublishStatus,state:"imported",warnings})}if(jsonMode){let summary=summarizeMarkdownImportResults(importedItems);process7.stdout.write(`${JSON.stringify(isBatch?{mode:"batch",import:{source_type:"markdown",source_path:markdownPath,recursive:hasFlag2(args,"recursive"),collection},skip_existing:skipExisting,summary,items:importedItems}:{...importedItems[0],import:{source_type:"markdown",source_path:importedItems[0].source_path,collection},skip_existing:skipExisting},null,2)}
2732
2735
  `);return}if(isBatch){printCmsImportMarkdownBatchOutput({collection,sourcePath:markdownPath,total:importedItems.length,summary:summarizeMarkdownImportResults(importedItems),items:importedItems});return}printCmsImportMarkdownOutput({collection,sourcePath:importedItems[0].source_path,itemId:importedItems[0].item_id,publishStatus:importedItems[0].publish_status,state:importedItems[0].state,matchedBy:importedItems[0].matched_by,warnings:importedItems[0].warnings});return}if(subcommand==="attach"){if(args.rest[1]!=="asset")throw new Error("`platform cms attach` \u5F53\u524D\u4EC5\u652F\u6301 `asset`\u3002");let collection=readOption2(args,"collection"),itemId=readOption2(args,"item-id"),fieldName=readOption2(args,"field"),assetIds=readCsvOption3(args,"asset-id"),replace2=hasFlag2(args,"replace");if(!collection||!itemId||!fieldName||assetIds.length===0)throw new Error("`platform cms attach asset` \u9700\u8981 `--collection <name>`\u3001`--item-id <id>`\u3001`--field <field-name>`\u3001`--asset-id <id[,id]>`\u3002");let[schemaResponse,itemResponse,assetResponses]=await Promise.all([sdk.inspectTenantCmsSchema(collection),sdk.getTenantCmsItem({collection,id:itemId}),Promise.all(assetIds.map(assetId=>sdk.getTenantAsset(assetId)))]),schema=schemaResponse.draft_schema??schemaResponse.active_schema;if(!schema)throw new Error(`Collection \`${collection}\` has no schema.`);let field=schema.fields.find(entry=>entry.name===fieldName);if(!field)throw new Error(`Collection \`${collection}\` does not contain field \`${fieldName}\`.`);if(field.type!=="image"&&field.type!=="images")throw new Error("`platform cms attach asset` \u5F53\u524D\u4EC5\u652F\u6301 `image`\u3001`images` \u5B57\u6BB5\u3002");if(field.type==="image"&&assetIds.length!==1)throw new Error("\u5355\u56FE\u5B57\u6BB5\u4E00\u6B21\u53EA\u80FD\u6302\u8F7D\u4E00\u4E2A\u7D20\u6750\uFF1B\u5982\u9700\u591A\u4E2A\u7D20\u6750\uFF0C\u8BF7\u4F7F\u7528 `images` \u5B57\u6BB5\u3002");if(assetResponses.some(asset=>asset.asset.media_type!=="image"))throw new Error("`platform cms attach asset` \u5F53\u524D\u4EC5\u652F\u6301\u6302\u8F7D\u56FE\u7247\u7D20\u6750\u3002");let payload=buildCmsAttachAssetPayload({item:itemResponse,fields:schema.fields,field,assets:assetResponses,replace:replace2}),response=await sdk.configureTenantCmsItem({...payload,item_id:itemId});if(jsonMode){process7.stdout.write(`${JSON.stringify({collection,item_id:response.item_id,publish_status:response.publish_status,field:field.name,field_type:field.type,mode:field.type==="images"?replace2?"replace":"append":"replace",asset_ids:assetResponses.map(asset=>asset.asset.asset_id)},null,2)}
2733
- `);return}printCmsAttachAssetOutput({collection,itemId:response.item_id,publishStatus:response.publish_status,fieldName:field.name,fieldType:field.type,assetIds:assetResponses.map(asset=>asset.asset.asset_id),replace:replace2});return}if(subcommand==="ensure"){if(args.rest[1]!=="category")throw new Error("`platform cms ensure` \u5F53\u524D\u4EC5\u652F\u6301 `category`\u3002");let collection=readOption2(args,"collection"),path=readOption2(args,"path");if(!collection||!path)throw new Error("`platform cms ensure category` \u9700\u8981 `--collection <name>` \u548C `--path <segment/segment>`\u3002");let segments=parseCmsCategoryPath(path),discover=await sdk.discoverTenantCmsCollection(collection),ensuredCategory=await ensureCmsCategoryPath({categories:discover.categories,segments,createCategory:async(segment,parentId)=>sdk.configureTenantCmsCategory({collection,node:{name:segment.name,slug:segment.slug,parent_id:parentId}})}),finalNode=ensuredCategory.finalNode,ensuredNodes=ensuredCategory.ensuredNodes;if(jsonMode){process7.stdout.write(`${JSON.stringify({collection,path,final_node:finalNode,ensured_nodes:ensuredNodes},null,2)}
2734
- `);return}printCmsEnsureCategoryOutput({collection,path,finalNode,ensuredNodes});return}if(subcommand==="list"){if(args.rest[1]!=="items")throw new Error("`platform cms list` \u5F53\u524D\u4EC5\u652F\u6301 `items`\u3002");let collection=readOption2(args,"collection");if(!collection)throw new Error("`platform cms list items` \u9700\u8981 `--collection <name>`\u3002");let status=(()=>{let value=readOption2(args,"status");if(value!==void 0){if(value==="draft"||value==="published"||value==="archived")return value;throw new Error("\u65E0\u6548\u7684 `--status`\uFF0C\u4EC5\u652F\u6301 `draft`\u3001`published`\u3001`archived`\u3002")}})(),response=await sdk.listTenantCmsItems({collection,page:readIntegerOption(args,"page"),pageSize:readIntegerOption(args,"page-size"),categoryId:readOption2(args,"category-id"),status,query:readOption2(args,"q")});if(jsonMode){process7.stdout.write(`${JSON.stringify(response,null,2)}
2736
+ `);return}printCmsAttachAssetOutput({collection,itemId:response.item_id,publishStatus:response.publish_status,fieldName:field.name,fieldType:field.type,assetIds:assetResponses.map(asset=>asset.asset.asset_id),replace:replace2});return}if(subcommand==="ensure"){if(args.rest[1]!=="category")throw new Error("`platform cms ensure` \u5F53\u524D\u4EC5\u652F\u6301 `category`\u3002");let collection=readOption2(args,"collection"),path2=readOption2(args,"path");if(!collection||!path2)throw new Error("`platform cms ensure category` \u9700\u8981 `--collection <name>` \u548C `--path <segment/segment>`\u3002");let segments=parseCmsCategoryPath(path2),discover=await sdk.discoverTenantCmsCollection(collection),ensuredCategory=await ensureCmsCategoryPath({categories:discover.categories,segments,createCategory:async(segment,parentId)=>sdk.configureTenantCmsCategory({collection,node:{name:segment.name,slug:segment.slug,parent_id:parentId}})}),finalNode=ensuredCategory.finalNode,ensuredNodes=ensuredCategory.ensuredNodes;if(jsonMode){process7.stdout.write(`${JSON.stringify({collection,path:path2,final_node:finalNode,ensured_nodes:ensuredNodes},null,2)}
2737
+ `);return}printCmsEnsureCategoryOutput({collection,path:path2,finalNode,ensuredNodes});return}if(subcommand==="list"){if(args.rest[1]!=="items")throw new Error("`platform cms list` \u5F53\u524D\u4EC5\u652F\u6301 `items`\u3002");let collection=readOption2(args,"collection");if(!collection)throw new Error("`platform cms list items` \u9700\u8981 `--collection <name>`\u3002");let status=(()=>{let value=readOption2(args,"status");if(value!==void 0){if(value==="draft"||value==="published"||value==="archived")return value;throw new Error("\u65E0\u6548\u7684 `--status`\uFF0C\u4EC5\u652F\u6301 `draft`\u3001`published`\u3001`archived`\u3002")}})(),response=await sdk.listTenantCmsItems({collection,page:readIntegerOption(args,"page"),pageSize:readIntegerOption(args,"page-size"),categoryId:readOption2(args,"category-id"),status,query:readOption2(args,"q")});if(jsonMode){process7.stdout.write(`${JSON.stringify(response,null,2)}
2735
2738
  `);return}printCmsTenantItemListOutput(response);return}if(subcommand==="batch"){if(args.rest[1]!=="update")throw new Error("`platform cms batch` \u5F53\u524D\u4EC5\u652F\u6301 `update`\u3002");let collection=readOption2(args,"collection"),itemIds=readCsvOption3(args,"item-id");if(!collection||itemIds.length===0)throw new Error("`platform cms batch update` \u9700\u8981 `--collection <name>` \u548C `--item-id <id[,id]>`\u3002");let categoryId=readOption2(args,"category-id"),clearCategory=hasFlag2(args,"clear-category");if(categoryId&&clearCategory)throw new Error("`platform cms batch update` \u4E0D\u80FD\u540C\u65F6\u6307\u5B9A `--category-id` \u548C `--clear-category`\u3002");let status=(()=>{let value=readOption2(args,"status");if(value!==void 0){if(value==="draft"||value==="published"||value==="archived")return value;throw new Error("\u65E0\u6548\u7684 `--status`\uFF0C\u4EC5\u652F\u6301 `draft`\u3001`published`\u3001`archived`\u3002")}})(),tagsToAdd=readCsvOption3(args,"add-tags");if(!categoryId&&!clearCategory&&!status&&tagsToAdd.length===0)throw new Error("`platform cms batch update` \u81F3\u5C11\u9700\u8981\u4E00\u4E2A\u53D8\u66F4\u9879\uFF1A`--category-id`\u3001`--clear-category`\u3001`--add-tags`\u3001`--status`\u3002");let response=await batchUpdateTenantCmsItems({sdk,payload:{collection,item_ids:itemIds,changes:{category:clearCategory?{mode:"clear"}:categoryId?{mode:"set",category_id:categoryId}:{mode:"keep"},tags:{add:tagsToAdd},publish_status:status?{mode:"set",value:status}:{mode:"keep"}}}});if(jsonMode){process7.stdout.write(`${JSON.stringify(response,null,2)}
2736
2739
  `);return}printCmsBatchUpdateOutput(response);return}if(subcommand==="inspect"){let inspectTarget=args.rest[1]??"schema";if(inspectTarget==="item"){let collection=readOption2(args,"collection")??args.rest[2],itemId=readOption2(args,"id");if(!collection||!itemId)throw new Error("`platform cms inspect item` \u9700\u8981 `--collection <name>` \u548C `--id <id>`\u3002");let response=await sdk.getTenantCmsItem({collection,id:itemId});if(jsonMode){process7.stdout.write(`${JSON.stringify(response,null,2)}
2737
2740
  `);return}printCmsTenantItemOutput(response);return}if(inspectTarget==="schema"){let collection=readOption2(args,"collection")??args.rest[2];if(!collection)throw new Error("`platform cms inspect schema` \u9700\u8981 `--collection <name>`\u3002");let response=await sdk.inspectTenantCmsSchema(collection);if(jsonMode){process7.stdout.write(`${JSON.stringify(response,null,2)}