@blocklet/pages-kit-inner-components 0.7.4 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/chunks/site-state-D9DYye_t.js +1 -0
- package/lib/cjs/locales.js +2 -2
- package/lib/cjs/resources.js +1 -1
- package/lib/cjs/site-state.js +1 -1
- package/lib/es/chunks/{site-state-zNlcYOxL.js → site-state-Ct2OR_RE.js} +570 -517
- package/lib/es/locales.js +17 -1
- package/lib/es/resources.js +1 -1
- package/lib/es/site-state.js +1 -1
- package/package.json +3 -3
- package/lib/cjs/chunks/site-state-DApZigAR.js +0 -1
package/lib/es/locales.js
CHANGED
|
@@ -411,7 +411,15 @@ const t = e({
|
|
|
411
411
|
addParamOption: "Add parameter option",
|
|
412
412
|
errorEmptyValue: "Value cannot be empty",
|
|
413
413
|
errorContainsSlash: "Value cannot contain slash (/)",
|
|
414
|
-
errorInvalidChars: "Value contains invalid characters, please use only URL-safe characters"
|
|
414
|
+
errorInvalidChars: "Value contains invalid characters, please use only URL-safe characters",
|
|
415
|
+
initialConflictWarning: "This route path conflicts with {count} URL(s) from other projects",
|
|
416
|
+
urlConflictTitle: "URL Conflict Detected",
|
|
417
|
+
urlConflictAlertTitle: "Potential Routing Issue",
|
|
418
|
+
urlConflictDescription: "The route path you are trying to save conflicts with existing URLs from other projects. You can still save it, but this may cause routing issues.",
|
|
419
|
+
conflictingUrls: "Conflicting URLs",
|
|
420
|
+
conflictProject: "Project",
|
|
421
|
+
conflictPage: "Page",
|
|
422
|
+
saveAnyway: "Save Anyway"
|
|
415
423
|
},
|
|
416
424
|
datasource: {
|
|
417
425
|
autoSaveSuccess: "Auto save success"
|
|
@@ -1005,6 +1013,14 @@ const t = e({
|
|
|
1005
1013
|
errorEmptyValue: "值不能为空",
|
|
1006
1014
|
errorContainsSlash: "值不能包含斜杠 (/)",
|
|
1007
1015
|
errorInvalidChars: "值包含无效字符,请仅使用URL安全字符",
|
|
1016
|
+
initialConflictWarning: "此路由路径与其他项目的 {count} 个 URL 存在冲突",
|
|
1017
|
+
urlConflictTitle: "检测到 URL 冲突",
|
|
1018
|
+
urlConflictAlertTitle: "潜在路由问题",
|
|
1019
|
+
urlConflictDescription: "您要保存的路由路径与其他项目的现有 URL 冲突。您仍然可以保存,但这可能会导致路由问题。",
|
|
1020
|
+
conflictingUrls: "冲突的 URL",
|
|
1021
|
+
conflictProject: "项目",
|
|
1022
|
+
conflictPage: "页面",
|
|
1023
|
+
saveAnyway: "仍然保存",
|
|
1008
1024
|
templates: {
|
|
1009
1025
|
default: "默认模板",
|
|
1010
1026
|
blog: "博客模板",
|
package/lib/es/resources.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { i as b, a as T, l as x } from "./chunks/components-CcZk17uO.js";
|
|
2
|
-
import { P as E, C as L, R as M, S as A, t as F, c as J, g as X } from "./chunks/site-state-
|
|
2
|
+
import { P as E, C as L, R as M, S as A, t as F, c as J, g as X } from "./chunks/site-state-Ct2OR_RE.js";
|
|
3
3
|
import { Router as G } from "express";
|
|
4
4
|
import { rm as C, mkdir as K } from "fs/promises";
|
|
5
5
|
import u from "joi";
|
package/lib/es/site-state.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./chunks/components-CcZk17uO.js";
|
|
2
|
-
import { d as b, a as h, b as y, S as L, f as U, h as q, i as v, e as z, g as C, j as F, m as G, t as J, k as K, u as N } from "./chunks/site-state-
|
|
2
|
+
import { d as b, a as h, b as y, S as L, f as U, h as q, i as v, e as z, g as C, j as F, m as G, t as J, k as K, u as N } from "./chunks/site-state-Ct2OR_RE.js";
|
|
3
3
|
import { nextId as V } from "@blocklet/pages-kit/utils/common";
|
|
4
4
|
import "@blocklet/pages-kit/utils/page-model";
|
|
5
5
|
import "@blocklet/pages-kit/utils/property";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@blocklet/pages-kit-inner-components",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"description": "Pages Kit inner components library",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -201,8 +201,8 @@
|
|
|
201
201
|
"yaml": "^2.5.0",
|
|
202
202
|
"yjs": "^13.6.18",
|
|
203
203
|
"zustand": "^4.5.5",
|
|
204
|
-
"@blocklet/pages-kit": "^0.7.
|
|
205
|
-
"@blocklet/pages-kit-block-studio": "^0.7.
|
|
204
|
+
"@blocklet/pages-kit": "^0.7.5",
|
|
205
|
+
"@blocklet/pages-kit-block-studio": "^0.7.5"
|
|
206
206
|
},
|
|
207
207
|
"devDependencies": {
|
|
208
208
|
"@trivago/prettier-plugin-sort-imports": "^5.2.1",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";const u=require("./components-CnPdZJ2Z.js"),G=require("@syncedstore/core"),ct=require("yjs"),lt=require("@blocklet/pages-kit/utils/data-source"),se=require("@blocklet/pages-kit/utils/route"),ut=require("lodash/cloneDeep"),w=require("sequelize");require("sqlite3");const pt=require("@blocklet/sdk/lib/config"),_=require("ufo"),dt=require("lodash"),ft=require("crypto"),Z=require("fs"),gt=require("p-limit"),g=require("path"),Ue=require("@blocklet/pages-kit/utils/common"),mt=require("@blocklet/pages-kit/utils/page-model"),ht=require("@blocklet/pages-kit/utils/property"),Ee=require("@blocklet/sdk/lib/component"),yt=require("@reactivedata/reactive"),T=require("fs/promises"),oe=require("glob"),St=require("lib0/decoding"),wt=require("lib0/encoding"),It=require("lodash/debounce"),bt=require("lodash/get"),Pt=require("lodash/isEmpty"),At=require("lodash/set"),Et=require("lodash/union"),Ve=require("lru-cache"),jt=require("stream/promises"),Dt=require("tar"),Tt=require("wait-on"),K=require("y-protocols/awareness"),fe=require("y-protocols/sync"),Ot=require("yaml"),Ne=require("./html-dP5_4zu1.js");require("@blocklet/pages-kit/types/state");const $=t=>t&&t.__esModule?t:{default:t};function le(t){if(t&&t.__esModule)return t;const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const a in t)if(a!=="default"){const s=Object.getOwnPropertyDescriptor(t,a);Object.defineProperty(e,a,s.get?s:{enumerable:!0,get:()=>t[a]})}}return e.default=t,Object.freeze(e)}const q=le(ct),je=$(ut),E=$(pt),$e=$(ft),V=$(Z),De=$(gt),Me=$(g),ge=le(St),v=le(wt),Te=$(It),Oe=$(bt),Re=$(Pt),Fe=$(At),Rt=$(Et),Ct=$(Tt),H=le(Ot),kt=w.DataTypes.sqlite.DATE.parse;w.DataTypes.sqlite.DATE.parse=(t,e)=>typeof t=="number"?new Date(t):kt(t,e);const F=new w.Sequelize({dialect:"sqlite",storage:u.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});F.query("PRAGMA journal_mode = WAL;");F.query("PRAGMA synchronous = normal;");F.query("PRAGMA journal_size_limit = 67108864;");F.query("PRAGMA cache_size = 10000;");process.on("SIGINT",async()=>{await F.close(),process.exit(0)});process.on("SIGTERM",async()=>{await F.close(),process.exit(0)});async function vt(t,e){try{if(t.getDialect()!=="sqlite")return;const[a]=await t.query("SELECT 1");if(!a||a.length===0)return;await t.query("PRAGMA shrink_memory;")}catch(a){if(a.name==="SequelizeConnectionError"||a?.message&&/closed!/.test(a.message))return;console.error("Failed to cleanup SQLite memory",e,a)}}let Se=null;Se&&clearInterval(Se);Se=setInterval(async()=>{u.logger.info("Start cleanupSqliteMemory"),await vt(F,u.databaseUrl),u.logger.info("End cleanupSqliteMemory")},60*1e3*10);const Lt="z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o",we="page",Ie="trigger-reload-project-resource",Ce=Lt,_t="z2qa7BQdkEb3TwYyEYC1psK6uvmGnHSUHt5RM",Ut="z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o";class ke extends w.Model{}ke.init({id:{type:w.DataTypes.UUID,allowNull:!1,primaryKey:!0,defaultValue:w.DataTypes.UUIDV4},projectId:{type:w.DataTypes.UUID,allowNull:!1},componentId:{type:w.DataTypes.STRING,allowNull:!1}},{sequelize:F,tableName:"ProjectComponents",timestamps:!1});const Nt="SLUG_INVALID",Y=t=>({error:"slugInvalid",code:Nt,field:"slug",message:t}),$t={error:"slugRequired",code:"SLUG_REQUIRED",field:"slug",message:()=>"Project slug is required"},Mt={error:"slugAlreadyExists",code:"SLUG_EXISTS",field:"slug",message:t=>`Project slug "${t}" already exists`},Ft=[/\.\./,/<[^>]*>/,/%[0-9a-f]{2}/i,/[<>'"%;{}()\\]/,/\x00/,/\n|\r|\t|\v|\f/,/[^a-zA-Z0-9-_@/\\:]/],qe=t=>{if(!t)return"";if(t==="/")return"/";const e=_.withoutTrailingSlash(t);return _.withLeadingSlash(e)||"/"},qt=t=>t.did===Ut;class N extends w.Model{static async getProjectByIdOrSlug(e,a){return e?N.findOne({where:{[w.Op.or]:[{id:e},{slug:e}],...a?.createdBy?{createdBy:a.createdBy}:{}}}):null}static async validateProjectSlug({slug:e,projectId:a}){if(e==null)return null;if(e==="")return $t;const s=e==="/"?"/":_.withoutTrailingSlash(_.withLeadingSlash(e)),o=qe(s);if(s!=="/"&&s.endsWith("/"))return Y(r=>`Project slug "${r}" cannot end with /`);if(/\/{2,}/.test(s))return Y(r=>`Project slug "${r}" cannot contain consecutive /`);if(/\s/.test(s))return Y(r=>`Project slug "${r}" cannot contain whitespace`);if(Ft.some(r=>r.test(s)))return Y(r=>`Project slug "${r}" contains invalid characters`);if(E.default.components?.filter(r=>r.mountPoint&&!qt(r)).some(r=>qe(r.mountPoint)===o))return Y(r=>`Project slug "${r}" conflicts with existing blocklet`);const l=await N.findOne({where:{slug:s}});return l&&l?.id!==a?Mt:null}}N.init({id:{type:w.DataTypes.UUID,defaultValue:w.DataTypes.UUIDV4,primaryKey:!0},name:{type:w.DataTypes.STRING,allowNull:!1},description:w.DataTypes.TEXT,createdAt:w.DataTypes.DATE,updatedAt:w.DataTypes.DATE,createdBy:{type:w.DataTypes.STRING,allowNull:!1},updatedBy:{type:w.DataTypes.STRING,allowNull:!1},slug:w.DataTypes.STRING,icon:w.DataTypes.STRING,pinnedAt:w.DataTypes.DATE,useAllResources:w.DataTypes.BOOLEAN,npmSecret:w.DataTypes.STRING,relatedBlocklets:{type:w.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 u.logger.error("Failed to parse relatedBlocklets",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("relatedBlocklets",t?JSON.stringify(t):"{}")}catch(e){u.logger.error("Failed to set relatedBlocklets",{error:e,value:t}),this.setDataValue("relatedBlocklets","{}")}}},productionState:{type:w.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 u.logger.error("Failed to parse productionState",{error:e,rawValue:t}),{}}},set(t){try{this.setDataValue("productionState",t?JSON.stringify(t):"{}")}catch(e){u.logger.error("Failed to set productionState",{error:e,value:t}),this.setDataValue("productionState","{}")}}},meta:{type:w.DataTypes.JSON,allowNull:!0}},{sequelize:F,paranoid:!0,indexes:[{name:"projects_slug_unique",unique:!0,fields:["slug"]},{name:"projects_created_by",fields:["createdBy"]},{name:"projects_pinned_updated_meta_not_null",fields:[{name:"pinnedAt",order:"DESC"},{name:"updatedAt",order:"DESC"}],where:{meta:{[w.Op.ne]:null}}}]});N.hasMany(ke,{foreignKey:"projectId",as:"components"});async function x(t){try{return await V.default.promises.access(t,V.default.constants.F_OK),!0}catch{return!1}}function ze(t,e){return new Promise((a,s)=>{const o=V.default.createReadStream(t),n=V.default.createWriteStream(e);o.on("error",s),n.on("error",s),n.on("finish",a),o.pipe(n)})}async function He(t,e){await V.default.promises.mkdir(e,{recursive:!0});const a=await V.default.promises.readdir(t,{withFileTypes:!0});for(const s of a){const o=Me.default.join(t,s.name),n=Me.default.join(e,s.name);s.isDirectory()?await He(o,n):await ze(o,n)}}async function xt(t,e){(await V.default.promises.stat(t)).isDirectory()?await He(t,e):await ze(t,e)}class ae extends w.Model{}ae.init({id:{type:w.DataTypes.UUID,primaryKey:!0,defaultValue:w.DataTypes.UUIDV4},projectId:{type:w.DataTypes.UUID,allowNull:!1,comment:"Project ID"},urlPath:{type:w.DataTypes.STRING(512),allowNull:!1,unique:!0,comment:"URL path, e.g. /project-slug/page-slug or /en/project-slug/page-slug"},projectSlug:{type:w.DataTypes.STRING,allowNull:!0,comment:"Project slug"},pageSlug:{type:w.DataTypes.STRING,allowNull:!1,comment:"Page slug"},pageId:{type:w.DataTypes.UUID,allowNull:!1,comment:"Page ID"},routeId:{type:w.DataTypes.UUID,allowNull:!0,comment:"Route ID (for draft mode)"},locale:{type:w.DataTypes.STRING(10),allowNull:!0,comment:"Locale code, e.g. en, zh"},defaultLocale:{type:w.DataTypes.STRING(10),allowNull:!0,comment:"Default locale"},shouldRedirect:{type:w.DataTypes.BOOLEAN,defaultValue:!1,comment:"Whether this URL should redirect"},mainPage:{type:w.DataTypes.BOOLEAN,defaultValue:!1,comment:"Whether this is the main page"},isPublic:{type:w.DataTypes.BOOLEAN,allowNull:!1,defaultValue:!0,comment:"Whether the page is public"},publishedAt:{type:w.DataTypes.BIGINT,allowNull:!0,comment:"Published timestamp"},locales:{type:w.DataTypes.JSON,allowNull:!0,comment:"Supported locales array"},createdAt:w.DataTypes.DATE,updatedAt:w.DataTypes.DATE},{sequelize:F,tableName:"PageUrlMappings",timestamps:!0,indexes:[{name:"idx_project_id",fields:["projectId"]},{name:"idx_url_path",unique:!0,fields:["urlPath"]},{name:"idx_page_id",fields:["pageId"]}]});function Bt(t){const{projectId:e,projectSlug:a,state:s}=t,o=a||e,n=dt.union(E.default.env.languages?.map(i=>i.code)||[],s.supportedLocales?.map(i=>i.locale)||[]),l={},r=(i,m)=>{o&&(l[_.joinURL("/",o,i)]={...m,shouldRedirect:!0,mainPage:!0}),l[_.joinURL("/",e,i)]={...m,shouldRedirect:!0,mainPage:!0};for(const A of n){const j={...m,locale:A};l[_.joinURL("/",A,e,i)]=j,o&&(l[_.joinURL("/",A,o,i)]=j)}};for(const i of s.pageIds||[]){const m=s.pages?.[i];if(!m||!m.isPublic)continue;const A={projectId:e,projectSlug:o,pageSlug:m.slug,pageId:i,defaultLocale:n?.[0],locales:n,publishedAt:s.config?.publishedAt,isPublic:m.isPublic};r(m.slug,A)}return l}function ne(t){t.observeDeep(e=>{e.some(a=>a.changes.keys.has("updatedAt")||a.changes.keys.has("publishedAt"))||t.set("updatedAt",new Date().toISOString())})}function Je(){return Z.mkdtempSync(g.join(E.default.env.dataDir,"tmp-"))}function re(t,e,a=[]){return Array.isArray(t)?t.flatMap((s,o)=>re(s,e,[...a,o])):typeof t=="object"?t===null?[]:Object.entries(t).flatMap(([s,o])=>re(o,e,[...a,s])):e(t)?[a]:[]}function U(t){return t.filter(e=>e!=null)}function xe(t,e){if(t===e)return!0;if(!t||!e)return t===e;const a=Object.keys(t),s=Object.keys(e);if(a.length!==s.length)return!1;if(a.length<10){for(const l of a){if(!(l in e))return!1;const r=t[l],i=e[l];if(r?.blockletId!==i?.blockletId||r?.page?.id!==i?.page?.id||r?.page?.updatedAt!==i?.page?.updatedAt||r?.component?.id!==i?.component?.id||r?.component?.updatedAt!==i?.component?.updatedAt)return!1}return!0}const o=$e.default.createHash("md5").update(JSON.stringify(t,Object.keys(t).sort())).digest("hex"),n=$e.default.createHash("md5").update(JSON.stringify(e,Object.keys(e).sort())).digest("hex");return o===n}function Gt(t){t.pages&&Object.keys(t.pages).forEach(a=>{const s=G.getYjsValue(t.pages[a]);s&&s instanceof q.Map&&ne(s)});const e=G.getYjsValue(t.pages);e&&e instanceof q.Map&&e.observe(a=>{a.changes.keys.forEach((s,o)=>{if(s.action==="add"){const n=G.getYjsValue(t.pages[o]);n&&n instanceof q.Map&&ne(n)}})})}function Vt(t){t.routes&&Object.keys(t.routes).forEach(a=>{const s=G.getYjsValue(t.routes?.[a]);s&&s instanceof q.Map&&ne(s)});const e=G.getYjsValue(t.routes);e&&e instanceof q.Map&&e.observe(a=>{a.changes.keys.forEach((s,o)=>{if(s.action==="add"){const n=G.getYjsValue(t.routes?.[o]);n&&n instanceof q.Map&&ne(n)}})})}function zt(t,e){for(const a of e||Object.keys(t.routes||{})){let s=a,o=[];if(a.includes("-")){const[n,...l]=a.split("-");s=n,o=l||[]}if(t.routes?.[s]!==void 0){t.routes[s].publishedAt=new Date().toISOString();const n=t.routes[s];if(!n||!n.params||n.params.length===0)continue;if(a.includes("-")&&o.length>0){const l=se.getRouteMetaDataByOptionIds(o,n);l&&(l.publishedAt=new Date().toISOString())}if(!e){const l=se.generateParamCombinations({basePath:n.path,params:n.params,routeId:n.id,paramsOptions:n.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const r of l)r.routeMetaData??={},r.routeMetaData.publishedAt=new Date().toISOString()}}}}function me({page:t,route:e,state:a,routeId:s,routePathInfo:o}){u.logger.info(`Executing datasource data assembly, routeId: ${s}, routePathInfo: ${JSON.stringify(o)}`);const n={...je.default(t),id:s,slug:o?.path??e.path,createdAt:e.createdAt,updatedAt:o?.routeMetaData?.updatedAt??e.updatedAt,publishedAt:o?.routeMetaData?.publishedAt??e.publishedAt,isPublic:(o?.routeMetaData?.isPublic??e.isPublic)&&e.isPublic};for(const l of a.supportedLocales){if(e.dataSource){let r=e.id;o&&(r=o.paramOptionIds.join("-"));const i=e.dataSource.pathDataMappings?.[r]?.dataCache?.[l.locale]??e.dataSource.pathDataMappings?.[r]?.dataCache?.[a.config.defaultLocale||"en"];if(!i)continue;lt.setPageDataSource(n,a,l.locale,i)}o&&o.routeMetaData&&(o.routeMetaData.publishedAt=new Date().toISOString())}return n}["true","1","yes","y"].includes(process.env.USE_FS_CACHE_HTML??"");const Ht=60*60*1e3,W=new Ve.LRUCache({max:300,ttl:Ht,ttlResolution:10*1e3,allowStale:!0});function Jt(t,e=[]){let a=0;const s=Array.from(W.keys()),o=t.map(n=>_.withoutTrailingSlash(n));for(const n of s)for(const l of o){if(Ne.matchCacheKey(n,{currentPath:l})){W.delete(n),a++,u.logger.info(`[Cache CLEAR] key: ${n}`);break}for(const r of e)if(Ne.matchCacheKey(n,{currentPath:`/${r}${l}`})){W.delete(n),a++,u.logger.info(`[Cache CLEAR] key: ${n}`);break}}return u.logger.info(`[Cache CLEAR] cleared ${a} entries for paths:`,o),a}function Kt(){const t=W.size;return W.clear(),u.logger.info(`[Cache CLEAR ALL] cleared ${t} entries`),t}E.default.events.on(E.default.Events.envUpdate,Kt);const{uploadToMediaKit:Yt}=require("@blocklet/uploader-server"),ve=/^\w+(\w|-|\.)+\w+\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm)$/,X=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/i,Be=/mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/gi,Wt=1e4,Xt=3e4,ee=0,he=1,Qt=0,Zt=1,be=E.default,z=g.join(process.env.BLOCKLET_DATA_DIR,"site-state"),ea=["production","draft"],ta=["production"];function ie(t){return t?.replace(/\//g,"|")||""}function Ke(){const t=be.env.languages?.map(a=>({locale:a.code,name:a.name}))||[],e=t[0]?.locale||"en";return{pageIds:[],pages:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{},components:{},supportedLocales:t,config:{defaultLocale:e},resources:{}}}class C extends q.Doc{constructor(e){super(),this.options=e,Z.existsSync(this.draftYjsFilePath)&&q.applyUpdate(this,Z.readFileSync(this.draftYjsFilePath)),this.syncedStore=yt.reactive(G.syncedStore({pages:{},pageIds:[],components:{},supportedLocales:[],config:{},resources:{},routeIds:[],routes:{},dataSourceIds:[],dataSources:{}},this)),this.initObserver(),this.on("update",this.updateHandler),this.awareness=new K.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 periodicCheckTimer;static async safeDeleteProjectStateDir(e){if(!e)throw new Error("Should provide project context");try{const a=g.join(z,e),s=g.join(z,`@del-${e}`);await T.rename(a,s)}catch(a){u.logger.error("Failed to safe delete project state dir:",a)}}static async getProjectIds(){return(await N.findAll({attributes:["id"],raw:!0}))?.map(e=>e.id)}static get projectIds(){return oe.globSync("*/",{cwd:z,ignore:["@del-*","@tmp-*",".*","staging","production","@backup-*","undefined"]})}static get allShared(){return this.projectIds.map(e=>C.shared(e))}static shared(e){if(!e)throw new Error("Should provide project context");let a=C.sharedInstances[e];return a||(a=new C({path:g.join(z,e)}),C.sharedInstances[e]=a,a)}static async getProductionState(e){const a=await N.findByPk(e,{attributes:["productionState"]});if(Re.default(a?.productionState)){const s=g.join(z,e,"production"),o=await Le(s,{includeResources:!0})??Ke();if(!o?.config?.defaultLocale){o.config??={};const n=be.env.languages?.map(l=>({locale:l.code,name:l.name}))||[];o.config.defaultLocale=n[0]?.locale}return o}return a?.productionState}destroy(){this.cancelRelease(),this.save({flush:!0}),this.conns.forEach((a,s)=>this.closeConn(s)),this.awareness.destroy();const e=g.basename(this.options.path);delete C.sharedInstances[e],super.destroy()}initObserver(){Gt(this.syncedStore),Vt(this.syncedStore)}get draftYjsFilePath(){return g.join(this.options.path,"draft.yjs")}static async getStateByProjectId({projectId:e,mode:a,clone:s=!0}){if(a==="draft"){const o=C.shared(e);return s?JSON.parse(JSON.stringify(o.syncedStore)):o.syncedStore}return C.getProductionState(e)}async getState(e){if(e==="draft")return JSON.parse(JSON.stringify(this.syncedStore));const a=g.basename(this.options.path);return C.getProductionState(a)}async setState(e,a){const s=await Qe(a,{exportAssets:!1,includeResources:!0}),o=this.getPublishDir(e);if(await T.mkdir(g.dirname(o),{recursive:!0}),await T.rm(o,{force:!0,recursive:!0}),await T.rename(s,o),e==="production"){const n=g.basename(this.options.path),l=je.default(a);await F.transaction(async r=>{await N.update({productionState:l},{where:{id:n},transaction:r});const i=await N.findByPk(n,{attributes:["slug"],transaction:r}),m=Bt({projectId:n,projectSlug:i?.slug,state:a});await ae.destroy({where:{projectId:n},transaction:r});const A=Object.entries(m).map(([j,p])=>({projectId:n,urlPath:j,projectSlug:p.projectSlug,pageSlug:p.pageSlug,pageId:p.pageId,routeId:p.routeId,locale:p.locale,defaultLocale:p.defaultLocale,shouldRedirect:p.shouldRedirect,mainPage:p.mainPage,isPublic:p.isPublic,publishedAt:p.publishedAt,locales:p.locales}));if(A.length>0)for(let p=0;p<A.length;p+=100)await ae.bulkCreate(A.slice(p,p+100),{transaction:r});u.logger.info(`[SiteState] saved ${A.length} URL mappings for project ${n}`)})}}getPublishDir(e){return g.join(this.options.path,e)}syncedStore;conns=new Map;awareness;releaseTimer;awarenessChangeHandler=({added:e,updated:a,removed:s},o)=>{const n=e.concat(a,s);if(o!==null){const i=this.conns.get(o);i&&(e.forEach(m=>{i.add(m)}),s.forEach(m=>{i.delete(m)}))}const l=v.createEncoder();v.writeVarUint(l,he),v.writeVarUint8Array(l,K.encodeAwarenessUpdate(this.awareness,n));const r=v.toUint8Array(l);this.conns.forEach((i,m)=>this.send(m,r))};updateHandler=e=>{const a=v.createEncoder();v.writeVarUint(a,ee),fe.writeUpdate(a,e);const s=v.toUint8Array(a);this.conns.forEach((o,n)=>this.send(n,s))};ensureDataStructure=()=>{this.transact(()=>{const{supportedLocales:e,pages:a,pageIds:s,config:o,routes:n,routeIds:l}=this.syncedStore;{const r=new Set(Object.keys(a));let i=0;for(;i<s.length;){const m=s[i];r.has(m)?(r.delete(m),i++):s.splice(i,1)}}{const r=new Set(Object.keys(n));let i=0;for(;i<l.length;){const m=l[i];r.has(m)?(r.delete(m),i++):l.splice(i,1)}}e.splice(0,e.length),e.push(...be.env.languages.map(r=>({locale:r.code,name:r.name}))),o.defaultLocale=e[0]?.locale;{let r=0;const i=new Set;for(;r<e.length;){const{locale:m}=e[r];i.has(m)?e.splice(r,1):(r++,i.add(m))}}})};send=(e,a)=>{e.readyState!==Qt&&e.readyState!==Zt&&this.closeConn(e);try{e.send(a,s=>{s&&this.closeConn(e)})}catch{this.closeConn(e)}};closeConn=e=>{if(e.removeAllListeners(),this.conns.has(e)){const a=this.conns.get(e);this.conns.delete(e),a&&K.removeAwarenessStates(this.awareness,Array.from(a),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(()=>{u.logger.info(`[SiteState] releasing instance due to no active connections: ${e}`),this.conns.size===0&&(this.releaseTimer=void 0,this.destroy())},C.RELEASE_DELAY),u.logger.info(`[SiteState] scheduled release for project ${e} in ${C.RELEASE_DELAY/1e3}s`)}cancelRelease(){if(this.releaseTimer){clearTimeout(this.releaseTimer),this.releaseTimer=void 0;const e=g.basename(this.options.path);u.logger.info(`[SiteState] cancelled scheduled release for project ${e}`)}}autoSave=Te.default(async()=>{await T.mkdir(g.dirname(this.draftYjsFilePath),{recursive:!0}),await T.writeFile(this.draftYjsFilePath,q.encodeStateAsUpdate(this))},Wt);save=({flush:e=!1}={})=>{this.autoSave(),e&&this.autoSave.flush()};publish=async({mode:e,routes:a})=>{const s=g.basename(this.options.path);await rt(s);const o=await this.getState("draft"),n=await this.getState("production");await Ae(o,n,{routes:a,mergeMode:"replace",deleteRoutes:!0,publishMode:e}),n.config.publishedAt=new Date().getTime(),zt(this.syncedStore,a),await this.setState(e,n),await this.clearPageCacheForRoutes(a,n)};mergeState=async(e,a)=>{const s=JSON.parse(JSON.stringify(a));e.config.fontFamily??={};const o=s.config?.fontFamily,n=e.config?.fontFamily;e.config.fontFamily.title=o?.title||n?.title,e.config.fontFamily.description=o?.description||n?.description,await new Promise((l,r)=>{this.transact(async()=>{try{const i=await Ae(e,a);l(i)}catch(i){r(i)}})})};clearPageCacheForRoutes=async(e,a)=>{const s=g.basename(this.options.path),n=(await N.findByPk(s))?.slug||s;let l=e;(!l||l.length===0)&&(l=a.pageIds??[]),u.logger.info(`[SiteState] clearing page cache for project ${s}, routes:`,l||[]);const r=a.supportedLocales.map(A=>A.locale),i=[],m=l.filter(A=>a.pageIds?.includes(A));for(const A of m){const p=a.pages[A].slug;n&&n!==s&&(n==="/"?i.push(p):i.push(`/${n}${p}`)),i.push(`/${s}${p}`)}if(i.length>0)try{const A=Jt(i,r);u.logger.info(`[SiteState] cleared ${A} page cache entries for project ${s}, routes:`,l)}catch{}};addConnection=e=>{if(this.conns.has(e))return;this.cancelRelease(),e.binaryType="arraybuffer",this.conns.set(e,new Set),e.on("message",o=>this.messageListener(e,new Uint8Array(o)));let a=!0;const s=setInterval(()=>{if(!a)this.conns.has(e)&&this.closeConn(e),clearInterval(s);else if(this.conns.has(e)){a=!1;try{e.ping()}catch{this.closeConn(e),clearInterval(s)}}},Xt);e.on("close",()=>{this.closeConn(e),clearInterval(s)}),e.on("pong",()=>{a=!0});{const o=v.createEncoder();v.writeVarUint(o,ee),fe.writeSyncStep1(o,this),this.send(e,v.toUint8Array(o));const n=this.awareness.getStates();if(n.size>0){const l=v.createEncoder();v.writeVarUint(l,he),v.writeVarUint8Array(l,K.encodeAwarenessUpdate(this.awareness,Array.from(n.keys()))),this.send(e,v.toUint8Array(l))}}};messageListener=(e,a)=>{try{const s=v.createEncoder(),o=ge.createDecoder(a),n=ge.readVarUint(o);switch(n){case ee:v.writeVarUint(s,ee),fe.readSyncMessage(o,s,this,null),v.length(s)>1&&(this.ensureDataStructure(),this.send(e,v.toUint8Array(s)));break;case he:{K.applyAwarenessUpdate(this.awareness,ge.readVarUint8Array(o),e);break}default:u.logger.warn(`Unsupported messageType ${n}`)}}catch(s){u.logger.error(s)}this.save()};static async pageUrlMap(e,a){if(u.logger.info(`[SiteState] get pageUrlMap, mode: ${e}, projectId: ${a}`),e==="production"){const n=a?{projectId:a}:{},l=await ae.findAll({where:n,raw:!0}),r={};for(const i of l)r[i.urlPath]={projectId:i.projectId,projectSlug:i.projectSlug,pageSlug:i.pageSlug,pageId:i.pageId,routeId:i.routeId,locale:i.locale,defaultLocale:i.defaultLocale,shouldRedirect:i.shouldRedirect,mainPage:i.mainPage,isPublic:i.isPublic,publishedAt:i.publishedAt,locales:i.locales};return u.logger.info(`[SiteState] loaded ${l.length} URL mappings from database`),r}let s=[];a?s=[a]:s=await this.getProjectIds();let o={};if(s?.length){u.logger.info("[SiteState] find project infos from database, projectIds: ",s);const n=30,l=De.default(5);for(let r=0;r<s.length;r+=n){const i=s.slice(r,r+n);u.logger.info(`[SiteState] processing project batch ${r/n+1}, ids: `,i);const m=await N.findAll({where:{id:{[w.Op.in]:i}},attributes:{exclude:["relatedBlocklets"]}});await Promise.all(m?.map(A=>l(async()=>{const j=A.id,p=A.slug||j,y={},d=await C.getStateByProjectId({projectId:A.id,mode:e,clone:!1}),P=Rt.default(E.default.env.languages?.map(D=>D.code)||[],d.supportedLocales?.map(D=>D.locale)||[]),O=(D,b)=>{p&&(y[_.joinURL("/",p,D)]={...b,shouldRedirect:!0,mainPage:!0}),y[_.joinURL("/",j,D)]={...b,shouldRedirect:!0,mainPage:!0};for(const k of P){const S={...b,locale:k};y[_.joinURL("/",k,j,D)]=S,p&&(y[_.joinURL("/",k,p,D)]=S)}};if(e==="draft")for(const D of d.routeIds||[]){const b=d?.routes?.[D];if(!b)continue;if(b.params&&b.params.length>0){const I=se.generateParamCombinations({basePath:b.path,params:b.params,routeId:b.id,paramsOptions:b.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]});for(const c of I){const f=c.path,h={projectId:j,projectSlug:p,pageSlug:f,pageId:b.displayTemplateId||"",routeId:D,defaultLocale:P?.[0],locales:P,publishedAt:d.config.publishedAt,isPublic:b.isPublic&&c?.routeMetaData?.isPublic};O(f,h)}}const k=b.path,S={projectId:j,projectSlug:p,pageSlug:k,pageId:b.displayTemplateId||"",routeId:D,defaultLocale:P?.[0],locales:P,publishedAt:d.config.publishedAt,isPublic:b.isPublic};O(k,S)}for(const D of d.pageIds||[]){const b=d.pages[D];if(!b)continue;const k=b.slug,S=A.slug||j,I={projectId:j,projectSlug:S,pageSlug:k,pageId:D,defaultLocale:P?.[0],locales:P,publishedAt:d.config.publishedAt,isPublic:b.isPublic,templateConfig:b.templateConfig};O(k,I)}o={...o,...y}})))}}return u.logger.info("[SiteState] success get pageUrlMap"),o}getDocumentSize(){return q.encodeStateAsUpdate(this).byteLength}static getInstancesSizeInfo(){const e=[];for(const[a,s]of Object.entries(C.sharedInstances)){const o=s.getDocumentSize();e.push({projectId:a,sizeInBytes:o,sizeInMB:`${(o/(1024*1024)).toFixed(2)} MB`,activeConnections:s.conns.size})}return e}static startPeriodicCheck(){this.periodicCheckTimer||(this.periodicCheckTimer=setInterval(()=>{this.performPeriodicCheck()},this.PERIODIC_CHECK_INTERVAL),u.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,u.logger.info("[SiteState] periodic check stopped"))}static performPeriodicCheck(){const e=Object.keys(C.sharedInstances).length,a=[],s=[];for(const[o,n]of Object.entries(C.sharedInstances))n.conns.size===0?a.push({projectId:o,instance:n}):s.push({projectId:o,connections:n.conns.size});if(u.logger.info(`[SiteState] periodic check summary: total instances: ${e}, with connections: ${s.length}, without connections: ${a.length}`),a.length>0){u.logger.info(`[SiteState] releasing ${a.length} instances without connections:`,a.map(n=>n.projectId));let o=0;for(const{projectId:n,instance:l}of a)try{u.logger.info(`[SiteState] releasing instance due to periodic check: ${n}`),l.destroy(),o++}catch(r){u.logger.error(`[SiteState] failed to release instance ${n} during periodic check:`,r)}u.logger.info(`[SiteState] periodic check completed: ${o}/${a.length} instances released successfully`)}else e>0?u.logger.debug("[SiteState] periodic check: all instances have active connections"):u.logger.debug("[SiteState] periodic check: no instances exist")}}async function aa(t,e,a){if(!t||!await x(t)||!(await T.lstat(t)).isFile())return null;let o=a[t];return o||(o=(async()=>{try{return(await Yt({filePath:t,fileName:e}))?.data?.filename}catch(n){return u.logger.error(`Failed to upload asset ${t}:`,n),null}})(),a[t]=o),o}const Ye=async(t,e)=>{const a=g.basename(t),s=await Ee.call({name:Ce,path:_.joinURL("/uploads",a),responseType:"stream",method:"GET"});if(s.status>=200&&s.status<400){const o=Z.createWriteStream(e);await jt.pipeline(s.data,o)}else throw new Error(`download asset failed ${s.status}`)},We=async(t,e)=>{await Promise.all(t.map(async a=>{try{await Ye(a,g.join(e,g.basename(a)))}catch(s){u.logger.error(`Failed to export assets: ${a}, ${s}`)}}))};function Xe(t){return ve.test(t)?[t]:X.test(t)?(Be.lastIndex=0,Array.from(t.matchAll(Be)).map(a=>a[1]).filter(a=>!!a)):[]}async function te(t,e,a){const{getFilename:s,exportAssets:o}=a,n=g.join(e,s(t));if(await T.mkdir(g.dirname(n),{recursive:!0}),await T.writeFile(n,H.stringify(t)),o){const r=re(t,i=>typeof i=="string"&&(ve.test(i)||X.test(i))).map(i=>{const m=Oe.default(t,i);return Xe(m)}).flat().filter(Boolean);await We(r,g.dirname(n))}}const Pe=new Ve.LRUCache({max:100,ttl:1*60*1e3});async function Ge(t,e,a){const s=re(t,r=>typeof r=="string"&&(ve.test(r)||X.test(r))),o=De.default(2),n=s.map(r=>o(async()=>{try{const i=Oe.default(t,r),m=Xe(i);for(const A of m){const j=g.basename(A),p=a.getFilePath(A,r),y=p?`${p}:${j}`:j,d=Pe.get(y);if(d){X.test(i)||Fe.default(t,r,d);return}const P=await aa(p,j,e);P&&(X.test(i)||Fe.default(t,r,P),Pe.set(y,P))}}catch(i){u.logger.error(`Failed to process upload for path ${r.join(".")}:`,i.message||i.reason)}})),l=await Promise.allSettled(n);a.onFinish?.(l)}async function Qe(t,{exportAssets:e,pageIds:a="all",componentIds:s="all",rawConfig:o,includeResources:n=!1,routeIds:l="all"}={}){const r=a==="all"?t.pageIds:a,i=ht.getComponentDependencies({state:t,pageIds:r,componentIds:s==="all"?Object.keys(t.components):s});Object.entries(t.components).forEach(([c,f])=>{f.data?.renderer?.type==="component-template"&&i.push(c)});const m=l==="all"?t.routeIds:l,A=c=>({id:c.id,name:c.name,isTemplateSection:c.isTemplateSection??!1,templateDescription:c.templateDescription,component:c.component,config:c.config,visibility:c.visibility,sections:c?.sectionIds?U(c?.sectionIds?.map(f=>{const h=c.sections?.[f];return h&&A(h)})):void 0}),j=(c,f)=>({id:c.id,createdAt:c.createdAt,updatedAt:c.updatedAt,publishedAt:c.publishedAt,isPublic:c.isPublic??!0,templateConfig:c.templateConfig,meta:c.locales?.[f]??{},sections:U(c.sectionIds.map(h=>{const R=c.sections[h];return R&&A(R)})),dataSource:Object.fromEntries(Object.entries(c.dataSource||{}).map(([h,R])=>[h,R?.[f]??{}]))}),p=c=>({id:c.id,createdAt:c.createdAt,updatedAt:c.updatedAt,publishedAt:c.publishedAt,path:c.path,handler:c.handler,isPublic:c.isPublic??!0,params:c.params??[],enabledGenerate:c.enabledGenerate??!1,displayTemplateId:c.displayTemplateId,dataSource:c.dataSource}),y=U(m.map(c=>{const f=t.routes[c];return f&&p(f)})),d=U(t.supportedLocales.map(c=>c.locale).flatMap(c=>r.map(f=>{const h=t.pages[f];return h&&{locale:c,slug:h.slug,page:j(h,c)}}))),P=Je(),O=g.join(P,"pages");await T.mkdir(O,{recursive:!0});const D=g.join(P,"components");await T.mkdir(D,{recursive:!0});const b=g.join(P,"routes");await T.mkdir(b,{recursive:!0});for(const{locale:c,slug:f,page:h}of d)await te(h,O,{getFilename:()=>`${ie(f)||"index"}.${c}.yml`,exportAssets:e});for(const c of y)await te(c,b,{getFilename:()=>`${ie(c.path)||"index"}.yml`,exportAssets:e});for(const c of i){const f=t.components[c]?.data;f&&await te(f,D,{getFilename:h=>`${h.name||"unnamed"}.${h.id}.yml`,exportAssets:e})}const k=g.join(P,".blocklet/pages/pages.config.yml");await T.mkdir(g.dirname(k),{recursive:!0});const S={pages:U(r.map(c=>{const f=t.pages[c];return f&&{id:c,slug:f.slug}})),routes:U(m.map(c=>{const f=t.routes[c];return f&&{id:c,path:f.path}})),components:U(i.map(c=>{const f=t.components[c]?.data;return f&&{id:c,name:f.name}})),...n?{resources:{components:U(Object.keys(t.resources?.components||{}).filter(c=>i.includes(c)).map(c=>({id:c,name:t.resources?.components?.[c]?.component?.name})))}}:{},supportedLocales:t.supportedLocales,config:t.config};await T.writeFile(k,H.stringify(S));const I=g.join(P,"config.source.json");if(o&&await T.writeFile(I,JSON.stringify(o)),n){const c=g.join(P,"resources"),f=g.join(c,"components");await T.mkdir(f,{recursive:!0});for(const M of Object.keys(t?.resources?.components??{}).filter(L=>i.includes(L))){const L=t.resources?.components?.[M]?.component;L&&await te(L,f,{getFilename:B=>`${B.name||"unnamed"}.${B.id}.yml`,exportAssets:e})}const h=g.join(P,"chunks");await T.mkdir(h,{recursive:!0});const R=await sa();for(const M of Object.keys(t?.resources?.components??{}).filter(L=>i.includes(L))){const L=t.resources?.components?.[M]?.component;if(L&&L.renderer?.type==="react-component"){const B=L.renderer?.chunks??[];if(B?.length>0)for(const J of B){const _e=g.join(h,J),de=R?.[J];try{de&&await x(de)&&!await x(_e)&&await T.copyFile(de,_e)}catch(it){u.logger.error(`copy chunk ${J} error`,it.message)}}}}}return P}async function Le(t,{importAssets:e,includeResources:a}={}){if(!await x(t))return null;let s,o=!1;try{(await T.lstat(t)).isDirectory()?s=t:/\.(tgz|gz|tar)$/.test(t)&&(o=!0,s=Je(),await Dt.x({file:t,C:s}));const r=(await oe.glob("**/.blocklet/pages/pages.config.yml",{cwd:s,absolute:!0}))[0],i=r&&g.join(g.dirname(r),"../../pages"),m=r&&g.join(g.dirname(r),"../../components"),A=r&&g.join(g.dirname(r),"../../routes");if(!r)return null;const j=await T.readFile(r,"utf-8"),p=H.parse(j),y=async(S,I,c)=>{let f=g.join(S,`${I}${c?`.${c}`:""}.yml`);if(!await x(f)&&(f=g.join(S,I,`index${c?`.${c}`:""}.yml`),!await x(f))||!(await T.lstat(f)).isFile())return null;const R=await T.readFile(f,"utf-8");return H.parse(R)},d=async(S,I)=>{try{const f=(await oe.glob(`*.${I}.yml`,{cwd:S,absolute:!0}))[0];if(!f)return null;const h=await T.readFile(f,"utf-8");return H.parse(h)}catch(c){u.logger.error("parse component error",c)}return null},P=async(S,I)=>{let c=g.join(S,`${I}.yml`);if(!await x(c)&&(c=g.join(S,I,"index.yml"),!await x(c))||!(await T.lstat(c)).isFile())return null;const h=await T.readFile(c,"utf-8");return H.parse(h)},O=U(await Promise.all(p.pages.map(async({slug:S})=>{const I=U(await Promise.all(p.supportedLocales.map(async({locale:h})=>{const R=i?await y(i,ie(S),h):void 0;if(R)return{locale:h,page:R};const M=i?await y(i,S,h):void 0;return M&&{locale:h,page:M}}))),c=I[0]?.page;if(!c)return null;const f=c.sections.map(mt.unzipSection);return{id:c.id||Ue.nextId(),createdAt:c.createdAt,updatedAt:c.updatedAt,publishedAt:c.publishedAt,isPublic:c.isPublic??!0,templateConfig:c.templateConfig,slug:S,sections:Object.fromEntries(f.map(h=>[h.id,h])),sectionIds:f.map(h=>h.id),locales:Object.fromEntries(I.map(({locale:h,page:R})=>[h,R.meta])),dataSource:c.dataSource?Object.fromEntries([...new Set(I.flatMap(({page:h})=>Object.keys(h.dataSource??{})))].map(h=>[h,Object.fromEntries(I.map(({locale:R,page:M})=>{const L=M.dataSource?.[h];return[R,L||{}]}))])):Object.fromEntries([...new Set(I.flatMap(({page:h})=>h.sections.map(R=>R.id)))].map(h=>[h,Object.fromEntries(I.map(({locale:R,page:M})=>{const L=M.dataSource?.[h];if(L)return[R,L];const B=M.sections.find(J=>J.id===h);return[R,B?.properties||{}]}))]))}}))),D=U(await Promise.all((p?.routes||[]).map(async({path:S})=>{const I=A?await P(A,ie(S)):void 0;return{...I,id:I?.id||Ue.nextId(),createdAt:I?.createdAt??new Date().toISOString(),updatedAt:I?.updatedAt??new Date().toISOString(),publishedAt:new Date(0).toISOString(),path:I?.path??`/${I?.id}`,params:I?.params,handler:I?.handler??"Pages Kit",isPublic:I?.isPublic??!0,enabledGenerate:I?.enabledGenerate??!1,displayTemplateId:I?.displayTemplateId??void 0,dataSource:I?.dataSource??{}}}))),b=m?U(await Promise.all((p.components||[]).map(async({id:S})=>d(m,S)))):[];if(e){const S=(...I)=>{u.logger.info(`[${o?g.basename(t):g.basename(g.join(t,"../../../../"))}] importAssets:`,...I)};try{S("wait image-bin api ready"),await Ct.default({resources:[`${Ee.getComponentWebEndpoint(u.IMAGE_BIN_NAME)}/api/sdk/uploads`],validateStatus:f=>f>=200&&f<=500}),S("image-bin api is ready");const I={},c={};S("start to upload assets"),await Promise.allSettled([Ge(b,I,{getFilePath:f=>m&&g.join(m,f),onFinish:f=>{S(`upload ${f.length} component assets`)}}),Ge(O,c,{getFilePath:(f,h)=>{const R=Oe.default(O,h.slice(0,1));return i&&g.join(i,g.dirname(R.slug),f)},onFinish:f=>{S(`upload ${f.length} page assets`)}})]),S("upload assets done"),Pe.clear(),global.gc&&global.gc()}catch(I){S("Error during asset import:",I)}}const k={};if(a){const S=r&&g.join(g.dirname(r),"../../resources/components"),I=U(await Promise.all((p.resources?.components||[]).map(async({id:c})=>d(S,c))));I.length>0&&(k.components=Object.fromEntries(I.map((c,f)=>[c.id,{index:f,component:c}])))}return{supportedLocales:p.supportedLocales,pageIds:O.map(S=>S.id),components:Object.fromEntries(b.map((S,I)=>[S.id,{index:I,data:S}])),pages:Object.fromEntries(O.map(S=>[S.id,S])),config:p.config||{},resources:k,routeIds:D.map(S=>S.id),routes:Object.fromEntries(D.map(S=>[S.id,S])),dataSourceIds:[],dataSources:{}}}finally{o&&s&&await T.rm(s,{force:!0,recursive:!0})}}async function Ae(t,e,{routes:a,mergeMode:s="byUpdateTime",deleteRoutes:o=!1,publishMode:n=void 0}={}){try{n&&u.clearPreloadComponentsCacheByMode(n)}catch(p){u.logger.error("clear preload page cache error",{error:p})}const{pages:l,pageIds:r,routeIds:i,routes:m,supportedLocales:A}=t;if(n==="production"){let p=a??[],y=null;for(const d of i??[]){const P=m?.[d];if(P?.params&&P?.params.length>0&&P?.paramsOptions&&P?.paramsOptions.length>0){const O=se.generateParamCombinations({basePath:P.path,params:P.params,routeId:P.id,paramsOptions:P.paramsOptions,currentIndex:0,currentParams:[],currentOptionIds:[],result:[]}),D=Object.fromEntries(O.map(b=>[`${d}-${b.paramOptionIds.join("-")}`,b]));y={...y||{},...D},a||(p=[...p,...O.map(b=>`${d}-${b.paramOptionIds.join("-")}`)])}else a||p.push(d)}u.logger.info("routeIds to be published: ",p);for(const d of p){let P=d;if(P.includes("-")){const[b]=P.split("-");P=b}const O=m?.[P];if(!O){const b=e.pageIds.indexOf(P);b!==-1&&o&&(e.pageIds.splice(b,1),delete e.pages[P]);for(const k of e.pageIds)k.includes(`${P}-`)&&(e.pageIds.splice(e.pageIds.indexOf(k),1),delete e.pages[k]);u.logger.info("delete main route page",P);continue}if(d.includes("-")&&!y?.[d]){const b=e.pageIds.indexOf(d);b!==-1&&o&&(e.pageIds.splice(b,1),delete e.pages[d]),u.logger.info("delete page",d);continue}if(!O.displayTemplateId){u.logger.info("no display template",d);continue}const D=l[O.displayTemplateId];if(!D){u.logger.info("no template page",d);continue}if(e.pageIds.includes(d)){if(u.logger.info("has need update page",d),s==="replace")e.pages[d]=me({page:D,route:O,state:t,routeId:d,routePathInfo:y?.[d]}),u.logger.info("replace page",d);else if(s==="byUpdateTime"){const b=e.pages[O.id];(!b||O.updatedAt&&O.updatedAt>b.updatedAt)&&(e.pages[d]=me({page:D,route:O,state:t,routeId:d,routePathInfo:y?.[d]}),u.logger.info("replace page by update time",d))}}else e.pageIds.push(d),e.pages[d]=me({page:D,route:O,state:t,routeId:d,routePathInfo:y?.[d]}),u.logger.info("add page",d)}if(o&&!a)for(const d of e.pageIds)p?.includes(d)||(delete e.pages[d],u.logger.info("delete page",d)),e.pageIds=[...e.pageIds].filter(P=>p?.includes(P))}else{for(const p of r){const y=l[p];if(y)if(e.pageIds.includes(y.id)){if(s==="replace")e.pages[y.id]=y;else if(s==="byUpdateTime"){const d=e.pages[y.id];(!d||y.updatedAt&&y.updatedAt>d.updatedAt)&&(e.pages[y.id]=y)}}else e.pageIds.push(y.id),e.pages[y.id]=y}for(const p of i){const y=m[p];if(y)if(e.routeIds.includes(y.id)){if(s==="replace")e.routes[y.id]=y;else if(s==="byUpdateTime"){const d=e.routes[y.id];(!d||y.updatedAt&&y.updatedAt>d.updatedAt)&&(e.routes[y.id]=y)}}else e.routeIds.push(y.id),e.routes[y.id]=y}}if(e.supportedLocales.splice(0,e.supportedLocales.length),e.supportedLocales.push(...je.default(A)),o)for(const p of Object.keys(e.components))delete e.components[p];let j=JSON.parse(JSON.stringify(t.components));j=Object.fromEntries(await Promise.all(Object.entries(j).map(async([p,y])=>{const d=await Ze(y?.data);return[p,{...y,data:d}]}))),Object.assign(e.components,j),Object.assign(e.config,JSON.parse(JSON.stringify(t.config))),Re.default(t.resources.components)||(e.resources.components=JSON.parse(JSON.stringify(t.resources.components||{})))}const Ze=u.memoizeWithFs(async t=>{if(!Re.default(t?.properties))return t;if(t?.renderer?.type==="react-component"){const{script:e,PROPERTIES_SCHEMA:a}=t?.renderer||{};if(a||e&&e.includes("PROPERTIES_SCHEMA"))try{const s=await u.getExportSchemaValueFromCode(e??"","PROPERTIES_SCHEMA",t.id,a);s&&s.length>0&&t&&(t.properties={},s.forEach((o,n)=>{t?.properties&&(t.properties[o.id]={index:n,data:o})}))}catch(s){u.logger.error("getPropertiesFromCode error",{componentId:t.id,name:t.name},{error:s})}}return t},{subdir:"getPropertiesFromCode"});let ce,Q,ue,pe;const et=()=>Ee.getResources({types:[{did:Ce,type:we},{did:_t,type:we}]}),sa=async()=>{const t=et(),e={};for(const a of t){const o=(await oe.glob("**/.blocklet/pages/pages.config.yml",{cwd:a.path,absolute:!0}))[0],n=o&&g.join(g.dirname(o),"../../chunks");if(n&&await x(n)){const l=await T.readdir(n);for(const r of l)e[r]=g.join(n,r)}}return e};function tt(){return ce=(async()=>{const t=et();Q=(await Promise.all(t.map(async a=>{const s=a.path?await Le(a.path,{importAssets:!1}):void 0;return s?{blockletId:a.did,state:s,blockletTitle:a.title}:void 0}))).filter(a=>!!a),ue=Q.reduce((a,s)=>Object.assign(a,Object.fromEntries(Object.values(s.state.pages).map(o=>o?[o?.id,{page:o,blockletId:s.blockletId}]:[]))),{});const e=Q.reduce((a,s)=>Object.assign(a,Object.fromEntries(Object.values(s.state.components).map(o=>[o.data.id,{blockletId:s.blockletId,component:o.data}]))),{});pe=Object.fromEntries(await Promise.all(Object.entries(e).map(async([a,s])=>{const o=await Ze(s.component);return[a,{...s,component:o}]})))})(),ce}function at(t){const e=Te.default(async()=>{await tt().catch(a=>{u.logger.error("load resource states error",{error:a})}),await t?.({states:Q,pages:ue,components:pe})},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(Ie,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(Ie,e)}}const st=Symbol.for("GLOBAL_RESOURCE_STATES_LISTENER_KEY"),ot=globalThis;ot[st]?.();ot[st]=at(async({pages:t,components:e})=>{const a=await C.getProjectIds();u.logger.info(`start update resource states projects(${a.length})`,a);const s=De.default(10);await Promise.race([new Promise(o=>{setTimeout(()=>{o({})},30*1e3)}),Promise.all(a.map(o=>s(async()=>{nt({projectId:o,pages:t,components:e})})))]).catch(o=>{u.logger.error("update resource states failed:",o)})});C.startPeriodicCheck();process.on("beforeExit",()=>{C.stopPeriodicCheck()});process.on("SIGINT",()=>{C.stopPeriodicCheck(),process.exit(0)});process.on("SIGTERM",()=>{C.stopPeriodicCheck(),process.exit(0)});async function nt({projectId:t,pages:e,components:a}){const s=C.sharedInstances[t];if(!s){u.logger.info(`projectId: ${t} not found in sharedInstances`);return}const o=s.syncedStore.resources.pages,n=s.syncedStore.resources.components,l=await N.findByPk(t,{attributes:{exclude:["productionState","relatedBlocklets"]}});let r;if(l?.useAllResources)r=a;else{const j=(await ke.findAll({where:{projectId:t}})).map(p=>p.componentId);r=Object.fromEntries(Object.entries(a||{}).filter(([p])=>j.includes(p)))}const i=!xe(o,e),m=!xe(n,r);i||m?s.transact(()=>{i&&(s.syncedStore.resources.pages=e,u.logger.info(`[${t}] pages resources updated: ${Object.keys(e||{}).length} pages`)),m&&(s.syncedStore.resources.components=r,u.logger.info(`[${t}] components resources updated: ${Object.keys(r||{}).length} components`))}):u.logger.info(`[${t}] resource states unchanged, skipping update`),u.logger.info(`update [${t}] resource states summary:`,{pages:Object.keys(s.syncedStore.resources.pages||{}).length,components:Object.keys(s.syncedStore.resources.components||{}).length,pagesChanged:i,componentsChanged:m})}const ye=new Map;async function rt(t){if(!ye.has(t)){const e=Te.default(async a=>nt({projectId:a,pages:ue,components:pe}),3e3);ye.set(t,e)}return ye.get(t)(t)}async function oa(){u.logger.info("trigger reload all project resource"),E.default.events.emit(Ie)}async function na({ensureLoaded:t=!0}={}){return t&&(ce??=tt(),await ce),{states:Q,pages:ue,components:pe}}exports.COMPONENT_DID=Ce;exports.PUBLISH_MODES=ta;exports.Project=N;exports.RESOURCE_TYPE=we;exports.SITE_STATE_PATH=z;exports.STATE_MODES=ea;exports.SiteState=C;exports.copyRecursive=xt;exports.downloadAsset=Ye;exports.downloadAssets=We;exports.fromPackage=Le;exports.getDefaultState=Ke;exports.getResourceStates=na;exports.initPackResourceStates=at;exports.mergeState=Ae;exports.toPackage=Qe;exports.triggerReloadAllProjectResource=oa;exports.updateResourceStatesByProjectId=rt;
|