@blocklet/pages-kit-inner-components 0.6.10 → 0.6.11

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.
@@ -0,0 +1 @@
1
+ "use strict";const d=require("./components-CacZMc0_.js"),F=require("@syncedstore/core"),Je=require("yjs"),Ke=require("@blocklet/pages-kit/utils/data-source"),Q=require("@blocklet/pages-kit/utils/route"),He=require("lodash"),We=require("@blocklet/sdk/lib/config"),I=require("fs"),g=require("path"),Te=require("@blocklet/pages-kit/utils/common"),Qe=require("@blocklet/pages-kit/utils/page-model"),Xe=require("@blocklet/pages-kit/utils/property"),Ie=require("@blocklet/sdk/lib/component"),Ze=require("@reactivedata/reactive"),X=require("glob"),et=require("lib0/decoding"),tt=require("lib0/encoding"),st=require("lodash/cloneDeep"),at=require("lodash/debounce"),nt=require("lodash/get"),ot=require("lodash/isEmpty"),rt=require("lodash/set"),it=require("lodash/union"),be=require("lru-cache"),ct=require("p-limit"),C=require("sequelize"),lt=require("stream/promises"),pt=require("tar"),Y=require("ufo"),ut=require("wait-on"),z=require("y-protocols/awareness"),le=require("y-protocols/sync"),dt=require("yaml");require("sqlite3");require("@blocklet/pages-kit/types/state");const M=t=>t&&t.__esModule?t:{default:t};function ae(t){if(t&&t.__esModule)return t;const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const s in t)if(s!=="default"){const a=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,a.get?a:{enumerable:!0,get:()=>t[s]})}}return e.default=t,Object.freeze(e)}const $=ae(Je),E=M(We),pe=ae(et),v=ae(tt),ft=M(st),Re=M(at),Ee=M(nt),we=M(ot),De=M(rt),gt=M(it),mt=M(ct),ht=M(ut),x=ae(dt),yt=C.DataTypes.sqlite.DATE.parse;C.DataTypes.sqlite.DATE.parse=(t,e)=>typeof t=="number"?new Date(t):yt(t,e);const U=new C.Sequelize({dialect:"sqlite",storage:d.databaseUrl,benchmark:process.env.ENABLE_SEQUELIZE_BENCHMARK==="true",retry:{match:[/SQLITE_BUSY/],name:"query",max:10},logging:process.env.ENABLE_SEQUELIZE_LOGGING==="true"?console.log:!1});U.query("pragma journal_mode = WAL;");U.query("pragma synchronous = normal;");U.query("pragma journal_size_limit = 33554432;");U.query("pragma cache_size = -2000;");U.query("pragma mmap_size = 33554432;");process.on("SIGINT",async()=>{await U.close(),process.exit(0)});process.on("SIGTERM",async()=>{await U.close(),process.exit(0)});async function St(t,e){try{if(t.getDialect()!=="sqlite")return;const[s]=await t.query("SELECT 1");if(!s||s.length===0)return;await t.query("PRAGMA shrink_memory;")}catch(s){if(s.name==="SequelizeConnectionError"||s?.message&&/closed!/.test(s.message))return;console.error("Failed to cleanup SQLite memory",e,s)}}let fe=null;fe&&clearInterval(fe);fe=setInterval(async()=>{d.logger.info("Start cleanupSqliteMemory"),await St(U,d.databaseUrl),d.logger.info("End cleanupSqliteMemory")},60*1e3*10);class Ae extends C.Model{}Ae.init({id:{type:C.DataTypes.UUID,allowNull:!1,primaryKey:!0,defaultValue:C.DataTypes.UUIDV4},projectId:{type:C.DataTypes.UUID,allowNull:!1},componentId:{type:C.DataTypes.STRING,allowNull:!1}},{sequelize:U,tableName:"ProjectComponents",timestamps:!1});class L extends C.Model{static async getProjectByIdOrSlug(e){return L.findOne({where:{[C.Op.or]:[{id:e},{slug:e}]}})}}L.init({id:{type:C.DataTypes.UUID,defaultValue:C.DataTypes.UUIDV4,primaryKey:!0},name:{type:C.DataTypes.STRING,allowNull:!1},description:C.DataTypes.TEXT,createdAt:C.DataTypes.DATE,updatedAt:C.DataTypes.DATE,createdBy:{type:C.DataTypes.STRING,allowNull:!1},updatedBy:{type:C.DataTypes.STRING,allowNull:!1},slug:C.DataTypes.STRING,icon:C.DataTypes.STRING,pinnedAt:C.DataTypes.DATE,useAllResources:C.DataTypes.BOOLEAN,npmSecret:C.DataTypes.STRING,relatedBlocklets:{type:C.DataTypes.JSON,allowNull:!1,defaultValue:{},get(){const t=this.getDataValue("relatedBlocklets");if(typeof t=="object")return t??{};try{return t?JSON.parse(t):{}}catch(e){return d.logger.error("Failed to parse relatedBlocklets",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("relatedBlocklets",t?JSON.stringify(t):"{}")}catch(e){d.logger.error("Failed to set relatedBlocklets",{error:e,value:t}),this.setDataValue("relatedBlocklets","{}")}}},productionState:{type:C.DataTypes.JSON,allowNull:!1,defaultValue:{},get(){const t=this.getDataValue("productionState");if(typeof t=="object")return t??{};try{return t?JSON.parse(t):{}}catch(e){return d.logger.error("Failed to parse productionState",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("productionState",t?JSON.stringify(t):"{}")}catch(e){d.logger.error("Failed to set productionState",{error:e,value:t}),this.setDataValue("productionState","{}")}}}},{sequelize:U,paranoid:!0});L.hasMany(Ae,{foreignKey:"projectId",as:"components"});const It="z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o",ge="page",me="trigger-reload-project-resource",Pe=It,bt="z2qa7BQdkEb3TwYyEYC1psK6uvmGnHSUHt5RM";function Z(t){t.observeDeep(e=>{e.some(s=>s.changes.keys.has("updatedAt")||s.changes.keys.has("publishedAt"))||t.set("updatedAt",new Date().toISOString())})}function Le(){return I.mkdtempSync(g.join(E.default.env.dataDir,"tmp-"))}function ee(t,e,s=[]){return Array.isArray(t)?t.flatMap((a,n)=>ee(a,e,[...s,n])):typeof t=="object"?t===null?[]:Object.entries(t).flatMap(([a,n])=>ee(n,e,[...s,a])):e(t)?[s]:[]}function R(t){return t.filter(e=>e!=null)}function Et(t){t.pages&&Object.keys(t.pages).forEach(s=>{const a=F.getYjsValue(t.pages[s]);a&&a instanceof $.Map&&Z(a)});const e=F.getYjsValue(t.pages);e&&e instanceof $.Map&&e.observe(s=>{s.changes.keys.forEach((a,n)=>{if(a.action==="add"){const o=F.getYjsValue(t.pages[n]);o&&o instanceof $.Map&&Z(o)}})})}function wt(t){t.routes&&Object.keys(t.routes).forEach(s=>{const a=F.getYjsValue(t.routes?.[s]);a&&a instanceof $.Map&&Z(a)});const e=F.getYjsValue(t.routes);e&&e instanceof $.Map&&e.observe(s=>{s.changes.keys.forEach((a,n)=>{if(a.action==="add"){const o=F.getYjsValue(t.routes?.[n]);o&&o instanceof $.Map&&Z(o)}})})}function At(t,e){for(const s of e||Object.keys(t.routes||{})){let a=s,n=[];if(s.includes("-")){const[o,...i]=s.split("-");a=o,n=i||[]}if(t.routes?.[a]!==void 0){t.routes[a].publishedAt=new Date().toISOString();const o=t.routes[a];if(!o||!o.params||o.params.length===0)continue;if(s.includes("-")&&n.length>0){const i=Q.getRouteMetaDataByOptionIds(n,o);i&&(i.publishedAt=new Date().toISOString())}if(!e){const i=Q.generateParamCombinations({basePath:o.path,params:o.params,routeId:o.id,paramsOptions:o.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const c of i)c.routeMetaData??={},c.routeMetaData.publishedAt=new Date().toISOString()}}}}function ue({page:t,route:e,state:s,routeId:a,routePathInfo:n}){d.logger.info(`Executing datasource data assembly, routeId: ${a}, routePathInfo: ${JSON.stringify(n)}`);const o={...He.cloneDeep(t),id:a,slug:n?.path??e.path,createdAt:e.createdAt,updatedAt:n?.routeMetaData?.updatedAt??e.updatedAt,publishedAt:n?.routeMetaData?.publishedAt??e.publishedAt,isPublic:(n?.routeMetaData?.isPublic??e.isPublic)&&e.isPublic};for(const i of s.supportedLocales){if(e.dataSource){let c=e.id;n&&(c=n.paramOptionIds.join("-"));const p=e.dataSource.pathDataMappings?.[c]?.dataCache?.[i.locale]??e.dataSource.pathDataMappings?.[c]?.dataCache?.[s.config.defaultLocale||"en"];if(!p)continue;Ke.setPageDataSource(o,s,i.locale,p)}n&&n.routeMetaData&&(n.routeMetaData.publishedAt=new Date().toISOString())}return o}const Pt=30*60*1e3,B=new be.LRUCache({max:100,ttl:Pt});function Ot(t,e=[]){let s=0;const a=Array.from(B.keys()),n=[];for(const o of t){n.push(`page-html:prod:${o}:lang-path=none`);for(const i of e)n.push(`page-html:prod:/${i}${o}:lang-path=${i}`)}for(const o of a){const i=o.split(":lang-path=")[0]||"";for(const c of n){const m=(c.split(":lang-path=")[0]||"").replace(/\/:[^/]+/g,"");if(i.startsWith(m)){B.delete(o),s++,d.logger.info(`[Cache CLEAR] key: ${o}`);break}}}return d.logger.info(`[Cache CLEAR] cleared ${s} entries for patterns:`,n),s}function Ct({projectId:t,projectSlug:e,supportedLocales:s=[]}){let a=0;const n=Array.from(B.keys()),o=[];o.push(`page-html:prod:/${t}`),e&&e!==t&&o.push(`page-html:prod:/${e}`);for(const i of s)o.push(`page-html:prod:/${i}/${t}`),e&&e!==t&&(e!=="/"?o.push(`page-html:prod:/${i}/${e}`):o.push(`page-html:prod:/${i}`));for(const i of n)for(const c of o)if(i.startsWith(c)){B.delete(i),a++,d.logger.info(`[Cache CLEAR PROJECT] key: ${i}`);break}return d.logger.info(`[Cache CLEAR PROJECT] cleared ${a} entries for project ${t}${e?` (slug: ${e})`:""}`),a}function jt(){const t=B.size;return B.clear(),d.logger.info(`[Cache CLEAR ALL] cleared ${t} entries`),t}E.default.events.on(E.default.Events.envUpdate,jt);const{uploadToMediaKit:Tt}=require("@blocklet/uploader-server"),Oe=/^\w+(\w|-|\.)+\w+\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm)$/,J=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/i,ke=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/gi,Dt=1e4,kt=3e4,H=0,de=1,vt=0,Rt=1,he=E.default,q=g.join(process.env.BLOCKLET_DATA_DIR,"site-state"),Lt=["production","draft"],_t=["production"];function te(t){return t?.replace(/\//g,"|")||""}function _e(){const t=he.env.languages?.map(s=>({locale:s.code,name:s.name}))||[],e=t[0]?.locale||"en";return{pageIds:[],pages:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{},components:{},supportedLocales:t,config:{defaultLocale:e},resources:{}}}class O extends $.Doc{constructor(e){super(),this.options=e,I.existsSync(this.draftYjsFilePath)&&$.applyUpdate(this,I.readFileSync(this.draftYjsFilePath)),this.syncedStore=Ze.reactive(F.syncedStore({pages:{},pageIds:[],components:{},supportedLocales:[],config:{},resources:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{}},this)),this.initObserver(),this.on("update",this.updateHandler),this.awareness=new z.Awareness(this),this.awareness.on("update",this.awarenessChangeHandler),this.ensureDataStructure()}static RELEASE_DELAY=5*60*1e3;static PERIODIC_CHECK_INTERVAL=2*60*60*1e3;static sharedInstances={};static pageUrlMapCache=new be.LRUCache({max:100,ttl:1e3*60*60*24});static periodicCheckTimer;static safeDeleteProjectStateDir(e){if(!e)throw new Error("Should provide project context");try{const s=g.join(q,e),a=g.join(q,`@del-${e}`);I.renameSync(s,a)}catch(s){d.logger.error("Failed to safe delete project state dir:",s)}}static async getProjectIds(){return(await L.findAll({attributes:["id"],raw:!0}))?.map(e=>e.id)}static get projectIds(){return X.globSync("*/",{cwd:q,ignore:["@del-*","@tmp-*",".*","staging","production","@backup-*","undefined"]})}static get allShared(){return this.projectIds.map(e=>O.shared(e))}static shared(e){if(!e)throw new Error("Should provide project context");let s=O.sharedInstances[e];return s||(s=new O({path:g.join(q,e)}),O.sharedInstances[e]=s,s)}static async getProductionState(e){const s=await L.findByPk(e,{attributes:["productionState"]});if(we.default(s?.productionState)){const a=g.join(q,e,"production"),n=await Ce(a,{includeResources:!0})??_e();if(!n?.config?.defaultLocale){n.config??={};const o=he.env.languages?.map(i=>({locale:i.code,name:i.name}))||[];n.config.defaultLocale=o[0]?.locale}return n}return s?.productionState}destroy(){this.cancelRelease(),this.save({flush:!0}),this.conns.forEach((s,a)=>this.closeConn(a)),this.awareness.destroy();const e=g.basename(this.options.path);delete O.sharedInstances[e],super.destroy()}initObserver(){Et(this.syncedStore),wt(this.syncedStore)}get draftYjsFilePath(){return g.join(this.options.path,"draft.yjs")}static async getStateByProjectId(e,s){if(s==="draft"){const a=O.shared(e);return JSON.parse(JSON.stringify(a.syncedStore))}return O.getProductionState(e)}async getState(e){if(e==="draft")return JSON.parse(JSON.stringify(this.syncedStore));const s=g.basename(this.options.path);return O.getProductionState(s)}async setState(e,s){const a=await Ne(s,{exportAssets:!1,includeResources:!0}),n=this.getPublishDir(e);if(I.mkdirSync(g.dirname(n),{recursive:!0}),I.rmSync(n,{force:!0,recursive:!0}),I.renameSync(a,n),e==="production"){const o=g.basename(this.options.path);O.pageUrlMapCache.delete(o),await L.update({productionState:{...s}},{where:{id:o}})}}getPublishDir(e){return g.join(this.options.path,e)}syncedStore;conns=new Map;awareness;releaseTimer;awarenessChangeHandler=({added:e,updated:s,removed:a},n)=>{const o=e.concat(s,a);if(n!==null){const p=this.conns.get(n);p&&(e.forEach(m=>{p.add(m)}),a.forEach(m=>{p.delete(m)}))}const i=v.createEncoder();v.writeVarUint(i,de),v.writeVarUint8Array(i,z.encodeAwarenessUpdate(this.awareness,o));const c=v.toUint8Array(i);this.conns.forEach((p,m)=>this.send(m,c))};updateHandler=e=>{const s=v.createEncoder();v.writeVarUint(s,H),le.writeUpdate(s,e);const a=v.toUint8Array(s);this.conns.forEach((n,o)=>this.send(o,a))};ensureDataStructure=()=>{const{supportedLocales:e,pages:s,pageIds:a,config:n,routes:o,routeIds:i}=this.syncedStore;{const c=new Set(Object.keys(s));let p=0;for(;p<a.length;){const m=a[p];c.has(m)?(c.delete(m),p++):a.splice(p,1)}}{const c=new Set(Object.keys(o));let p=0;for(;p<i.length;){const m=i[p];c.has(m)?(c.delete(m),p++):i.splice(p,1)}}e.splice(0,e.length),e.push(...he.env.languages.map(c=>({locale:c.code,name:c.name}))),n.defaultLocale=e[0]?.locale;{let c=0;const p=new Set;for(;c<e.length;){const{locale:m}=e[c];p.has(m)?e.splice(c,1):(c++,p.add(m))}}};send=(e,s)=>{e.readyState!==vt&&e.readyState!==Rt&&this.closeConn(e);try{e.send(s,a=>{a&&this.closeConn(e)})}catch{this.closeConn(e)}};closeConn=e=>{if(e.removeAllListeners(),this.conns.has(e)){const s=this.conns.get(e);this.conns.delete(e),s&&z.removeAwarenessStates(this.awareness,Array.from(s),null)}e.close(),this.checkAndScheduleRelease()};checkAndScheduleRelease(){this.conns.size===0&&this.scheduleRelease()}scheduleRelease(){this.cancelRelease();const e=g.basename(this.options.path);this.releaseTimer=setTimeout(()=>{d.logger.info(`[SiteState] releasing instance due to no active connections: ${e}`),this.conns.size===0&&(this.releaseTimer=void 0,this.destroy())},O.RELEASE_DELAY),d.logger.info(`[SiteState] scheduled release for project ${e} in ${O.RELEASE_DELAY/1e3}s`)}cancelRelease(){if(this.releaseTimer){clearTimeout(this.releaseTimer),this.releaseTimer=void 0;const e=g.basename(this.options.path);d.logger.info(`[SiteState] cancelled scheduled release for project ${e}`)}}autoSave=Re.default(()=>{I.mkdirSync(g.dirname(this.draftYjsFilePath),{recursive:!0}),I.writeFileSync(this.draftYjsFilePath,$.encodeStateAsUpdate(this))},Dt);save=({flush:e=!1}={})=>{this.autoSave(),e&&this.autoSave.flush()};publish=async({mode:e,routes:s})=>{const a=await this.getState("draft"),n=await this.getState("production");await Se(a,n,{routes:s,mergeMode:"replace",deleteRoutes:!0,publishMode:e}),n.config.publishedAt=new Date().getTime(),At(this.syncedStore,s),await this.setState(e,n),await this.clearPageCacheForRoutes(s,n)};mergeState=async(e,s)=>{const a=JSON.parse(JSON.stringify(s));e.config.fontFamily??={};const n=a.config?.fontFamily,o=e.config?.fontFamily;e.config.fontFamily.title=n?.title||o?.title,e.config.fontFamily.description=n?.description||o?.description,await new Promise((i,c)=>{this.transact(async()=>{try{const p=await Se(e,s);i(p)}catch(p){c(p)}})})};clearPageCacheForRoutes=async(e,s)=>{const a=g.basename(this.options.path),o=(await L.findByPk(a))?.slug||a;if(d.logger.info(`[SiteState] clearing page cache for project ${a}, routes:`,e||[]),!e||e.length===0){Ct({projectId:a,projectSlug:o,supportedLocales:s.supportedLocales.map(m=>m.locale)});return}const i=s.supportedLocales.map(m=>m.locale),c=[],p=e.filter(m=>s.pages[m]);for(const m of p){const T=s.pages[m].slug;o&&o!==a&&(o==="/"?c.push(T):c.push(`/${o}${T}`)),c.push(`/${a}${T}`)}if(d.logger.info(`[SiteState] clearing page cache for project ${a}, pathPatterns:`,c),c.length>0){const m=Ot(c,i);d.logger.info(`[SiteState] cleared ${m} page cache entries for project ${a}, routes:`,e)}};addConnection=e=>{if(this.conns.has(e))return;this.cancelRelease(),e.binaryType="arraybuffer",this.conns.set(e,new Set),e.on("message",n=>this.messageListener(e,new Uint8Array(n)));let s=!0;const a=setInterval(()=>{if(!s)this.conns.has(e)&&this.closeConn(e),clearInterval(a);else if(this.conns.has(e)){s=!1;try{e.ping()}catch{this.closeConn(e),clearInterval(a)}}},kt);e.on("close",()=>{this.closeConn(e),clearInterval(a)}),e.on("pong",()=>{s=!0});{const n=v.createEncoder();v.writeVarUint(n,H),le.writeSyncStep1(n,this),this.send(e,v.toUint8Array(n));const o=this.awareness.getStates();if(o.size>0){const i=v.createEncoder();v.writeVarUint(i,de),v.writeVarUint8Array(i,z.encodeAwarenessUpdate(this.awareness,Array.from(o.keys()))),this.send(e,v.toUint8Array(i))}}};messageListener=(e,s)=>{try{const a=v.createEncoder(),n=pe.createDecoder(s),o=pe.readVarUint(n);switch(o){case H:v.writeVarUint(a,H),le.readSyncMessage(n,a,this,null),v.length(a)>1&&(this.ensureDataStructure(),this.send(e,v.toUint8Array(a)));break;case de:{z.applyAwarenessUpdate(this.awareness,pe.readVarUint8Array(n),e);break}default:d.logger.warn(`Unsupported messageType ${o}`)}}catch(a){d.logger.error(a)}this.save()};static async pageUrlMap(e,s){let a=[];s?a=[s]:a=await this.getProjectIds();let n={};if(e==="production"&&a?.length){const o=new Map(a?.map(i=>[i,!0])||[]);for(const i of a){const c=O.pageUrlMapCache.get(i);c&&(n={...n,...c},o.delete(i))}a=Array.from(o.keys())}if(a?.length){const o=await L.findAll({where:{id:{[C.Op.in]:a}}});await Promise.all(o?.map(async i=>{const c=i.id,p=i.slug||c,m={},k=e==="production"&&i?.productionState?i.productionState:await O.getStateByProjectId(i.id,e),T=gt.default(E.default.env.languages?.map(u=>u.code)||[],k.supportedLocales?.map(u=>u.locale)||[]),w=(u,l)=>{p&&(m[Y.joinURL("/",p,u)]={...l,shouldRedirect:!0,mainPage:!0}),m[Y.joinURL("/",c,u)]={...l,shouldRedirect:!0,mainPage:!0};for(const y of T){const j={...l,locale:y};m[Y.joinURL("/",y,c,u)]=j,p&&(m[Y.joinURL("/",y,p,u)]=j)}};if(e==="draft")for(const u of k.routeIds||[]){const l=k?.routes?.[u];if(!l)continue;if(l.params&&l.params.length>0){const h=Q.generateParamCombinations({basePath:l.path,params:l.params,routeId:l.id,paramsOptions:l.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const f of h){const S=f.path,A={projectId:c,projectSlug:p,pageSlug:S,pageId:l.displayTemplateId||"",routeId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic&&f?.routeMetaData?.isPublic};w(S,A)}}const y=l.path,j={projectId:c,projectSlug:p,pageSlug:y,pageId:l.displayTemplateId||"",routeId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic};w(y,j)}for(const u of k.pageIds){const l=k.pages[u];if(!l||e==="production"&&!l.isPublic)continue;const y=l.slug,j=i.slug||c,h={projectId:c,projectSlug:j,pageSlug:y,pageId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic,templateConfig:l.templateConfig};w(y,h)}e==="production"&&O.pageUrlMapCache.set(c,m),n={...n,...m}}))}return n}getDocumentSize(){return $.encodeStateAsUpdate(this).byteLength}static getInstancesSizeInfo(){const e=[];for(const[s,a]of Object.entries(O.sharedInstances)){const n=a.getDocumentSize();e.push({projectId:s,sizeInBytes:n,sizeInMB:`${(n/(1024*1024)).toFixed(2)} MB`,activeConnections:a.conns.size})}return e}static startPeriodicCheck(){this.periodicCheckTimer||(this.periodicCheckTimer=setInterval(()=>{this.performPeriodicCheck()},this.PERIODIC_CHECK_INTERVAL),d.logger.info(`[SiteState] periodic check started, interval: ${this.PERIODIC_CHECK_INTERVAL/(60*60*1e3)} hours`))}static stopPeriodicCheck(){this.periodicCheckTimer&&(clearInterval(this.periodicCheckTimer),this.periodicCheckTimer=void 0,d.logger.info("[SiteState] periodic check stopped"))}static performPeriodicCheck(){const e=Object.keys(O.sharedInstances).length,s=[],a=[];for(const[n,o]of Object.entries(O.sharedInstances))o.conns.size===0?s.push({projectId:n,instance:o}):a.push({projectId:n,connections:o.conns.size});if(d.logger.info(`[SiteState] periodic check summary: total instances: ${e}, with connections: ${a.length}, without connections: ${s.length}`),s.length>0){d.logger.info(`[SiteState] releasing ${s.length} instances without connections:`,s.map(o=>o.projectId));let n=0;for(const{projectId:o,instance:i}of s)try{d.logger.info(`[SiteState] releasing instance due to periodic check: ${o}`),i.destroy(),n++}catch(c){d.logger.error(`[SiteState] failed to release instance ${o} during periodic check:`,c)}d.logger.info(`[SiteState] periodic check completed: ${n}/${s.length} instances released successfully`)}else e>0?d.logger.debug("[SiteState] periodic check: all instances have active connections"):d.logger.debug("[SiteState] periodic check: no instances exist")}}async function $t(t,e,s){if(!t||!I.existsSync(t)||!I.lstatSync(t).isFile())return null;let a=s[t];return a||(a=(async()=>{try{return(await Tt({filePath:t,fileName:e}))?.data?.filename}catch(n){return d.logger.error(`Failed to upload asset ${t}:`,n),null}})(),s[t]=a),a}const $e=async(t,e)=>{const s=g.basename(t),a=await Ie.call({name:Pe,path:Y.joinURL("/uploads",s),responseType:"stream",method:"GET"});if(a.status>=200&&a.status<400){const n=I.createWriteStream(e);await lt.pipeline(a.data,n)}else throw new Error(`download asset failed ${a.status}`)},Ue=async(t,e)=>{await Promise.all(t.map(async s=>{try{await $e(s,g.join(e,g.basename(s)))}catch(a){d.logger.error(`Failed to export assets: ${s}, ${a}`)}}))};function Me(t){return Oe.test(t)?[t]:J.test(t)?(ke.lastIndex=0,Array.from(t.matchAll(ke)).map(s=>s[1]).filter(s=>!!s)):[]}async function W(t,e,s){const{getFilename:a,exportAssets:n}=s,o=g.join(e,a(t));if(I.mkdirSync(g.dirname(o),{recursive:!0}),I.writeFileSync(o,x.stringify(t)),n){const c=ee(t,p=>typeof p=="string"&&(Oe.test(p)||J.test(p))).map(p=>{const m=Ee.default(t,p);return Me(m)}).flat().filter(Boolean);await Ue(c,g.dirname(o))}}const ye=new be.LRUCache({max:100,ttl:1*60*1e3});async function ve(t,e,s){const a=ee(t,c=>typeof c=="string"&&(Oe.test(c)||J.test(c))),n=mt.default(2),o=a.map(c=>n(async()=>{try{const p=Ee.default(t,c),m=Me(p);for(const k of m){const T=g.basename(k),w=s.getFilePath(k,c),u=w?`${w}:${T}`:T,l=ye.get(u);if(l){J.test(p)||De.default(t,c,l);return}const y=await $t(w,T,e);y&&(J.test(p)||De.default(t,c,y),ye.set(u,y))}}catch(p){d.logger.error(`Failed to process upload for path ${c.join(".")}:`,p.message||p.reason)}})),i=await Promise.allSettled(o);s.onFinish?.(i)}async function Ne(t,{exportAssets:e,pageIds:s="all",componentIds:a="all",rawConfig:n,includeResources:o=!1,routeIds:i="all"}={}){const c=s==="all"?t.pageIds:s,p=Xe.getComponentDependencies({state:t,pageIds:c,componentIds:a==="all"?Object.keys(t.components):a}),m=i==="all"?t.routeIds:i,k=r=>({id:r.id,name:r.name,isTemplateSection:r.isTemplateSection??!1,templateDescription:r.templateDescription,llmConfig:r.llmConfig,component:r.component,config:r.config,visibility:r.visibility,sections:r?.sectionIds?R(r?.sectionIds?.map(b=>{const D=r.sections?.[b];return D&&k(D)})):void 0}),T=(r,b)=>({id:r.id,createdAt:r.createdAt,updatedAt:r.updatedAt,publishedAt:r.publishedAt,isPublic:r.isPublic??!0,templateConfig:r.templateConfig,meta:r.locales?.[b]??{},sections:R(r.sectionIds.map(D=>{const N=r.sections[D];return N&&k(N)})),dataSource:Object.fromEntries(Object.entries(r.dataSource||{}).map(([D,N])=>[D,N?.[b]??{}]))}),w=r=>({id:r.id,createdAt:r.createdAt,updatedAt:r.updatedAt,publishedAt:r.publishedAt,path:r.path,handler:r.handler,isPublic:r.isPublic??!0,params:r.params??[],enabledGenerate:r.enabledGenerate??!1,displayTemplateId:r.displayTemplateId,dataSource:r.dataSource}),u=R(m.map(r=>{const b=t.routes[r];return b&&w(b)})),l=R(t.supportedLocales.map(r=>r.locale).flatMap(r=>c.map(b=>{const D=t.pages[b];return D&&{locale:r,slug:D.slug,page:T(D,r)}}))),y=Le(),j=g.join(y,"pages");I.mkdirSync(j,{recursive:!0});const h=g.join(y,"components");I.mkdirSync(h,{recursive:!0});const f=g.join(y,"routes");I.mkdirSync(f,{recursive:!0});for(const{locale:r,slug:b,page:D}of l)await W(D,j,{getFilename:()=>`${te(b)||"index"}.${r}.yml`,exportAssets:e});for(const r of u)await W(r,f,{getFilename:()=>`${te(r.path)||"index"}.yml`,exportAssets:e});for(const r of p){const b=t.components[r]?.data;b&&await W(b,h,{getFilename:D=>`${D.name||"unnamed"}.${D.id}.yml`,exportAssets:e})}const S=g.join(y,".blocklet/pages/pages.config.yml");I.mkdirSync(g.dirname(S),{recursive:!0});const A={pages:R(c.map(r=>{const b=t.pages[r];return b&&{id:r,slug:b.slug}})),routes:R(m.map(r=>{const b=t.routes[r];return b&&{id:r,path:b.path}})),components:R(p.map(r=>{const b=t.components[r]?.data;return b&&{id:r,name:b.name}})),...o?{resources:{components:R(Object.keys(t.resources?.components||{}).filter(r=>p.includes(r)).map(r=>({id:r,name:t.resources?.components?.[r]?.component?.name})))}}:{},supportedLocales:t.supportedLocales,config:t.config};I.writeFileSync(S,x.stringify(A));const P=g.join(y,"config.source.json");if(n&&I.writeFileSync(P,JSON.stringify(n)),o){const r=g.join(y,"resources"),b=g.join(r,"components");I.mkdirSync(b,{recursive:!0});for(const V of Object.keys(t?.resources?.components??{}).filter(_=>p.includes(_))){const _=t.resources?.components?.[V]?.component;_&&await W(_,b,{getFilename:G=>`${G.name||"unnamed"}.${G.id}.yml`,exportAssets:e})}const D=g.join(y,"chunks");I.mkdirSync(D,{recursive:!0});const N=Ut();for(const V of Object.keys(t?.resources?.components??{}).filter(_=>p.includes(_))){const _=t.resources?.components?.[V]?.component;if(_&&_.renderer?.type==="react-component"){const G=_.renderer?.chunks??[];if(G?.length>0)for(const ie of G){const je=g.join(D,ie),ce=N?.[ie];try{ce&&I.existsSync(ce)&&!I.existsSync(je)&&I.copyFileSync(ce,je)}catch(Ye){d.logger.error(`copy chunk ${ie} error`,Ye.message)}}}}}return y}async function Ce(t,{importAssets:e,includeResources:s}={}){if(!I.existsSync(t))return null;let a,n=!1;try{I.lstatSync(t).isDirectory()?a=t:/\.(tgz|gz|tar)$/.test(t)&&(n=!0,a=Le(),await pt.x({file:t,C:a}));const o=X.globSync("**/.blocklet/pages/pages.config.yml",{cwd:a,absolute:!0}).at(0),i=o&&g.join(g.dirname(o),"../../pages"),c=o&&g.join(g.dirname(o),"../../components"),p=o&&g.join(g.dirname(o),"../../routes");if(!o)return null;const m=x.parse(I.readFileSync(o).toString()),k=(h,f,S)=>{let A=g.join(h,`${f}${S?`.${S}`:""}.yml`);return(!I.existsSync(A)||!I.lstatSync(A).isFile())&&(A=g.join(h,f,`index${S?`.${S}`:""}.yml`),!I.existsSync(A)||!I.lstatSync(A))?null:x.parse(I.readFileSync(A).toString())},T=(h,f)=>{try{const S=X.globSync(`*.${f}.yml`,{cwd:h,absolute:!0})[0];return S?x.parse(I.readFileSync(S).toString()):null}catch(S){d.logger.error("parse component error",S)}return null},w=(h,f)=>{let S=g.join(h,`${f}.yml`);return(!I.existsSync(S)||!I.lstatSync(S).isFile())&&(S=g.join(h,f,"index.yml"),!I.existsSync(S)||!I.lstatSync(S))?null:x.parse(I.readFileSync(S).toString())},u=R(m.pages.map(({slug:h})=>{const f=R(m.supportedLocales.map(({locale:P})=>{const r=i?k(i,te(h),P):void 0;if(r)return{locale:P,page:r};const b=i?k(i,h,P):void 0;return b&&{locale:P,page:b}})),S=f[0]?.page;if(!S)return null;const A=S.sections.map(Qe.unzipSection);return{id:S.id||Te.nextId(),createdAt:S.createdAt,updatedAt:S.updatedAt,publishedAt:S.publishedAt,isPublic:S.isPublic??!0,templateConfig:S.templateConfig,slug:h,sections:Object.fromEntries(A.map(P=>[P.id,P])),sectionIds:A.map(P=>P.id),locales:Object.fromEntries(f.map(({locale:P,page:r})=>[P,r.meta])),dataSource:S.dataSource?Object.fromEntries([...new Set(f.flatMap(({page:P})=>Object.keys(P.dataSource??{})))].map(P=>[P,Object.fromEntries(f.map(({locale:r,page:b})=>{const D=b.dataSource?.[P];return[r,D||{}]}))])):Object.fromEntries([...new Set(f.flatMap(({page:P})=>P.sections.map(r=>r.id)))].map(P=>[P,Object.fromEntries(f.map(({locale:r,page:b})=>{const D=b.dataSource?.[P];if(D)return[r,D];const N=b.sections.find(V=>V.id===P);return[r,N?.properties||{}]}))]))}})),l=R(m?.routes?.map(({path:h})=>{const f=p?w(p,te(h)):void 0;return{...f,id:f?.id||Te.nextId(),createdAt:f?.createdAt??new Date().toISOString(),updatedAt:f?.updatedAt??new Date().toISOString(),publishedAt:new Date(0).toISOString(),path:f?.path??`/${f?.id}`,params:f?.params,handler:f?.handler??"Pages Kit",isPublic:f?.isPublic??!0,enabledGenerate:f?.enabledGenerate??!1,displayTemplateId:f?.displayTemplateId??void 0,dataSource:f?.dataSource??{}}})??[]),y=c?R(m.components?.map(({id:h})=>T(c,h))??[]):[];if(e){const h=(...f)=>{d.logger.info(`[${n?g.basename(t):g.basename(g.join(t,"../../../../"))}] importAssets:`,...f)};try{h("wait image-bin api ready"),await ht.default({resources:[`${Ie.getComponentWebEndpoint(d.IMAGE_BIN_NAME)}/api/sdk/uploads`],validateStatus:A=>A>=200&&A<=500}),h("image-bin api is ready");const f={},S={};h("start to upload assets"),await Promise.allSettled([ve(y,f,{getFilePath:A=>c&&g.join(c,A),onFinish:A=>{h(`upload ${A.length} component assets`)}}),ve(u,S,{getFilePath:(A,P)=>{const r=Ee.default(u,P.slice(0,1));return i&&g.join(i,g.dirname(r.slug),A)},onFinish:A=>{h(`upload ${A.length} page assets`)}})]),h("upload assets done"),ye.clear(),global.gc&&global.gc()}catch(f){h("Error during asset import:",f)}}const j={};if(s){const h=o&&g.join(g.dirname(o),"../../resources/components"),f=R(m.resources?.components?.map(({id:S})=>T(h,S))??[]);f.length>0&&(j.components=Object.fromEntries(f.map((S,A)=>[S.id,{index:A,component:S}])))}return{supportedLocales:m.supportedLocales,pageIds:u.map(h=>h.id),components:Object.fromEntries(y.map((h,f)=>[h.id,{index:f,data:h}])),pages:Object.fromEntries(u.map(h=>[h.id,h])),config:m.config||{},resources:j,routeIds:l.map(h=>h.id),routes:Object.fromEntries(l.map(h=>[h.id,h])),dataSourceIds:[],dataSources:{}}}finally{n&&a&&I.rmSync(a,{force:!0,recursive:!0})}}async function Se(t,e,{routes:s,mergeMode:a="byUpdateTime",deleteRoutes:n=!1,publishMode:o=void 0}={}){try{o&&d.clearPreloadComponentsCacheByMode(o)}catch(w){d.logger.error("clear preload page cache error",{error:w})}const{pages:i,pageIds:c,routeIds:p,routes:m,supportedLocales:k}=t;if(o==="production"){let w=s??[],u=null;for(const l of p??[]){const y=m?.[l];if(y?.params&&y?.params.length>0&&y?.paramsOptions&&y?.paramsOptions.length>0){const j=Q.generateParamCombinations({basePath:y.path,params:y.params,routeId:y.id,paramsOptions:y.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]}),h=Object.fromEntries(j.map(f=>[`${l}-${f.paramOptionIds.join("-")}`,f]));u={...u||{},...h},s||(w=[...w,...j.map(f=>`${l}-${f.paramOptionIds.join("-")}`)])}else s||w.push(l)}d.logger.info("routeIds to be published: ",w);for(const l of w){let y=l;if(y.includes("-")){const[f]=y.split("-");y=f}const j=m?.[y];if(!j){const f=e.pageIds.indexOf(y);f!==-1&&n&&(e.pageIds.splice(f,1),delete e.pages[y]);for(const S of e.pageIds)S.includes(`${y}-`)&&(e.pageIds.splice(e.pageIds.indexOf(S),1),delete e.pages[S]);d.logger.info("delete main route page",y);continue}if(l.includes("-")&&!u?.[l]){const f=e.pageIds.indexOf(l);f!==-1&&n&&(e.pageIds.splice(f,1),delete e.pages[l]),d.logger.info("delete page",l);continue}if(!j.displayTemplateId){d.logger.info("no display template",l);continue}const h=i[j.displayTemplateId];if(!h){d.logger.info("no template page",l);continue}if(e.pageIds.includes(l)){if(d.logger.info("has need update page",l),a==="replace")e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("replace page",l);else if(a==="byUpdateTime"){const f=e.pages[j.id];(!f||j.updatedAt&&j.updatedAt>f.updatedAt)&&(e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("replace page by update time",l))}}else e.pageIds.push(l),e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("add page",l)}if(n&&!s)for(const l of e.pageIds)w?.includes(l)||(delete e.pages[l],d.logger.info("delete page",l)),e.pageIds=[...e.pageIds].filter(y=>w?.includes(y))}else{for(const w of c){const u=i[w];if(u)if(e.pageIds.includes(u.id)){if(a==="replace")e.pages[u.id]=u;else if(a==="byUpdateTime"){const l=e.pages[u.id];(!l||u.updatedAt&&u.updatedAt>l.updatedAt)&&(e.pages[u.id]=u)}}else e.pageIds.push(u.id),e.pages[u.id]=u}for(const w of p){const u=m[w];if(u)if(e.routeIds.includes(u.id)){if(a==="replace")e.routes[u.id]=u;else if(a==="byUpdateTime"){const l=e.routes[u.id];(!l||u.updatedAt&&u.updatedAt>l.updatedAt)&&(e.routes[u.id]=u)}}else e.routeIds.push(u.id),e.routes[u.id]=u}}if(e.supportedLocales.splice(0,e.supportedLocales.length),e.supportedLocales.push(...ft.default(k)),n)for(const w of Object.keys(e.components))delete e.components[w];let T=JSON.parse(JSON.stringify(t.components));T=Object.fromEntries(await Promise.all(Object.entries(T).map(async([w,u])=>{const l=await Fe(u?.data);return[w,{...u,data:l}]}))),Object.assign(e.components,T),Object.assign(e.config,JSON.parse(JSON.stringify(t.config))),we.default(t.resources.components)||(e.resources.components=JSON.parse(JSON.stringify(t.resources.components||{})))}const Fe=d.memoizeWithFs(async t=>{if(!we.default(t?.properties))return t;if(t?.renderer?.type==="react-component"){const{script:e,PROPERTIES_SCHEMA:s}=t?.renderer||{};if(s||e&&e.includes("PROPERTIES_SCHEMA"))try{const a=await d.getExportSchemaValueFromCode(e??"","PROPERTIES_SCHEMA",t.id,s);a&&a.length>0&&t&&(t.properties={},a.forEach((n,o)=>{t?.properties&&(t.properties[n.id]={index:o,data:n})}))}catch(a){d.logger.error("getPropertiesFromCode error",{componentId:t.id,name:t.name},{error:a})}}return t},{subdir:"getPropertiesFromCode"});let se,K,ne,oe;const qe=()=>Ie.getResources({types:[{did:Pe,type:ge},{did:bt,type:ge}]}),Ut=()=>{const t=qe(),e={};return t.forEach(s=>{const a=X.globSync("**/.blocklet/pages/pages.config.yml",{cwd:s.path,absolute:!0}).at(0),n=a&&g.join(g.dirname(a),"../../chunks");if(n&&I.existsSync(n)){const o=I.readdirSync(n);for(const i of o)e[i]=g.join(n,i)}}),e};function xe(){return se=(async()=>{const t=qe();K=(await Promise.all(t.map(async s=>{const a=s.path?await Ce(s.path,{importAssets:!1}):void 0;return a?{blockletId:s.did,state:a,blockletTitle:s.title}:void 0}))).filter(s=>!!s),ne=K.reduce((s,a)=>Object.assign(s,Object.fromEntries(Object.values(a.state.pages).map(n=>n?[n?.id,{page:n,blockletId:a.blockletId}]:[]))),{});const e=K.reduce((s,a)=>Object.assign(s,Object.fromEntries(Object.values(a.state.components).map(n=>[n.data.id,{blockletId:a.blockletId,component:n.data}]))),{});oe=Object.fromEntries(await Promise.all(Object.entries(e).map(async([s,a])=>{const n=await Fe(a.component);return[s,{...a,component:n}]})))})(),se}function Be(t){const e=Re.default(async()=>{await xe().catch(s=>{d.logger.error("load resource states error",{error:s})}),await t?.({states:K,pages:ne,components:oe})},3e3,{leading:!1,trailing:!0});return e(),E.default.events.on(E.default.Events.componentAdded,e),E.default.events.on(E.default.Events.componentRemoved,e),E.default.events.on(E.default.Events.componentStarted,e),E.default.events.on(E.default.Events.componentStopped,e),E.default.events.on(E.default.Events.componentUpdated,e),E.default.events.on(me,e),()=>{E.default.events.off(E.default.Events.componentAdded,e),E.default.events.off(E.default.Events.componentRemoved,e),E.default.events.off(E.default.Events.componentStarted,e),E.default.events.off(E.default.Events.componentStopped,e),E.default.events.off(E.default.Events.componentUpdated,e),E.default.events.off(me,e)}}const Ve=Symbol.for("GLOBAL_RESOURCE_STATES_LISTENER_KEY"),Ge=Symbol.for("GLOBAL_ENV_UPDATE_LISTENER_KEY"),re=globalThis;re[Ve]?.();re[Ve]=Be(async({pages:t,components:e})=>{const s=await O.getProjectIds();d.logger.info(`start update resource states projects(${s.length})`,s),await Promise.race([new Promise(a=>{setTimeout(()=>{a({})},30*1e3)}),Promise.all(s.map(async a=>{ze({projectId:a,pages:t,components:e})}))]).catch(a=>{d.logger.error("update resource states failed:",a)})});re[Ge]?.();re[Ge]=()=>{const t=()=>{O.pageUrlMapCache.clear(),d.logger.info("[Cache CLEAR ALL] clear all page url map cache by env update")};return E.default.events.on(E.default.Events.envUpdate,t),()=>{E.default.events.off(E.default.Events.envUpdate,t)}};O.startPeriodicCheck();process.on("beforeExit",()=>{O.stopPeriodicCheck()});process.on("SIGINT",()=>{O.stopPeriodicCheck(),process.exit(0)});process.on("SIGTERM",()=>{O.stopPeriodicCheck(),process.exit(0)});async function ze({projectId:t,pages:e,components:s}){const a=O.sharedInstances[t];if(!a){d.logger.info(`projectId: ${t} not found in sharedInstances`);return}if(a.syncedStore.resources.pages=e,(await L.findByPk(t))?.useAllResources)a.syncedStore.resources.components=s;else{const i=(await Ae.findAll({where:{projectId:t}})).map(p=>p.componentId),c=Object.fromEntries(Object.entries(s||{}).filter(([p])=>i.includes(p)));a.syncedStore.resources.components=c}d.logger.info(`update [${t}] resource states:`,{pages:Object.keys(a.syncedStore.resources.pages||{}).length,components:Object.keys(a.syncedStore.resources.components||{}).length})}async function Mt(t){return ze({projectId:t,pages:ne,components:oe})}async function Nt(){d.logger.info("trigger reload all project resource"),E.default.events.emit(me)}async function Ft({ensureLoaded:t=!0}={}){return t&&(se??=xe(),await se),{states:K,pages:ne,components:oe}}exports.COMPONENT_DID=Pe;exports.PUBLISH_MODES=_t;exports.Project=L;exports.RESOURCE_TYPE=ge;exports.SITE_STATE_PATH=q;exports.STATE_MODES=Lt;exports.SiteState=O;exports.downloadAsset=$e;exports.downloadAssets=Ue;exports.fromPackage=Ce;exports.getDefaultState=_e;exports.getResourceStates=Ft;exports.initPackResourceStates=Be;exports.mergeState=Se;exports.toPackage=Ne;exports.triggerReloadAllProjectResource=Nt;exports.updateResourceStatesByProjectId=Mt;
@@ -1 +1 @@
1
- "use strict";const g=require("./chunks/components-CacZMc0_.js"),c=require("./chunks/site-state-BkjuFb4-.js"),F=require("express"),L=require("fs"),J=require("joi"),X=require("lodash/groupBy"),W=require("lodash/sortBy"),B=require("path"),G=require("@blocklet/sdk/lib/middlewares/auth"),K=require("@blocklet/sdk/lib/component"),m=e=>e&&e.__esModule?e:{default:e},u=m(L),f=m(J),C=m(X),Y=m(W),D=m(B),k=m(G),$=async(e,t,o)=>{try{const{projectId:s}=e.params;if(!s)return o();const n=await c.Project.findByPk(s);if(!n)return t?.status(404).json({error:"Project not found"});const r=e.user?.did,a=e.user?.role||"UNKNOWN_ROLE";if(!r)return t?.status(401).json({error:"Authentication required"});if(g.isMultiTenant()){const P=n.createdBy===r,y=g.getMultiTenantAllProjectAccessPassports()?.includes?.(a);if(!P&&!y)return t?.status(403).json({error:"No permission to access this project in multi-tenant mode"})}else if(!["owner","admin","pagesEditor"].includes(a))return t?.status(403).json({error:"No permission to access this project in single-tenant mode"});e.project=n,e.projectId=s,o()}catch(s){g.logger.error("Project middleware error:",s),t?.status(400).json({error:"Internal server error"})}};function b(e,t){return new Promise((o,s)=>{const n=u.default.createReadStream(e),r=u.default.createWriteStream(t);n.on("error",s),r.on("error",s),r.on("finish",o),n.pipe(r)})}async function N(e,t){await u.default.promises.mkdir(t,{recursive:!0});const o=await u.default.promises.readdir(e,{withFileTypes:!0});for(const s of o){const n=D.default.join(e,s.name),r=D.default.join(t,s.name);s.isDirectory()?await N(n,r):await b(n,r)}}async function z(e,t){(await u.default.promises.stat(e)).isDirectory()?await N(e,t):await b(e,t)}const h=(e,t,o)=>g.isMultiTenant()?k.default()(e,t,o):k.default({roles:["owner","admin","pagesEditor"]})(e,t,o),H=(e,t)=>{const o=K.getResourceExportDir({projectId:e,releaseId:t});return B.join(o,c.COMPONENT_DID,c.RESOURCE_TYPE)},w=F.Router(),T="@page",U="@component",j=":",R="ALL",q="@project",v=({pageId:e,projectId:t})=>[T,t,e].join(j),Q=e=>{const[t,o,s]=e.split(j);if(t===T)return{pageId:s,projectId:o}},x=({componentId:e,projectId:t})=>[U,t,e].join(j),V=e=>{const[t,o,s]=e.split(j);if(t===U)return{componentId:s,projectId:o}},Z=e=>[q,e].join(j),ee=e=>{const[t,o]=e.split(j);if(t===q)return o},te=e=>{try{return JSON.parse(e)}catch{}return{}};async function A(e){const t=await c.SiteState.getStateByProjectId(e,"production"),o=await c.Project.findByPk(e),s=t.pageIds.map(r=>{const a=t.pages[r];if(a)return{id:v({pageId:r,projectId:e}),name:a.slug}}).filter(Boolean),n=Y.default(Object.values(t.components),r=>r.index).map(({data:r})=>({id:x({componentId:r.id,projectId:e}),name:r.name||r.id}));return{id:Z(e),name:o?.name||"Unnamed Project",children:[{id:v({pageId:R,projectId:e}),name:"Pages",children:s},{id:x({componentId:R,projectId:e}),name:"Components",children:n}]}}w.get("/resources",h,async(e,t)=>{const{projectId:o}=te(e.query.resourcesParams);if(o){e.params={...e.params,projectId:o},await $(e,t,()=>{});const r=await A(o);t.json({resources:[r]});return}const s=await c.Project.findAll({where:{}}),n=await Promise.all(s.map(r=>A(r.id)));t.json({resources:n})});const oe=f.default.object({projectId:f.default.string().required().min(1),releaseId:f.default.string().allow(""),resources:f.default.array().items(f.default.string()).required(),locale:f.default.string().allow("")});w.post("/resources",h,async(e,t)=>{const{resources:o,projectId:s,releaseId:n}=await oe.validateAsync(e.body),r="production",a=[],P=[];for(const i of o){if(ee(i))continue;const{pageId:d,projectId:_}=Q(i)||{};if(d)d===R||d&&_&&a.push({pageId:d,projectId:_});else{const{componentId:I,projectId:p}=V(i)||{};I===R||I&&p&&P.push({componentId:I,projectId:p})}}const y=C.default(a,"projectId"),O=C.default(P,"projectId"),M=new Set([...Object.keys(y),...Object.keys(O)]),E=H(s,n);u.default.rmSync(E,{recursive:!0,force:!0}),u.default.mkdirSync(E,{recursive:!0});for(const i of M){const d=await c.SiteState.getStateByProjectId(i,r),_=y[i],I=O[i],p=_?.map(l=>l.pageId),S=I?.map(l=>l.componentId);if(p?.length||S?.length){const l=await c.toPackage(d,{exportAssets:!0,pageIds:p,componentIds:S});await z(l,E),u.default.rmSync(l,{recursive:!0,force:!0})}g.logger.info(`Exported resources for project ${i}`,{pageIds:p,componentIds:S})}t.json({})});w.get("/all-resources",h,async(e,t)=>{const{states:o}=await c.getResourceStates(),s=o?.map(n=>{const r={blockletId:n.blockletId,blockletTitle:n.blockletTitle,components:{}};if(n.state.components&&(r.components=n.state.components),Object.keys(r.components).length!==0)return r}).filter(Boolean);t.json(s)});module.exports=w;
1
+ "use strict";const g=require("./chunks/components-CacZMc0_.js"),c=require("./chunks/site-state-Vc48a38-.js"),F=require("express"),L=require("fs"),J=require("joi"),X=require("lodash/groupBy"),W=require("lodash/sortBy"),B=require("path"),G=require("@blocklet/sdk/lib/middlewares/auth"),K=require("@blocklet/sdk/lib/component"),m=e=>e&&e.__esModule?e:{default:e},u=m(L),f=m(J),C=m(X),Y=m(W),D=m(B),k=m(G),$=async(e,t,o)=>{try{const{projectId:s}=e.params;if(!s)return o();const n=await c.Project.findByPk(s);if(!n)return t?.status(404).json({error:"Project not found"});const r=e.user?.did,a=e.user?.role||"UNKNOWN_ROLE";if(!r)return t?.status(401).json({error:"Authentication required"});if(g.isMultiTenant()){const P=n.createdBy===r,y=g.getMultiTenantAllProjectAccessPassports()?.includes?.(a);if(!P&&!y)return t?.status(403).json({error:"No permission to access this project in multi-tenant mode"})}else if(!["owner","admin","pagesEditor"].includes(a))return t?.status(403).json({error:"No permission to access this project in single-tenant mode"});e.project=n,e.projectId=s,o()}catch(s){g.logger.error("Project middleware error:",s),t?.status(400).json({error:"Internal server error"})}};function b(e,t){return new Promise((o,s)=>{const n=u.default.createReadStream(e),r=u.default.createWriteStream(t);n.on("error",s),r.on("error",s),r.on("finish",o),n.pipe(r)})}async function N(e,t){await u.default.promises.mkdir(t,{recursive:!0});const o=await u.default.promises.readdir(e,{withFileTypes:!0});for(const s of o){const n=D.default.join(e,s.name),r=D.default.join(t,s.name);s.isDirectory()?await N(n,r):await b(n,r)}}async function z(e,t){(await u.default.promises.stat(e)).isDirectory()?await N(e,t):await b(e,t)}const h=(e,t,o)=>g.isMultiTenant()?k.default()(e,t,o):k.default({roles:["owner","admin","pagesEditor"]})(e,t,o),H=(e,t)=>{const o=K.getResourceExportDir({projectId:e,releaseId:t});return B.join(o,c.COMPONENT_DID,c.RESOURCE_TYPE)},w=F.Router(),T="@page",U="@component",j=":",R="ALL",q="@project",v=({pageId:e,projectId:t})=>[T,t,e].join(j),Q=e=>{const[t,o,s]=e.split(j);if(t===T)return{pageId:s,projectId:o}},x=({componentId:e,projectId:t})=>[U,t,e].join(j),V=e=>{const[t,o,s]=e.split(j);if(t===U)return{componentId:s,projectId:o}},Z=e=>[q,e].join(j),ee=e=>{const[t,o]=e.split(j);if(t===q)return o},te=e=>{try{return JSON.parse(e)}catch{}return{}};async function A(e){const t=await c.SiteState.getStateByProjectId(e,"production"),o=await c.Project.findByPk(e),s=t.pageIds.map(r=>{const a=t.pages[r];if(a)return{id:v({pageId:r,projectId:e}),name:a.slug}}).filter(Boolean),n=Y.default(Object.values(t.components),r=>r.index).map(({data:r})=>({id:x({componentId:r.id,projectId:e}),name:r.name||r.id}));return{id:Z(e),name:o?.name||"Unnamed Project",children:[{id:v({pageId:R,projectId:e}),name:"Pages",children:s},{id:x({componentId:R,projectId:e}),name:"Components",children:n}]}}w.get("/resources",h,async(e,t)=>{const{projectId:o}=te(e.query.resourcesParams);if(o){e.params={...e.params,projectId:o},await $(e,t,()=>{});const r=await A(o);t.json({resources:[r]});return}const s=await c.Project.findAll({where:{}}),n=await Promise.all(s.map(r=>A(r.id)));t.json({resources:n})});const oe=f.default.object({projectId:f.default.string().required().min(1),releaseId:f.default.string().allow(""),resources:f.default.array().items(f.default.string()).required(),locale:f.default.string().allow("")});w.post("/resources",h,async(e,t)=>{const{resources:o,projectId:s,releaseId:n}=await oe.validateAsync(e.body),r="production",a=[],P=[];for(const i of o){if(ee(i))continue;const{pageId:d,projectId:_}=Q(i)||{};if(d)d===R||d&&_&&a.push({pageId:d,projectId:_});else{const{componentId:I,projectId:p}=V(i)||{};I===R||I&&p&&P.push({componentId:I,projectId:p})}}const y=C.default(a,"projectId"),O=C.default(P,"projectId"),M=new Set([...Object.keys(y),...Object.keys(O)]),E=H(s,n);u.default.rmSync(E,{recursive:!0,force:!0}),u.default.mkdirSync(E,{recursive:!0});for(const i of M){const d=await c.SiteState.getStateByProjectId(i,r),_=y[i],I=O[i],p=_?.map(l=>l.pageId),S=I?.map(l=>l.componentId);if(p?.length||S?.length){const l=await c.toPackage(d,{exportAssets:!0,pageIds:p,componentIds:S});await z(l,E),u.default.rmSync(l,{recursive:!0,force:!0})}g.logger.info(`Exported resources for project ${i}`,{pageIds:p,componentIds:S})}t.json({})});w.get("/all-resources",h,async(e,t)=>{const{states:o}=await c.getResourceStates(),s=o?.map(n=>{const r={blockletId:n.blockletId,blockletTitle:n.blockletTitle,components:{}};if(n.state.components&&(r.components=n.state.components),Object.keys(r.components).length!==0)return r}).filter(Boolean);t.json(s)});module.exports=w;
@@ -1 +1 @@
1
- "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require("./chunks/components-CacZMc0_.js");const e=require("./chunks/site-state-BkjuFb4-.js"),u=require("@blocklet/pages-kit/utils/common");require("@blocklet/pages-kit/utils/page-model");require("@blocklet/pages-kit/utils/property");require("@blocklet/pages-kit/utils/route");require("@blocklet/sdk/lib/component");require("@blocklet/sdk/lib/config");require("@reactivedata/reactive");require("@syncedstore/core");require("fs");require("glob");require("lib0/decoding");require("lib0/encoding");require("lodash/cloneDeep");require("lodash/debounce");require("lodash/get");require("lodash/isEmpty");require("lodash/set");require("lodash/union");require("lru-cache");require("p-limit");require("path");require("sequelize");require("stream/promises");require("tar");require("ufo");require("wait-on");require("y-protocols/awareness");require("y-protocols/sync");require("yaml");require("yjs");const t=require("@blocklet/pages-kit/types/state");exports.PUBLISH_MODES=e.PUBLISH_MODES;exports.SITE_STATE_PATH=e.SITE_STATE_PATH;exports.STATE_MODES=e.STATE_MODES;exports.default=e.SiteState;exports.downloadAsset=e.downloadAsset;exports.downloadAssets=e.downloadAssets;exports.fromPackage=e.fromPackage;exports.getDefaultState=e.getDefaultState;exports.getResourceStates=e.getResourceStates;exports.initPackResourceStates=e.initPackResourceStates;exports.mergeState=e.mergeState;exports.toPackage=e.toPackage;exports.triggerReloadAllProjectResource=e.triggerReloadAllProjectResource;Object.defineProperty(exports,"nextId",{enumerable:!0,get:()=>u.nextId});Object.keys(t).forEach(r=>{r!=="default"&&!Object.prototype.hasOwnProperty.call(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:()=>t[r]})});
1
+ "use strict";Object.defineProperties(exports,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}});require("./chunks/components-CacZMc0_.js");const e=require("./chunks/site-state-Vc48a38-.js"),u=require("@blocklet/pages-kit/utils/common");require("@blocklet/pages-kit/utils/page-model");require("@blocklet/pages-kit/utils/property");require("@blocklet/pages-kit/utils/route");require("@blocklet/sdk/lib/component");require("@blocklet/sdk/lib/config");require("@reactivedata/reactive");require("@syncedstore/core");require("fs");require("glob");require("lib0/decoding");require("lib0/encoding");require("lodash/cloneDeep");require("lodash/debounce");require("lodash/get");require("lodash/isEmpty");require("lodash/set");require("lodash/union");require("lru-cache");require("p-limit");require("path");require("sequelize");require("stream/promises");require("tar");require("ufo");require("wait-on");require("y-protocols/awareness");require("y-protocols/sync");require("yaml");require("yjs");const t=require("@blocklet/pages-kit/types/state");exports.PUBLISH_MODES=e.PUBLISH_MODES;exports.SITE_STATE_PATH=e.SITE_STATE_PATH;exports.STATE_MODES=e.STATE_MODES;exports.default=e.SiteState;exports.downloadAsset=e.downloadAsset;exports.downloadAssets=e.downloadAssets;exports.fromPackage=e.fromPackage;exports.getDefaultState=e.getDefaultState;exports.getResourceStates=e.getResourceStates;exports.initPackResourceStates=e.initPackResourceStates;exports.mergeState=e.mergeState;exports.toPackage=e.toPackage;exports.triggerReloadAllProjectResource=e.triggerReloadAllProjectResource;exports.updateResourceStatesByProjectId=e.updateResourceStatesByProjectId;Object.defineProperty(exports,"nextId",{enumerable:!0,get:()=>u.nextId});Object.keys(t).forEach(r=>{r!=="default"&&!Object.prototype.hasOwnProperty.call(exports,r)&&Object.defineProperty(exports,r,{enumerable:!0,get:()=>t[r]})});
@@ -434,11 +434,7 @@ class C extends N.Doc {
434
434
  let s = C.sharedInstances[e];
435
435
  return s || (s = new C({
436
436
  path: E(q, e)
437
- }), C.sharedInstances[e] = s, qe({
438
- projectId: e,
439
- pages: ne,
440
- components: ie
441
- }), s);
437
+ }), C.sharedInstances[e] = s, s);
442
438
  }
443
439
  // 轻量级 production 状态获取,不加载 draft 数据
444
440
  static async getProductionState(e) {
@@ -1558,10 +1554,17 @@ async function qe({
1558
1554
  components: Object.keys(a.syncedStore.resources.components || {}).length
1559
1555
  });
1560
1556
  }
1561
- async function ks() {
1557
+ async function ks(t) {
1558
+ return qe({
1559
+ projectId: t,
1560
+ pages: ne,
1561
+ components: ie
1562
+ });
1563
+ }
1564
+ async function Ts() {
1562
1565
  f.info("trigger reload all project resource"), I.events.emit(he);
1563
1566
  }
1564
- async function Ts({
1567
+ async function Ds({
1565
1568
  ensureLoaded: t = !0
1566
1569
  } = {}) {
1567
1570
  return t && (re ??= ze(), await re), { states: Q, pages: ne, components: ie };
@@ -1577,10 +1580,11 @@ export {
1577
1580
  Gt as d,
1578
1581
  zt as e,
1579
1582
  Jt as f,
1580
- Ts as g,
1583
+ Ds as g,
1581
1584
  Be as h,
1582
1585
  Ht as i,
1583
- ks as j,
1586
+ Ts as j,
1584
1587
  je as m,
1585
- Kt as t
1588
+ Kt as t,
1589
+ ks as u
1586
1590
  };
@@ -1,5 +1,5 @@
1
1
  import { i as A, a as M, l as b } from "./chunks/components-BWQM8y6L.js";
2
- import { P as w, C as J, R as X, S as x, t as W, g as G } from "./chunks/site-state-BMW2lUR1.js";
2
+ import { P as w, C as J, R as X, S as x, t as W, g as G } from "./chunks/site-state-Dt2__Byi.js";
3
3
  import { Router as K } from "express";
4
4
  import a from "fs";
5
5
  import m from "joi";
@@ -1,6 +1,6 @@
1
1
  import "./chunks/components-BWQM8y6L.js";
2
- import { c as b, a as h, b as B, S as L, e as U, f as q, h as v, d as y, g as z, i as C, m as F, t as G, j as J } from "./chunks/site-state-BMW2lUR1.js";
3
- import { nextId as N } from "@blocklet/pages-kit/utils/common";
2
+ import { c as O, a as b, b as h, S as y, e as L, f as U, h as q, d as v, g as z, i as C, m as F, t as G, j as J, u as K } from "./chunks/site-state-Dt2__Byi.js";
3
+ import { nextId as Q } from "@blocklet/pages-kit/utils/common";
4
4
  import "@blocklet/pages-kit/utils/page-model";
5
5
  import "@blocklet/pages-kit/utils/property";
6
6
  import "@blocklet/pages-kit/utils/route";
@@ -32,18 +32,19 @@ import "yaml";
32
32
  import "yjs";
33
33
  export * from "@blocklet/pages-kit/types/state";
34
34
  export {
35
- b as PUBLISH_MODES,
36
- h as SITE_STATE_PATH,
37
- B as STATE_MODES,
38
- L as default,
39
- U as downloadAsset,
40
- q as downloadAssets,
41
- v as fromPackage,
42
- y as getDefaultState,
35
+ O as PUBLISH_MODES,
36
+ b as SITE_STATE_PATH,
37
+ h as STATE_MODES,
38
+ y as default,
39
+ L as downloadAsset,
40
+ U as downloadAssets,
41
+ q as fromPackage,
42
+ v as getDefaultState,
43
43
  z as getResourceStates,
44
44
  C as initPackResourceStates,
45
45
  F as mergeState,
46
- N as nextId,
46
+ Q as nextId,
47
47
  G as toPackage,
48
- J as triggerReloadAllProjectResource
48
+ J as triggerReloadAllProjectResource,
49
+ K as updateResourceStatesByProjectId
49
50
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blocklet/pages-kit-inner-components",
3
- "version": "0.6.10",
3
+ "version": "0.6.11",
4
4
  "description": "Pages Kit inner components library",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -203,8 +203,8 @@
203
203
  "yaml": "^2.5.0",
204
204
  "yjs": "^13.6.18",
205
205
  "zustand": "^4.5.5",
206
- "@blocklet/pages-kit": "^0.6.10",
207
- "@blocklet/pages-kit-block-studio": "^0.6.10"
206
+ "@blocklet/pages-kit": "^0.6.11",
207
+ "@blocklet/pages-kit-block-studio": "^0.6.11"
208
208
  },
209
209
  "devDependencies": {
210
210
  "@trivago/prettier-plugin-sort-imports": "^5.2.1",
@@ -1 +0,0 @@
1
- "use strict";const d=require("./components-CacZMc0_.js"),F=require("@syncedstore/core"),Je=require("yjs"),Ke=require("@blocklet/pages-kit/utils/data-source"),Q=require("@blocklet/pages-kit/utils/route"),He=require("lodash"),We=require("@blocklet/sdk/lib/config"),I=require("fs"),g=require("path"),Te=require("@blocklet/pages-kit/utils/common"),Qe=require("@blocklet/pages-kit/utils/page-model"),Xe=require("@blocklet/pages-kit/utils/property"),Ie=require("@blocklet/sdk/lib/component"),Ze=require("@reactivedata/reactive"),X=require("glob"),et=require("lib0/decoding"),tt=require("lib0/encoding"),st=require("lodash/cloneDeep"),at=require("lodash/debounce"),nt=require("lodash/get"),ot=require("lodash/isEmpty"),rt=require("lodash/set"),it=require("lodash/union"),be=require("lru-cache"),ct=require("p-limit"),C=require("sequelize"),lt=require("stream/promises"),pt=require("tar"),Y=require("ufo"),ut=require("wait-on"),z=require("y-protocols/awareness"),le=require("y-protocols/sync"),dt=require("yaml");require("sqlite3");require("@blocklet/pages-kit/types/state");const M=t=>t&&t.__esModule?t:{default:t};function ae(t){if(t&&t.__esModule)return t;const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const s in t)if(s!=="default"){const a=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,a.get?a:{enumerable:!0,get:()=>t[s]})}}return e.default=t,Object.freeze(e)}const $=ae(Je),E=M(We),pe=ae(et),v=ae(tt),ft=M(st),Re=M(at),Ee=M(nt),we=M(ot),De=M(rt),gt=M(it),mt=M(ct),ht=M(ut),x=ae(dt),yt=C.DataTypes.sqlite.DATE.parse;C.DataTypes.sqlite.DATE.parse=(t,e)=>typeof t=="number"?new Date(t):yt(t,e);const U=new C.Sequelize({dialect:"sqlite",storage:d.databaseUrl,benchmark:process.env.ENABLE_SEQUELIZE_BENCHMARK==="true",retry:{match:[/SQLITE_BUSY/],name:"query",max:10},logging:process.env.ENABLE_SEQUELIZE_LOGGING==="true"?console.log:!1});U.query("pragma journal_mode = WAL;");U.query("pragma synchronous = normal;");U.query("pragma journal_size_limit = 33554432;");U.query("pragma cache_size = -2000;");U.query("pragma mmap_size = 33554432;");process.on("SIGINT",async()=>{await U.close(),process.exit(0)});process.on("SIGTERM",async()=>{await U.close(),process.exit(0)});async function St(t,e){try{if(t.getDialect()!=="sqlite")return;const[s]=await t.query("SELECT 1");if(!s||s.length===0)return;await t.query("PRAGMA shrink_memory;")}catch(s){if(s.name==="SequelizeConnectionError"||s?.message&&/closed!/.test(s.message))return;console.error("Failed to cleanup SQLite memory",e,s)}}let fe=null;fe&&clearInterval(fe);fe=setInterval(async()=>{d.logger.info("Start cleanupSqliteMemory"),await St(U,d.databaseUrl),d.logger.info("End cleanupSqliteMemory")},60*1e3*10);class Ae extends C.Model{}Ae.init({id:{type:C.DataTypes.UUID,allowNull:!1,primaryKey:!0,defaultValue:C.DataTypes.UUIDV4},projectId:{type:C.DataTypes.UUID,allowNull:!1},componentId:{type:C.DataTypes.STRING,allowNull:!1}},{sequelize:U,tableName:"ProjectComponents",timestamps:!1});class L extends C.Model{static async getProjectByIdOrSlug(e){return L.findOne({where:{[C.Op.or]:[{id:e},{slug:e}]}})}}L.init({id:{type:C.DataTypes.UUID,defaultValue:C.DataTypes.UUIDV4,primaryKey:!0},name:{type:C.DataTypes.STRING,allowNull:!1},description:C.DataTypes.TEXT,createdAt:C.DataTypes.DATE,updatedAt:C.DataTypes.DATE,createdBy:{type:C.DataTypes.STRING,allowNull:!1},updatedBy:{type:C.DataTypes.STRING,allowNull:!1},slug:C.DataTypes.STRING,icon:C.DataTypes.STRING,pinnedAt:C.DataTypes.DATE,useAllResources:C.DataTypes.BOOLEAN,npmSecret:C.DataTypes.STRING,relatedBlocklets:{type:C.DataTypes.JSON,allowNull:!1,defaultValue:{},get(){const t=this.getDataValue("relatedBlocklets");if(typeof t=="object")return t??{};try{return t?JSON.parse(t):{}}catch(e){return d.logger.error("Failed to parse relatedBlocklets",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("relatedBlocklets",t?JSON.stringify(t):"{}")}catch(e){d.logger.error("Failed to set relatedBlocklets",{error:e,value:t}),this.setDataValue("relatedBlocklets","{}")}}},productionState:{type:C.DataTypes.JSON,allowNull:!1,defaultValue:{},get(){const t=this.getDataValue("productionState");if(typeof t=="object")return t??{};try{return t?JSON.parse(t):{}}catch(e){return d.logger.error("Failed to parse productionState",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("productionState",t?JSON.stringify(t):"{}")}catch(e){d.logger.error("Failed to set productionState",{error:e,value:t}),this.setDataValue("productionState","{}")}}}},{sequelize:U,paranoid:!0});L.hasMany(Ae,{foreignKey:"projectId",as:"components"});const It="z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o",ge="page",me="trigger-reload-project-resource",Pe=It,bt="z2qa7BQdkEb3TwYyEYC1psK6uvmGnHSUHt5RM";function Z(t){t.observeDeep(e=>{e.some(s=>s.changes.keys.has("updatedAt")||s.changes.keys.has("publishedAt"))||t.set("updatedAt",new Date().toISOString())})}function Le(){return I.mkdtempSync(g.join(E.default.env.dataDir,"tmp-"))}function ee(t,e,s=[]){return Array.isArray(t)?t.flatMap((a,n)=>ee(a,e,[...s,n])):typeof t=="object"?t===null?[]:Object.entries(t).flatMap(([a,n])=>ee(n,e,[...s,a])):e(t)?[s]:[]}function R(t){return t.filter(e=>e!=null)}function Et(t){t.pages&&Object.keys(t.pages).forEach(s=>{const a=F.getYjsValue(t.pages[s]);a&&a instanceof $.Map&&Z(a)});const e=F.getYjsValue(t.pages);e&&e instanceof $.Map&&e.observe(s=>{s.changes.keys.forEach((a,n)=>{if(a.action==="add"){const o=F.getYjsValue(t.pages[n]);o&&o instanceof $.Map&&Z(o)}})})}function wt(t){t.routes&&Object.keys(t.routes).forEach(s=>{const a=F.getYjsValue(t.routes?.[s]);a&&a instanceof $.Map&&Z(a)});const e=F.getYjsValue(t.routes);e&&e instanceof $.Map&&e.observe(s=>{s.changes.keys.forEach((a,n)=>{if(a.action==="add"){const o=F.getYjsValue(t.routes?.[n]);o&&o instanceof $.Map&&Z(o)}})})}function At(t,e){for(const s of e||Object.keys(t.routes||{})){let a=s,n=[];if(s.includes("-")){const[o,...i]=s.split("-");a=o,n=i||[]}if(t.routes?.[a]!==void 0){t.routes[a].publishedAt=new Date().toISOString();const o=t.routes[a];if(!o||!o.params||o.params.length===0)continue;if(s.includes("-")&&n.length>0){const i=Q.getRouteMetaDataByOptionIds(n,o);i&&(i.publishedAt=new Date().toISOString())}if(!e){const i=Q.generateParamCombinations({basePath:o.path,params:o.params,routeId:o.id,paramsOptions:o.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const c of i)c.routeMetaData??={},c.routeMetaData.publishedAt=new Date().toISOString()}}}}function ue({page:t,route:e,state:s,routeId:a,routePathInfo:n}){d.logger.info(`Executing datasource data assembly, routeId: ${a}, routePathInfo: ${JSON.stringify(n)}`);const o={...He.cloneDeep(t),id:a,slug:n?.path??e.path,createdAt:e.createdAt,updatedAt:n?.routeMetaData?.updatedAt??e.updatedAt,publishedAt:n?.routeMetaData?.publishedAt??e.publishedAt,isPublic:(n?.routeMetaData?.isPublic??e.isPublic)&&e.isPublic};for(const i of s.supportedLocales){if(e.dataSource){let c=e.id;n&&(c=n.paramOptionIds.join("-"));const p=e.dataSource.pathDataMappings?.[c]?.dataCache?.[i.locale]??e.dataSource.pathDataMappings?.[c]?.dataCache?.[s.config.defaultLocale||"en"];if(!p)continue;Ke.setPageDataSource(o,s,i.locale,p)}n&&n.routeMetaData&&(n.routeMetaData.publishedAt=new Date().toISOString())}return o}const Pt=30*60*1e3,B=new be.LRUCache({max:100,ttl:Pt});function Ot(t,e=[]){let s=0;const a=Array.from(B.keys()),n=[];for(const o of t){n.push(`page-html:prod:${o}:lang-path=none`);for(const i of e)n.push(`page-html:prod:/${i}${o}:lang-path=${i}`)}for(const o of a){const i=o.split(":lang-path=")[0]||"";for(const c of n){const m=(c.split(":lang-path=")[0]||"").replace(/\/:[^/]+/g,"");if(i.startsWith(m)){B.delete(o),s++,d.logger.info(`[Cache CLEAR] key: ${o}`);break}}}return d.logger.info(`[Cache CLEAR] cleared ${s} entries for patterns:`,n),s}function Ct({projectId:t,projectSlug:e,supportedLocales:s=[]}){let a=0;const n=Array.from(B.keys()),o=[];o.push(`page-html:prod:/${t}`),e&&e!==t&&o.push(`page-html:prod:/${e}`);for(const i of s)o.push(`page-html:prod:/${i}/${t}`),e&&e!==t&&(e!=="/"?o.push(`page-html:prod:/${i}/${e}`):o.push(`page-html:prod:/${i}`));for(const i of n)for(const c of o)if(i.startsWith(c)){B.delete(i),a++,d.logger.info(`[Cache CLEAR PROJECT] key: ${i}`);break}return d.logger.info(`[Cache CLEAR PROJECT] cleared ${a} entries for project ${t}${e?` (slug: ${e})`:""}`),a}function jt(){const t=B.size;return B.clear(),d.logger.info(`[Cache CLEAR ALL] cleared ${t} entries`),t}E.default.events.on(E.default.Events.envUpdate,jt);const{uploadToMediaKit:Tt}=require("@blocklet/uploader-server"),Oe=/^\w+(\w|-|\.)+\w+\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm)$/,J=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/i,ke=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/gi,Dt=1e4,kt=3e4,H=0,de=1,vt=0,Rt=1,he=E.default,q=g.join(process.env.BLOCKLET_DATA_DIR,"site-state"),Lt=["production","draft"],_t=["production"];function te(t){return t?.replace(/\//g,"|")||""}function _e(){const t=he.env.languages?.map(s=>({locale:s.code,name:s.name}))||[],e=t[0]?.locale||"en";return{pageIds:[],pages:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{},components:{},supportedLocales:t,config:{defaultLocale:e},resources:{}}}class O extends $.Doc{constructor(e){super(),this.options=e,I.existsSync(this.draftYjsFilePath)&&$.applyUpdate(this,I.readFileSync(this.draftYjsFilePath)),this.syncedStore=Ze.reactive(F.syncedStore({pages:{},pageIds:[],components:{},supportedLocales:[],config:{},resources:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{}},this)),this.initObserver(),this.on("update",this.updateHandler),this.awareness=new z.Awareness(this),this.awareness.on("update",this.awarenessChangeHandler),this.ensureDataStructure()}static RELEASE_DELAY=5*60*1e3;static PERIODIC_CHECK_INTERVAL=2*60*60*1e3;static sharedInstances={};static pageUrlMapCache=new be.LRUCache({max:100,ttl:1e3*60*60*24});static periodicCheckTimer;static safeDeleteProjectStateDir(e){if(!e)throw new Error("Should provide project context");try{const s=g.join(q,e),a=g.join(q,`@del-${e}`);I.renameSync(s,a)}catch(s){d.logger.error("Failed to safe delete project state dir:",s)}}static async getProjectIds(){return(await L.findAll({attributes:["id"],raw:!0}))?.map(e=>e.id)}static get projectIds(){return X.globSync("*/",{cwd:q,ignore:["@del-*","@tmp-*",".*","staging","production","@backup-*","undefined"]})}static get allShared(){return this.projectIds.map(e=>O.shared(e))}static shared(e){if(!e)throw new Error("Should provide project context");let s=O.sharedInstances[e];return s||(s=new O({path:g.join(q,e)}),O.sharedInstances[e]=s,ze({projectId:e,pages:ne,components:oe}),s)}static async getProductionState(e){const s=await L.findByPk(e,{attributes:["productionState"]});if(we.default(s?.productionState)){const a=g.join(q,e,"production"),n=await Ce(a,{includeResources:!0})??_e();if(!n?.config?.defaultLocale){n.config??={};const o=he.env.languages?.map(i=>({locale:i.code,name:i.name}))||[];n.config.defaultLocale=o[0]?.locale}return n}return s?.productionState}destroy(){this.cancelRelease(),this.save({flush:!0}),this.conns.forEach((s,a)=>this.closeConn(a)),this.awareness.destroy();const e=g.basename(this.options.path);delete O.sharedInstances[e],super.destroy()}initObserver(){Et(this.syncedStore),wt(this.syncedStore)}get draftYjsFilePath(){return g.join(this.options.path,"draft.yjs")}static async getStateByProjectId(e,s){if(s==="draft"){const a=O.shared(e);return JSON.parse(JSON.stringify(a.syncedStore))}return O.getProductionState(e)}async getState(e){if(e==="draft")return JSON.parse(JSON.stringify(this.syncedStore));const s=g.basename(this.options.path);return O.getProductionState(s)}async setState(e,s){const a=await Ne(s,{exportAssets:!1,includeResources:!0}),n=this.getPublishDir(e);if(I.mkdirSync(g.dirname(n),{recursive:!0}),I.rmSync(n,{force:!0,recursive:!0}),I.renameSync(a,n),e==="production"){const o=g.basename(this.options.path);O.pageUrlMapCache.delete(o),await L.update({productionState:{...s}},{where:{id:o}})}}getPublishDir(e){return g.join(this.options.path,e)}syncedStore;conns=new Map;awareness;releaseTimer;awarenessChangeHandler=({added:e,updated:s,removed:a},n)=>{const o=e.concat(s,a);if(n!==null){const p=this.conns.get(n);p&&(e.forEach(m=>{p.add(m)}),a.forEach(m=>{p.delete(m)}))}const i=v.createEncoder();v.writeVarUint(i,de),v.writeVarUint8Array(i,z.encodeAwarenessUpdate(this.awareness,o));const c=v.toUint8Array(i);this.conns.forEach((p,m)=>this.send(m,c))};updateHandler=e=>{const s=v.createEncoder();v.writeVarUint(s,H),le.writeUpdate(s,e);const a=v.toUint8Array(s);this.conns.forEach((n,o)=>this.send(o,a))};ensureDataStructure=()=>{const{supportedLocales:e,pages:s,pageIds:a,config:n,routes:o,routeIds:i}=this.syncedStore;{const c=new Set(Object.keys(s));let p=0;for(;p<a.length;){const m=a[p];c.has(m)?(c.delete(m),p++):a.splice(p,1)}}{const c=new Set(Object.keys(o));let p=0;for(;p<i.length;){const m=i[p];c.has(m)?(c.delete(m),p++):i.splice(p,1)}}e.splice(0,e.length),e.push(...he.env.languages.map(c=>({locale:c.code,name:c.name}))),n.defaultLocale=e[0]?.locale;{let c=0;const p=new Set;for(;c<e.length;){const{locale:m}=e[c];p.has(m)?e.splice(c,1):(c++,p.add(m))}}};send=(e,s)=>{e.readyState!==vt&&e.readyState!==Rt&&this.closeConn(e);try{e.send(s,a=>{a&&this.closeConn(e)})}catch{this.closeConn(e)}};closeConn=e=>{if(e.removeAllListeners(),this.conns.has(e)){const s=this.conns.get(e);this.conns.delete(e),s&&z.removeAwarenessStates(this.awareness,Array.from(s),null)}e.close(),this.checkAndScheduleRelease()};checkAndScheduleRelease(){this.conns.size===0&&this.scheduleRelease()}scheduleRelease(){this.cancelRelease();const e=g.basename(this.options.path);this.releaseTimer=setTimeout(()=>{d.logger.info(`[SiteState] releasing instance due to no active connections: ${e}`),this.conns.size===0&&(this.releaseTimer=void 0,this.destroy())},O.RELEASE_DELAY),d.logger.info(`[SiteState] scheduled release for project ${e} in ${O.RELEASE_DELAY/1e3}s`)}cancelRelease(){if(this.releaseTimer){clearTimeout(this.releaseTimer),this.releaseTimer=void 0;const e=g.basename(this.options.path);d.logger.info(`[SiteState] cancelled scheduled release for project ${e}`)}}autoSave=Re.default(()=>{I.mkdirSync(g.dirname(this.draftYjsFilePath),{recursive:!0}),I.writeFileSync(this.draftYjsFilePath,$.encodeStateAsUpdate(this))},Dt);save=({flush:e=!1}={})=>{this.autoSave(),e&&this.autoSave.flush()};publish=async({mode:e,routes:s})=>{const a=await this.getState("draft"),n=await this.getState("production");await Se(a,n,{routes:s,mergeMode:"replace",deleteRoutes:!0,publishMode:e}),n.config.publishedAt=new Date().getTime(),At(this.syncedStore,s),await this.setState(e,n),await this.clearPageCacheForRoutes(s,n)};mergeState=async(e,s)=>{const a=JSON.parse(JSON.stringify(s));e.config.fontFamily??={};const n=a.config?.fontFamily,o=e.config?.fontFamily;e.config.fontFamily.title=n?.title||o?.title,e.config.fontFamily.description=n?.description||o?.description,await new Promise((i,c)=>{this.transact(async()=>{try{const p=await Se(e,s);i(p)}catch(p){c(p)}})})};clearPageCacheForRoutes=async(e,s)=>{const a=g.basename(this.options.path),o=(await L.findByPk(a))?.slug||a;if(d.logger.info(`[SiteState] clearing page cache for project ${a}, routes:`,e||[]),!e||e.length===0){Ct({projectId:a,projectSlug:o,supportedLocales:s.supportedLocales.map(m=>m.locale)});return}const i=s.supportedLocales.map(m=>m.locale),c=[],p=e.filter(m=>s.pages[m]);for(const m of p){const T=s.pages[m].slug;o&&o!==a&&(o==="/"?c.push(T):c.push(`/${o}${T}`)),c.push(`/${a}${T}`)}if(d.logger.info(`[SiteState] clearing page cache for project ${a}, pathPatterns:`,c),c.length>0){const m=Ot(c,i);d.logger.info(`[SiteState] cleared ${m} page cache entries for project ${a}, routes:`,e)}};addConnection=e=>{if(this.conns.has(e))return;this.cancelRelease(),e.binaryType="arraybuffer",this.conns.set(e,new Set),e.on("message",n=>this.messageListener(e,new Uint8Array(n)));let s=!0;const a=setInterval(()=>{if(!s)this.conns.has(e)&&this.closeConn(e),clearInterval(a);else if(this.conns.has(e)){s=!1;try{e.ping()}catch{this.closeConn(e),clearInterval(a)}}},kt);e.on("close",()=>{this.closeConn(e),clearInterval(a)}),e.on("pong",()=>{s=!0});{const n=v.createEncoder();v.writeVarUint(n,H),le.writeSyncStep1(n,this),this.send(e,v.toUint8Array(n));const o=this.awareness.getStates();if(o.size>0){const i=v.createEncoder();v.writeVarUint(i,de),v.writeVarUint8Array(i,z.encodeAwarenessUpdate(this.awareness,Array.from(o.keys()))),this.send(e,v.toUint8Array(i))}}};messageListener=(e,s)=>{try{const a=v.createEncoder(),n=pe.createDecoder(s),o=pe.readVarUint(n);switch(o){case H:v.writeVarUint(a,H),le.readSyncMessage(n,a,this,null),v.length(a)>1&&(this.ensureDataStructure(),this.send(e,v.toUint8Array(a)));break;case de:{z.applyAwarenessUpdate(this.awareness,pe.readVarUint8Array(n),e);break}default:d.logger.warn(`Unsupported messageType ${o}`)}}catch(a){d.logger.error(a)}this.save()};static async pageUrlMap(e,s){let a=[];s?a=[s]:a=await this.getProjectIds();let n={};if(e==="production"&&a?.length){const o=new Map(a?.map(i=>[i,!0])||[]);for(const i of a){const c=O.pageUrlMapCache.get(i);c&&(n={...n,...c},o.delete(i))}a=Array.from(o.keys())}if(a?.length){const o=await L.findAll({where:{id:{[C.Op.in]:a}}});await Promise.all(o?.map(async i=>{const c=i.id,p=i.slug||c,m={},k=e==="production"&&i?.productionState?i.productionState:await O.getStateByProjectId(i.id,e),T=gt.default(E.default.env.languages?.map(u=>u.code)||[],k.supportedLocales?.map(u=>u.locale)||[]),w=(u,l)=>{p&&(m[Y.joinURL("/",p,u)]={...l,shouldRedirect:!0,mainPage:!0}),m[Y.joinURL("/",c,u)]={...l,shouldRedirect:!0,mainPage:!0};for(const y of T){const j={...l,locale:y};m[Y.joinURL("/",y,c,u)]=j,p&&(m[Y.joinURL("/",y,p,u)]=j)}};if(e==="draft")for(const u of k.routeIds||[]){const l=k?.routes?.[u];if(!l)continue;if(l.params&&l.params.length>0){const h=Q.generateParamCombinations({basePath:l.path,params:l.params,routeId:l.id,paramsOptions:l.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const f of h){const S=f.path,A={projectId:c,projectSlug:p,pageSlug:S,pageId:l.displayTemplateId||"",routeId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic&&f?.routeMetaData?.isPublic};w(S,A)}}const y=l.path,j={projectId:c,projectSlug:p,pageSlug:y,pageId:l.displayTemplateId||"",routeId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic};w(y,j)}for(const u of k.pageIds){const l=k.pages[u];if(!l||e==="production"&&!l.isPublic)continue;const y=l.slug,j=i.slug||c,h={projectId:c,projectSlug:j,pageSlug:y,pageId:u,defaultLocale:T?.[0],locales:T,publishedAt:k.config.publishedAt,isPublic:l.isPublic,templateConfig:l.templateConfig};w(y,h)}e==="production"&&O.pageUrlMapCache.set(c,m),n={...n,...m}}))}return n}getDocumentSize(){return $.encodeStateAsUpdate(this).byteLength}static getInstancesSizeInfo(){const e=[];for(const[s,a]of Object.entries(O.sharedInstances)){const n=a.getDocumentSize();e.push({projectId:s,sizeInBytes:n,sizeInMB:`${(n/(1024*1024)).toFixed(2)} MB`,activeConnections:a.conns.size})}return e}static startPeriodicCheck(){this.periodicCheckTimer||(this.periodicCheckTimer=setInterval(()=>{this.performPeriodicCheck()},this.PERIODIC_CHECK_INTERVAL),d.logger.info(`[SiteState] periodic check started, interval: ${this.PERIODIC_CHECK_INTERVAL/(60*60*1e3)} hours`))}static stopPeriodicCheck(){this.periodicCheckTimer&&(clearInterval(this.periodicCheckTimer),this.periodicCheckTimer=void 0,d.logger.info("[SiteState] periodic check stopped"))}static performPeriodicCheck(){const e=Object.keys(O.sharedInstances).length,s=[],a=[];for(const[n,o]of Object.entries(O.sharedInstances))o.conns.size===0?s.push({projectId:n,instance:o}):a.push({projectId:n,connections:o.conns.size});if(d.logger.info(`[SiteState] periodic check summary: total instances: ${e}, with connections: ${a.length}, without connections: ${s.length}`),s.length>0){d.logger.info(`[SiteState] releasing ${s.length} instances without connections:`,s.map(o=>o.projectId));let n=0;for(const{projectId:o,instance:i}of s)try{d.logger.info(`[SiteState] releasing instance due to periodic check: ${o}`),i.destroy(),n++}catch(c){d.logger.error(`[SiteState] failed to release instance ${o} during periodic check:`,c)}d.logger.info(`[SiteState] periodic check completed: ${n}/${s.length} instances released successfully`)}else e>0?d.logger.debug("[SiteState] periodic check: all instances have active connections"):d.logger.debug("[SiteState] periodic check: no instances exist")}}async function $t(t,e,s){if(!t||!I.existsSync(t)||!I.lstatSync(t).isFile())return null;let a=s[t];return a||(a=(async()=>{try{return(await Tt({filePath:t,fileName:e}))?.data?.filename}catch(n){return d.logger.error(`Failed to upload asset ${t}:`,n),null}})(),s[t]=a),a}const $e=async(t,e)=>{const s=g.basename(t),a=await Ie.call({name:Pe,path:Y.joinURL("/uploads",s),responseType:"stream",method:"GET"});if(a.status>=200&&a.status<400){const n=I.createWriteStream(e);await lt.pipeline(a.data,n)}else throw new Error(`download asset failed ${a.status}`)},Ue=async(t,e)=>{await Promise.all(t.map(async s=>{try{await $e(s,g.join(e,g.basename(s)))}catch(a){d.logger.error(`Failed to export assets: ${s}, ${a}`)}}))};function Me(t){return Oe.test(t)?[t]:J.test(t)?(ke.lastIndex=0,Array.from(t.matchAll(ke)).map(s=>s[1]).filter(s=>!!s)):[]}async function W(t,e,s){const{getFilename:a,exportAssets:n}=s,o=g.join(e,a(t));if(I.mkdirSync(g.dirname(o),{recursive:!0}),I.writeFileSync(o,x.stringify(t)),n){const c=ee(t,p=>typeof p=="string"&&(Oe.test(p)||J.test(p))).map(p=>{const m=Ee.default(t,p);return Me(m)}).flat().filter(Boolean);await Ue(c,g.dirname(o))}}const ye=new be.LRUCache({max:100,ttl:1*60*1e3});async function ve(t,e,s){const a=ee(t,c=>typeof c=="string"&&(Oe.test(c)||J.test(c))),n=mt.default(2),o=a.map(c=>n(async()=>{try{const p=Ee.default(t,c),m=Me(p);for(const k of m){const T=g.basename(k),w=s.getFilePath(k,c),u=w?`${w}:${T}`:T,l=ye.get(u);if(l){J.test(p)||De.default(t,c,l);return}const y=await $t(w,T,e);y&&(J.test(p)||De.default(t,c,y),ye.set(u,y))}}catch(p){d.logger.error(`Failed to process upload for path ${c.join(".")}:`,p.message||p.reason)}})),i=await Promise.allSettled(o);s.onFinish?.(i)}async function Ne(t,{exportAssets:e,pageIds:s="all",componentIds:a="all",rawConfig:n,includeResources:o=!1,routeIds:i="all"}={}){const c=s==="all"?t.pageIds:s,p=Xe.getComponentDependencies({state:t,pageIds:c,componentIds:a==="all"?Object.keys(t.components):a}),m=i==="all"?t.routeIds:i,k=r=>({id:r.id,name:r.name,isTemplateSection:r.isTemplateSection??!1,templateDescription:r.templateDescription,llmConfig:r.llmConfig,component:r.component,config:r.config,visibility:r.visibility,sections:r?.sectionIds?R(r?.sectionIds?.map(b=>{const D=r.sections?.[b];return D&&k(D)})):void 0}),T=(r,b)=>({id:r.id,createdAt:r.createdAt,updatedAt:r.updatedAt,publishedAt:r.publishedAt,isPublic:r.isPublic??!0,templateConfig:r.templateConfig,meta:r.locales?.[b]??{},sections:R(r.sectionIds.map(D=>{const N=r.sections[D];return N&&k(N)})),dataSource:Object.fromEntries(Object.entries(r.dataSource||{}).map(([D,N])=>[D,N?.[b]??{}]))}),w=r=>({id:r.id,createdAt:r.createdAt,updatedAt:r.updatedAt,publishedAt:r.publishedAt,path:r.path,handler:r.handler,isPublic:r.isPublic??!0,params:r.params??[],enabledGenerate:r.enabledGenerate??!1,displayTemplateId:r.displayTemplateId,dataSource:r.dataSource}),u=R(m.map(r=>{const b=t.routes[r];return b&&w(b)})),l=R(t.supportedLocales.map(r=>r.locale).flatMap(r=>c.map(b=>{const D=t.pages[b];return D&&{locale:r,slug:D.slug,page:T(D,r)}}))),y=Le(),j=g.join(y,"pages");I.mkdirSync(j,{recursive:!0});const h=g.join(y,"components");I.mkdirSync(h,{recursive:!0});const f=g.join(y,"routes");I.mkdirSync(f,{recursive:!0});for(const{locale:r,slug:b,page:D}of l)await W(D,j,{getFilename:()=>`${te(b)||"index"}.${r}.yml`,exportAssets:e});for(const r of u)await W(r,f,{getFilename:()=>`${te(r.path)||"index"}.yml`,exportAssets:e});for(const r of p){const b=t.components[r]?.data;b&&await W(b,h,{getFilename:D=>`${D.name||"unnamed"}.${D.id}.yml`,exportAssets:e})}const S=g.join(y,".blocklet/pages/pages.config.yml");I.mkdirSync(g.dirname(S),{recursive:!0});const A={pages:R(c.map(r=>{const b=t.pages[r];return b&&{id:r,slug:b.slug}})),routes:R(m.map(r=>{const b=t.routes[r];return b&&{id:r,path:b.path}})),components:R(p.map(r=>{const b=t.components[r]?.data;return b&&{id:r,name:b.name}})),...o?{resources:{components:R(Object.keys(t.resources?.components||{}).filter(r=>p.includes(r)).map(r=>({id:r,name:t.resources?.components?.[r]?.component?.name})))}}:{},supportedLocales:t.supportedLocales,config:t.config};I.writeFileSync(S,x.stringify(A));const P=g.join(y,"config.source.json");if(n&&I.writeFileSync(P,JSON.stringify(n)),o){const r=g.join(y,"resources"),b=g.join(r,"components");I.mkdirSync(b,{recursive:!0});for(const V of Object.keys(t?.resources?.components??{}).filter(_=>p.includes(_))){const _=t.resources?.components?.[V]?.component;_&&await W(_,b,{getFilename:G=>`${G.name||"unnamed"}.${G.id}.yml`,exportAssets:e})}const D=g.join(y,"chunks");I.mkdirSync(D,{recursive:!0});const N=Ut();for(const V of Object.keys(t?.resources?.components??{}).filter(_=>p.includes(_))){const _=t.resources?.components?.[V]?.component;if(_&&_.renderer?.type==="react-component"){const G=_.renderer?.chunks??[];if(G?.length>0)for(const ie of G){const je=g.join(D,ie),ce=N?.[ie];try{ce&&I.existsSync(ce)&&!I.existsSync(je)&&I.copyFileSync(ce,je)}catch(Ye){d.logger.error(`copy chunk ${ie} error`,Ye.message)}}}}}return y}async function Ce(t,{importAssets:e,includeResources:s}={}){if(!I.existsSync(t))return null;let a,n=!1;try{I.lstatSync(t).isDirectory()?a=t:/\.(tgz|gz|tar)$/.test(t)&&(n=!0,a=Le(),await pt.x({file:t,C:a}));const o=X.globSync("**/.blocklet/pages/pages.config.yml",{cwd:a,absolute:!0}).at(0),i=o&&g.join(g.dirname(o),"../../pages"),c=o&&g.join(g.dirname(o),"../../components"),p=o&&g.join(g.dirname(o),"../../routes");if(!o)return null;const m=x.parse(I.readFileSync(o).toString()),k=(h,f,S)=>{let A=g.join(h,`${f}${S?`.${S}`:""}.yml`);return(!I.existsSync(A)||!I.lstatSync(A).isFile())&&(A=g.join(h,f,`index${S?`.${S}`:""}.yml`),!I.existsSync(A)||!I.lstatSync(A))?null:x.parse(I.readFileSync(A).toString())},T=(h,f)=>{try{const S=X.globSync(`*.${f}.yml`,{cwd:h,absolute:!0})[0];return S?x.parse(I.readFileSync(S).toString()):null}catch(S){d.logger.error("parse component error",S)}return null},w=(h,f)=>{let S=g.join(h,`${f}.yml`);return(!I.existsSync(S)||!I.lstatSync(S).isFile())&&(S=g.join(h,f,"index.yml"),!I.existsSync(S)||!I.lstatSync(S))?null:x.parse(I.readFileSync(S).toString())},u=R(m.pages.map(({slug:h})=>{const f=R(m.supportedLocales.map(({locale:P})=>{const r=i?k(i,te(h),P):void 0;if(r)return{locale:P,page:r};const b=i?k(i,h,P):void 0;return b&&{locale:P,page:b}})),S=f[0]?.page;if(!S)return null;const A=S.sections.map(Qe.unzipSection);return{id:S.id||Te.nextId(),createdAt:S.createdAt,updatedAt:S.updatedAt,publishedAt:S.publishedAt,isPublic:S.isPublic??!0,templateConfig:S.templateConfig,slug:h,sections:Object.fromEntries(A.map(P=>[P.id,P])),sectionIds:A.map(P=>P.id),locales:Object.fromEntries(f.map(({locale:P,page:r})=>[P,r.meta])),dataSource:S.dataSource?Object.fromEntries([...new Set(f.flatMap(({page:P})=>Object.keys(P.dataSource??{})))].map(P=>[P,Object.fromEntries(f.map(({locale:r,page:b})=>{const D=b.dataSource?.[P];return[r,D||{}]}))])):Object.fromEntries([...new Set(f.flatMap(({page:P})=>P.sections.map(r=>r.id)))].map(P=>[P,Object.fromEntries(f.map(({locale:r,page:b})=>{const D=b.dataSource?.[P];if(D)return[r,D];const N=b.sections.find(V=>V.id===P);return[r,N?.properties||{}]}))]))}})),l=R(m?.routes?.map(({path:h})=>{const f=p?w(p,te(h)):void 0;return{...f,id:f?.id||Te.nextId(),createdAt:f?.createdAt??new Date().toISOString(),updatedAt:f?.updatedAt??new Date().toISOString(),publishedAt:new Date(0).toISOString(),path:f?.path??`/${f?.id}`,params:f?.params,handler:f?.handler??"Pages Kit",isPublic:f?.isPublic??!0,enabledGenerate:f?.enabledGenerate??!1,displayTemplateId:f?.displayTemplateId??void 0,dataSource:f?.dataSource??{}}})??[]),y=c?R(m.components?.map(({id:h})=>T(c,h))??[]):[];if(e){const h=(...f)=>{d.logger.info(`[${n?g.basename(t):g.basename(g.join(t,"../../../../"))}] importAssets:`,...f)};try{h("wait image-bin api ready"),await ht.default({resources:[`${Ie.getComponentWebEndpoint(d.IMAGE_BIN_NAME)}/api/sdk/uploads`],validateStatus:A=>A>=200&&A<=500}),h("image-bin api is ready");const f={},S={};h("start to upload assets"),await Promise.allSettled([ve(y,f,{getFilePath:A=>c&&g.join(c,A),onFinish:A=>{h(`upload ${A.length} component assets`)}}),ve(u,S,{getFilePath:(A,P)=>{const r=Ee.default(u,P.slice(0,1));return i&&g.join(i,g.dirname(r.slug),A)},onFinish:A=>{h(`upload ${A.length} page assets`)}})]),h("upload assets done"),ye.clear(),global.gc&&global.gc()}catch(f){h("Error during asset import:",f)}}const j={};if(s){const h=o&&g.join(g.dirname(o),"../../resources/components"),f=R(m.resources?.components?.map(({id:S})=>T(h,S))??[]);f.length>0&&(j.components=Object.fromEntries(f.map((S,A)=>[S.id,{index:A,component:S}])))}return{supportedLocales:m.supportedLocales,pageIds:u.map(h=>h.id),components:Object.fromEntries(y.map((h,f)=>[h.id,{index:f,data:h}])),pages:Object.fromEntries(u.map(h=>[h.id,h])),config:m.config||{},resources:j,routeIds:l.map(h=>h.id),routes:Object.fromEntries(l.map(h=>[h.id,h])),dataSourceIds:[],dataSources:{}}}finally{n&&a&&I.rmSync(a,{force:!0,recursive:!0})}}async function Se(t,e,{routes:s,mergeMode:a="byUpdateTime",deleteRoutes:n=!1,publishMode:o=void 0}={}){try{o&&d.clearPreloadComponentsCacheByMode(o)}catch(w){d.logger.error("clear preload page cache error",{error:w})}const{pages:i,pageIds:c,routeIds:p,routes:m,supportedLocales:k}=t;if(o==="production"){let w=s??[],u=null;for(const l of p??[]){const y=m?.[l];if(y?.params&&y?.params.length>0&&y?.paramsOptions&&y?.paramsOptions.length>0){const j=Q.generateParamCombinations({basePath:y.path,params:y.params,routeId:y.id,paramsOptions:y.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]}),h=Object.fromEntries(j.map(f=>[`${l}-${f.paramOptionIds.join("-")}`,f]));u={...u||{},...h},s||(w=[...w,...j.map(f=>`${l}-${f.paramOptionIds.join("-")}`)])}else s||w.push(l)}d.logger.info("routeIds to be published: ",w);for(const l of w){let y=l;if(y.includes("-")){const[f]=y.split("-");y=f}const j=m?.[y];if(!j){const f=e.pageIds.indexOf(y);f!==-1&&n&&(e.pageIds.splice(f,1),delete e.pages[y]);for(const S of e.pageIds)S.includes(`${y}-`)&&(e.pageIds.splice(e.pageIds.indexOf(S),1),delete e.pages[S]);d.logger.info("delete main route page",y);continue}if(l.includes("-")&&!u?.[l]){const f=e.pageIds.indexOf(l);f!==-1&&n&&(e.pageIds.splice(f,1),delete e.pages[l]),d.logger.info("delete page",l);continue}if(!j.displayTemplateId){d.logger.info("no display template",l);continue}const h=i[j.displayTemplateId];if(!h){d.logger.info("no template page",l);continue}if(e.pageIds.includes(l)){if(d.logger.info("has need update page",l),a==="replace")e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("replace page",l);else if(a==="byUpdateTime"){const f=e.pages[j.id];(!f||j.updatedAt&&j.updatedAt>f.updatedAt)&&(e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("replace page by update time",l))}}else e.pageIds.push(l),e.pages[l]=ue({page:h,route:j,state:t,routeId:l,routePathInfo:u?.[l]}),d.logger.info("add page",l)}if(n&&!s)for(const l of e.pageIds)w?.includes(l)||(delete e.pages[l],d.logger.info("delete page",l)),e.pageIds=[...e.pageIds].filter(y=>w?.includes(y))}else{for(const w of c){const u=i[w];if(u)if(e.pageIds.includes(u.id)){if(a==="replace")e.pages[u.id]=u;else if(a==="byUpdateTime"){const l=e.pages[u.id];(!l||u.updatedAt&&u.updatedAt>l.updatedAt)&&(e.pages[u.id]=u)}}else e.pageIds.push(u.id),e.pages[u.id]=u}for(const w of p){const u=m[w];if(u)if(e.routeIds.includes(u.id)){if(a==="replace")e.routes[u.id]=u;else if(a==="byUpdateTime"){const l=e.routes[u.id];(!l||u.updatedAt&&u.updatedAt>l.updatedAt)&&(e.routes[u.id]=u)}}else e.routeIds.push(u.id),e.routes[u.id]=u}}if(e.supportedLocales.splice(0,e.supportedLocales.length),e.supportedLocales.push(...ft.default(k)),n)for(const w of Object.keys(e.components))delete e.components[w];let T=JSON.parse(JSON.stringify(t.components));T=Object.fromEntries(await Promise.all(Object.entries(T).map(async([w,u])=>{const l=await Fe(u?.data);return[w,{...u,data:l}]}))),Object.assign(e.components,T),Object.assign(e.config,JSON.parse(JSON.stringify(t.config))),we.default(t.resources.components)||(e.resources.components=JSON.parse(JSON.stringify(t.resources.components||{})))}const Fe=d.memoizeWithFs(async t=>{if(!we.default(t?.properties))return t;if(t?.renderer?.type==="react-component"){const{script:e,PROPERTIES_SCHEMA:s}=t?.renderer||{};if(s||e&&e.includes("PROPERTIES_SCHEMA"))try{const a=await d.getExportSchemaValueFromCode(e??"","PROPERTIES_SCHEMA",t.id,s);a&&a.length>0&&t&&(t.properties={},a.forEach((n,o)=>{t?.properties&&(t.properties[n.id]={index:o,data:n})}))}catch(a){d.logger.error("getPropertiesFromCode error",{componentId:t.id,name:t.name},{error:a})}}return t},{subdir:"getPropertiesFromCode"});let se,K,ne,oe;const qe=()=>Ie.getResources({types:[{did:Pe,type:ge},{did:bt,type:ge}]}),Ut=()=>{const t=qe(),e={};return t.forEach(s=>{const a=X.globSync("**/.blocklet/pages/pages.config.yml",{cwd:s.path,absolute:!0}).at(0),n=a&&g.join(g.dirname(a),"../../chunks");if(n&&I.existsSync(n)){const o=I.readdirSync(n);for(const i of o)e[i]=g.join(n,i)}}),e};function xe(){return se=(async()=>{const t=qe();K=(await Promise.all(t.map(async s=>{const a=s.path?await Ce(s.path,{importAssets:!1}):void 0;return a?{blockletId:s.did,state:a,blockletTitle:s.title}:void 0}))).filter(s=>!!s),ne=K.reduce((s,a)=>Object.assign(s,Object.fromEntries(Object.values(a.state.pages).map(n=>n?[n?.id,{page:n,blockletId:a.blockletId}]:[]))),{});const e=K.reduce((s,a)=>Object.assign(s,Object.fromEntries(Object.values(a.state.components).map(n=>[n.data.id,{blockletId:a.blockletId,component:n.data}]))),{});oe=Object.fromEntries(await Promise.all(Object.entries(e).map(async([s,a])=>{const n=await Fe(a.component);return[s,{...a,component:n}]})))})(),se}function Be(t){const e=Re.default(async()=>{await xe().catch(s=>{d.logger.error("load resource states error",{error:s})}),await t?.({states:K,pages:ne,components:oe})},3e3,{leading:!1,trailing:!0});return e(),E.default.events.on(E.default.Events.componentAdded,e),E.default.events.on(E.default.Events.componentRemoved,e),E.default.events.on(E.default.Events.componentStarted,e),E.default.events.on(E.default.Events.componentStopped,e),E.default.events.on(E.default.Events.componentUpdated,e),E.default.events.on(me,e),()=>{E.default.events.off(E.default.Events.componentAdded,e),E.default.events.off(E.default.Events.componentRemoved,e),E.default.events.off(E.default.Events.componentStarted,e),E.default.events.off(E.default.Events.componentStopped,e),E.default.events.off(E.default.Events.componentUpdated,e),E.default.events.off(me,e)}}const Ve=Symbol.for("GLOBAL_RESOURCE_STATES_LISTENER_KEY"),Ge=Symbol.for("GLOBAL_ENV_UPDATE_LISTENER_KEY"),re=globalThis;re[Ve]?.();re[Ve]=Be(async({pages:t,components:e})=>{const s=await O.getProjectIds();d.logger.info(`start update resource states projects(${s.length})`,s),await Promise.race([new Promise(a=>{setTimeout(()=>{a({})},30*1e3)}),Promise.all(s.map(async a=>{ze({projectId:a,pages:t,components:e})}))]).catch(a=>{d.logger.error("update resource states failed:",a)})});re[Ge]?.();re[Ge]=()=>{const t=()=>{O.pageUrlMapCache.clear(),d.logger.info("[Cache CLEAR ALL] clear all page url map cache by env update")};return E.default.events.on(E.default.Events.envUpdate,t),()=>{E.default.events.off(E.default.Events.envUpdate,t)}};O.startPeriodicCheck();process.on("beforeExit",()=>{O.stopPeriodicCheck()});process.on("SIGINT",()=>{O.stopPeriodicCheck(),process.exit(0)});process.on("SIGTERM",()=>{O.stopPeriodicCheck(),process.exit(0)});async function ze({projectId:t,pages:e,components:s}){const a=O.sharedInstances[t];if(!a){d.logger.info(`projectId: ${t} not found in sharedInstances`);return}if(a.syncedStore.resources.pages=e,(await L.findByPk(t))?.useAllResources)a.syncedStore.resources.components=s;else{const i=(await Ae.findAll({where:{projectId:t}})).map(p=>p.componentId),c=Object.fromEntries(Object.entries(s||{}).filter(([p])=>i.includes(p)));a.syncedStore.resources.components=c}d.logger.info(`update [${t}] resource states:`,{pages:Object.keys(a.syncedStore.resources.pages||{}).length,components:Object.keys(a.syncedStore.resources.components||{}).length})}async function Mt(){d.logger.info("trigger reload all project resource"),E.default.events.emit(me)}async function Nt({ensureLoaded:t=!0}={}){return t&&(se??=xe(),await se),{states:K,pages:ne,components:oe}}exports.COMPONENT_DID=Pe;exports.PUBLISH_MODES=_t;exports.Project=L;exports.RESOURCE_TYPE=ge;exports.SITE_STATE_PATH=q;exports.STATE_MODES=Lt;exports.SiteState=O;exports.downloadAsset=$e;exports.downloadAssets=Ue;exports.fromPackage=Ce;exports.getDefaultState=_e;exports.getResourceStates=Nt;exports.initPackResourceStates=Be;exports.mergeState=Se;exports.toPackage=Ne;exports.triggerReloadAllProjectResource=Mt;