@blocklet/pages-kit-inner-components 0.6.84 → 0.6.85

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,1635 @@
1
+ import { d as Ne, l as f, I as et, c as tt, m as st, b as ot } from "./components-DLwSTd_N.js";
2
+ import { getYjsValue as V, syncedStore as at } from "@syncedstore/core";
3
+ import * as N from "yjs";
4
+ import { setPageDataSource as rt } from "@blocklet/pages-kit/utils/data-source";
5
+ import { getRouteMetaDataByOptionIds as nt, generateParamCombinations as Ie } from "@blocklet/pages-kit/utils/route";
6
+ import Ee from "lodash/cloneDeep";
7
+ import E from "@blocklet/sdk/lib/config";
8
+ import { mkdtempSync as it, existsSync as M, readFileSync as J, renameSync as ve, mkdirSync as F, rmSync as _e, writeFileSync as te, copyFileSync as ct, lstatSync as G, readdirSync as lt, createWriteStream as pt } from "fs";
9
+ import { join as b, basename as k, dirname as L } from "path";
10
+ import { nextId as Re } from "@blocklet/pages-kit/utils/common";
11
+ import { unzipSection as ut } from "@blocklet/pages-kit/utils/page-model";
12
+ import { getComponentDependencies as dt } from "@blocklet/pages-kit/utils/property";
13
+ import { getComponentWebEndpoint as ft, getResources as mt, call as gt } from "@blocklet/sdk/lib/component";
14
+ import { reactive as ht } from "@reactivedata/reactive";
15
+ import { globSync as se } from "glob";
16
+ import * as de from "lib0/decoding";
17
+ import * as D from "lib0/encoding";
18
+ import Fe from "lodash/debounce";
19
+ import be from "lodash/get";
20
+ import we from "lodash/isEmpty";
21
+ import je from "lodash/set";
22
+ import yt from "lodash/union";
23
+ import { LRUCache as Ae } from "lru-cache";
24
+ import St from "p-limit";
25
+ import { DataTypes as j, Sequelize as It, Model as xe, Op as Ge } from "sequelize";
26
+ import { pipeline as Et } from "stream/promises";
27
+ import { x as bt } from "tar";
28
+ import { withoutTrailingSlash as Be, withLeadingSlash as wt, joinURL as Y } from "ufo";
29
+ import At from "wait-on";
30
+ import { Awareness as Pt, encodeAwarenessUpdate as De, removeAwarenessStates as Ot, applyAwarenessUpdate as Ct } from "y-protocols/awareness";
31
+ import { writeUpdate as vt, writeSyncStep1 as Rt, readSyncMessage as jt } from "y-protocols/sync";
32
+ import * as B from "yaml";
33
+ import { m as Te } from "./html-DOgzvdOd.js";
34
+ import "sqlite3";
35
+ import "@blocklet/pages-kit/types/state";
36
+ const Dt = j.sqlite.DATE.parse;
37
+ j.sqlite.DATE.parse = (t, e) => typeof t == "number" ? new Date(t) : Dt(t, e);
38
+ const _ = new It({
39
+ dialect: "sqlite",
40
+ storage: Ne,
41
+ benchmark: process.env.ENABLE_SEQUELIZE_BENCHMARK === "true",
42
+ retry: {
43
+ match: [/SQLITE_BUSY/],
44
+ name: "query",
45
+ max: 10
46
+ },
47
+ // eslint-disable-next-line no-console
48
+ logging: process.env.ENABLE_SEQUELIZE_LOGGING === "true" ? console.log : !1
49
+ // logQueryParameters: true,
50
+ });
51
+ _.query("pragma journal_mode = WAL;");
52
+ _.query("pragma synchronous = normal;");
53
+ _.query("pragma journal_size_limit = 33554432;");
54
+ _.query("pragma cache_size = -2000;");
55
+ _.query("pragma mmap_size = 33554432;");
56
+ process.on("SIGINT", async () => {
57
+ await _.close(), process.exit(0);
58
+ });
59
+ process.on("SIGTERM", async () => {
60
+ await _.close(), process.exit(0);
61
+ });
62
+ async function Tt(t, e) {
63
+ try {
64
+ if (t.getDialect() !== "sqlite")
65
+ return;
66
+ const [s] = await t.query("SELECT 1");
67
+ if (!s || s.length === 0)
68
+ return;
69
+ await t.query("PRAGMA shrink_memory;");
70
+ } catch (s) {
71
+ if (s.name === "SequelizeConnectionError" || s?.message && /closed!/.test(s.message))
72
+ return;
73
+ console.error("Failed to cleanup SQLite memory", e, s);
74
+ }
75
+ }
76
+ let ge = null;
77
+ ge && clearInterval(ge);
78
+ ge = setInterval(
79
+ async () => {
80
+ f.info("Start cleanupSqliteMemory"), await Tt(_, Ne), f.info("End cleanupSqliteMemory");
81
+ },
82
+ 60 * 1e3 * 10
83
+ // 10 minutes
84
+ );
85
+ const kt = "z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o", ke = "page", he = "trigger-reload-project-resource", Ve = kt, Lt = "z2qa7BQdkEb3TwYyEYC1psK6uvmGnHSUHt5RM", Ut = "z8iZiDFg3vkkrPwsiba1TLXy3H9XHzFERsP8o";
86
+ class Pe extends xe {
87
+ // Foreign key to Component
88
+ }
89
+ Pe.init(
90
+ {
91
+ id: {
92
+ type: j.UUID,
93
+ allowNull: !1,
94
+ primaryKey: !0,
95
+ defaultValue: j.UUIDV4
96
+ },
97
+ projectId: {
98
+ type: j.UUID,
99
+ allowNull: !1
100
+ },
101
+ componentId: {
102
+ type: j.STRING,
103
+ allowNull: !1
104
+ }
105
+ },
106
+ { sequelize: _, tableName: "ProjectComponents", timestamps: !1 }
107
+ );
108
+ const $t = "SLUG_INVALID", q = (t) => ({
109
+ error: "slugInvalid",
110
+ code: $t,
111
+ field: "slug",
112
+ message: t
113
+ }), Mt = {
114
+ error: "slugRequired",
115
+ code: "SLUG_REQUIRED",
116
+ field: "slug",
117
+ message: () => "Project slug is required"
118
+ }, Nt = {
119
+ error: "slugAlreadyExists",
120
+ code: "SLUG_EXISTS",
121
+ field: "slug",
122
+ message: (t) => `Project slug "${t}" already exists`
123
+ }, _t = [
124
+ /\.\./,
125
+ // Directory traversal
126
+ /<[^>]*>/,
127
+ // HTML/XML tags
128
+ /%[0-9a-f]{2}/i,
129
+ // Percent encoding
130
+ /[<>'"%;{}()\\]/,
131
+ // Special characters
132
+ // eslint-disable-next-line no-control-regex
133
+ /\x00/,
134
+ // Null byte
135
+ /\n|\r|\t|\v|\f/,
136
+ // Control characters
137
+ /[^a-zA-Z0-9-_@/\\:]/
138
+ // Only allow specific characters
139
+ ], Le = (t) => {
140
+ if (!t) return "";
141
+ if (t === "/") return "/";
142
+ const e = Be(t);
143
+ return wt(e) || "/";
144
+ }, Ft = (t) => t.did === Ut;
145
+ class U extends xe {
146
+ static async getProjectByIdOrSlug(e) {
147
+ return U.findOne({
148
+ where: {
149
+ [Ge.or]: [{ id: e }, { slug: e }]
150
+ }
151
+ });
152
+ }
153
+ static async validateProjectSlug({
154
+ slug: e,
155
+ projectId: s
156
+ }) {
157
+ if (e == null)
158
+ return null;
159
+ if (e === "")
160
+ return Mt;
161
+ const o = Le(e);
162
+ if (e !== "/" && e.endsWith("/"))
163
+ return q((n) => `Project slug "${n}" cannot end with /`);
164
+ if (/\/{2,}/.test(e))
165
+ return q((n) => `Project slug "${n}" cannot contain consecutive /`);
166
+ if (/\s/.test(e))
167
+ return q((n) => `Project slug "${n}" cannot contain whitespace`);
168
+ if (_t.some((n) => n.test(e)))
169
+ return q((n) => `Project slug "${n}" contains invalid characters`);
170
+ if (E.components?.filter((n) => n.mountPoint && !Ft(n)).some((n) => Le(n.mountPoint) === o))
171
+ return q((n) => `Project slug "${n}" conflicts with existing blocklet`);
172
+ const r = await U.findOne({ where: { slug: e } });
173
+ return r && r?.id !== s ? Nt : null;
174
+ }
175
+ }
176
+ U.init(
177
+ {
178
+ id: {
179
+ type: j.UUID,
180
+ defaultValue: j.UUIDV4,
181
+ primaryKey: !0
182
+ },
183
+ name: {
184
+ type: j.STRING,
185
+ allowNull: !1
186
+ },
187
+ description: j.TEXT,
188
+ createdAt: j.DATE,
189
+ updatedAt: j.DATE,
190
+ createdBy: {
191
+ type: j.STRING,
192
+ allowNull: !1
193
+ },
194
+ updatedBy: {
195
+ type: j.STRING,
196
+ allowNull: !1
197
+ },
198
+ slug: j.STRING,
199
+ icon: j.STRING,
200
+ pinnedAt: j.DATE,
201
+ useAllResources: j.BOOLEAN,
202
+ npmSecret: j.STRING,
203
+ relatedBlocklets: {
204
+ type: j.JSON,
205
+ allowNull: !1,
206
+ defaultValue: {},
207
+ get() {
208
+ const t = this.getDataValue("relatedBlocklets");
209
+ if (typeof t == "object")
210
+ return t ?? {};
211
+ try {
212
+ return t ? JSON.parse(t) : {};
213
+ } catch (e) {
214
+ return f.error("Failed to parse relatedBlocklets", { error: e, rawValue: t }), {};
215
+ }
216
+ },
217
+ set(t) {
218
+ try {
219
+ this.setDataValue("relatedBlocklets", t ? JSON.stringify(t) : "{}");
220
+ } catch (e) {
221
+ f.error("Failed to set relatedBlocklets", { error: e, value: t }), this.setDataValue("relatedBlocklets", "{}");
222
+ }
223
+ }
224
+ },
225
+ productionState: {
226
+ type: j.JSON,
227
+ allowNull: !1,
228
+ defaultValue: {},
229
+ get() {
230
+ const t = this.getDataValue("productionState");
231
+ if (typeof t == "object")
232
+ return t ?? {};
233
+ try {
234
+ return t ? JSON.parse(t) : {};
235
+ } catch (e) {
236
+ return f.error("Failed to parse productionState", { error: e, rawValue: t }), {};
237
+ }
238
+ },
239
+ set(t) {
240
+ try {
241
+ this.setDataValue("productionState", t ? JSON.stringify(t) : "{}");
242
+ } catch (e) {
243
+ f.error("Failed to set productionState", { error: e, value: t }), this.setDataValue("productionState", "{}");
244
+ }
245
+ }
246
+ }
247
+ },
248
+ { sequelize: _, paranoid: !0 }
249
+ );
250
+ U.hasMany(Pe, {
251
+ foreignKey: "projectId",
252
+ as: "components"
253
+ });
254
+ function oe(t) {
255
+ t.observeDeep((e) => {
256
+ e.some((s) => s.changes.keys.has("updatedAt") || s.changes.keys.has("publishedAt")) || t.set("updatedAt", (/* @__PURE__ */ new Date()).toISOString());
257
+ });
258
+ }
259
+ function ze() {
260
+ return it(b(E.env.dataDir, "tmp-"));
261
+ }
262
+ function ae(t, e, s = []) {
263
+ return Array.isArray(t) ? t.flatMap((o, a) => ae(o, e, [...s, a])) : typeof t == "object" ? t === null ? [] : Object.entries(t).flatMap(([o, a]) => ae(a, e, [...s, o])) : e(t) ? [s] : [];
264
+ }
265
+ function T(t) {
266
+ return t.filter((e) => e != null);
267
+ }
268
+ function xt(t) {
269
+ t.pages && Object.keys(t.pages).forEach((s) => {
270
+ const o = V(t.pages[s]);
271
+ o && o instanceof N.Map && oe(o);
272
+ });
273
+ const e = V(t.pages);
274
+ e && e instanceof N.Map && e.observe((s) => {
275
+ s.changes.keys.forEach((o, a) => {
276
+ if (o.action === "add") {
277
+ const r = V(t.pages[a]);
278
+ r && r instanceof N.Map && oe(r);
279
+ }
280
+ });
281
+ });
282
+ }
283
+ function Gt(t) {
284
+ t.routes && Object.keys(t.routes).forEach((s) => {
285
+ const o = V(t.routes?.[s]);
286
+ o && o instanceof N.Map && oe(o);
287
+ });
288
+ const e = V(t.routes);
289
+ e && e instanceof N.Map && e.observe((s) => {
290
+ s.changes.keys.forEach((o, a) => {
291
+ if (o.action === "add") {
292
+ const r = V(t.routes?.[a]);
293
+ r && r instanceof N.Map && oe(r);
294
+ }
295
+ });
296
+ });
297
+ }
298
+ function Bt(t, e) {
299
+ for (const s of e || Object.keys(t.routes || {})) {
300
+ let o = s, a = [];
301
+ if (s.includes("-")) {
302
+ const [r, ...n] = s.split("-");
303
+ o = r, a = n || [];
304
+ }
305
+ if (t.routes?.[o] !== void 0) {
306
+ t.routes[o].publishedAt = (/* @__PURE__ */ new Date()).toISOString();
307
+ const r = t.routes[o];
308
+ if (!r || !r.params || r.params.length === 0)
309
+ continue;
310
+ if (s.includes("-") && a.length > 0) {
311
+ const n = nt(a, r);
312
+ n && (n.publishedAt = (/* @__PURE__ */ new Date()).toISOString());
313
+ }
314
+ if (!e) {
315
+ const n = Ie({
316
+ basePath: r.path,
317
+ params: r.params,
318
+ routeId: r.id,
319
+ paramsOptions: r.paramsOptions,
320
+ currentIndex: 0,
321
+ currentParams: [],
322
+ currentOptionIds: [],
323
+ result: []
324
+ });
325
+ for (const l of n)
326
+ l.routeMetaData ??= {}, l.routeMetaData.publishedAt = (/* @__PURE__ */ new Date()).toISOString();
327
+ }
328
+ }
329
+ }
330
+ }
331
+ function fe({
332
+ page: t,
333
+ route: e,
334
+ state: s,
335
+ routeId: o,
336
+ routePathInfo: a
337
+ }) {
338
+ f.info(
339
+ `Executing datasource data assembly, routeId: ${o}, routePathInfo: ${JSON.stringify(a)}`
340
+ );
341
+ const r = {
342
+ ...Ee(t),
343
+ id: o,
344
+ slug: a?.path ?? e.path,
345
+ createdAt: e.createdAt,
346
+ updatedAt: a?.routeMetaData?.updatedAt ?? e.updatedAt,
347
+ publishedAt: a?.routeMetaData?.publishedAt ?? e.publishedAt,
348
+ isPublic: (a?.routeMetaData?.isPublic ?? e.isPublic) && e.isPublic
349
+ };
350
+ for (const n of s.supportedLocales) {
351
+ if (e.dataSource) {
352
+ let l = e.id;
353
+ a && (l = a.paramOptionIds.join("-"));
354
+ const p = e.dataSource.pathDataMappings?.[l]?.dataCache?.[n.locale] ?? e.dataSource.pathDataMappings?.[l]?.dataCache?.[s.config.defaultLocale || "en"];
355
+ if (!p)
356
+ continue;
357
+ rt(r, s, n.locale, p);
358
+ }
359
+ a && a.routeMetaData && (a.routeMetaData.publishedAt = (/* @__PURE__ */ new Date()).toISOString());
360
+ }
361
+ return r;
362
+ }
363
+ ["true", "1", "yes", "y"].includes(process.env.USE_FS_CACHE_HTML ?? "");
364
+ const Vt = 60 * 60 * 1e3, W = new Ae({
365
+ max: 100,
366
+ ttl: Vt,
367
+ ttlResolution: 10 * 1e3,
368
+ // 10 seconds
369
+ allowStale: !0
370
+ });
371
+ function zt(t, e = []) {
372
+ let s = 0;
373
+ const o = Array.from(W.keys()), a = t.map((r) => Be(r));
374
+ for (const r of o)
375
+ for (const n of a) {
376
+ if (Te(r, { currentPath: n })) {
377
+ W.delete(r), s++, f.info(`[Cache CLEAR] key: ${r}`);
378
+ break;
379
+ }
380
+ for (const l of e)
381
+ if (Te(r, { currentPath: `/${l}${n}` })) {
382
+ W.delete(r), s++, f.info(`[Cache CLEAR] key: ${r}`);
383
+ break;
384
+ }
385
+ }
386
+ return f.info(`[Cache CLEAR] cleared ${s} entries for paths:`, a), s;
387
+ }
388
+ function Kt() {
389
+ const t = W.size;
390
+ return W.clear(), f.info(`[Cache CLEAR ALL] cleared ${t} entries`), t;
391
+ }
392
+ E.events.on(E.Events.envUpdate, Kt);
393
+ const { uploadToMediaKit: qt } = require("@blocklet/uploader-server"), Oe = /^\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, Ue = /mediakit:\/\/([a-f0-9]{32}\.(jpe?g|png|gif|svg|bmp|webp|mp4|m4v|webm))/gi, Ht = 1e4, Jt = 3e4, Z = 0, me = 1, Yt = 0, Wt = 1, ye = E, H = b(process.env.BLOCKLET_DATA_DIR, "site-state"), Ms = ["production", "draft"], Ns = ["production"];
394
+ function re(t) {
395
+ return t?.replace(/\//g, "|") || "";
396
+ }
397
+ function Xt() {
398
+ const t = ye.env.languages?.map((s) => ({ locale: s.code, name: s.name })) || [], e = t[0]?.locale || "en";
399
+ return {
400
+ pageIds: [],
401
+ pages: {},
402
+ routeIds: [],
403
+ routes: {},
404
+ dataSourceIds: [],
405
+ dataSources: {},
406
+ components: {},
407
+ supportedLocales: t,
408
+ config: { defaultLocale: e },
409
+ resources: {}
410
+ };
411
+ }
412
+ class C extends N.Doc {
413
+ constructor(e) {
414
+ super(), this.options = e, M(this.draftYjsFilePath) && N.applyUpdate(this, J(this.draftYjsFilePath)), this.syncedStore = ht(
415
+ at(
416
+ {
417
+ pages: {},
418
+ pageIds: [],
419
+ components: {},
420
+ supportedLocales: [],
421
+ config: {},
422
+ resources: {},
423
+ routeIds: [],
424
+ routes: {},
425
+ dataSourceIds: [],
426
+ dataSources: {}
427
+ },
428
+ this
429
+ )
430
+ ), this.initObserver(), this.on("update", this.updateHandler), this.awareness = new Pt(this), this.awareness.on("update", this.awarenessChangeHandler), this.ensureDataStructure();
431
+ }
432
+ // 延迟释放时间:5 分钟
433
+ static RELEASE_DELAY = 5 * 60 * 1e3;
434
+ // 定期检查间隔:2 小时
435
+ static PERIODIC_CHECK_INTERVAL = 2 * 60 * 60 * 1e3;
436
+ // 2 hours
437
+ static sharedInstances = {};
438
+ static pageUrlMapCache = new Ae({
439
+ max: 100,
440
+ ttl: 1e3 * 60 * 60 * 24
441
+ // 1 day
442
+ });
443
+ // 定期检查定时器
444
+ static periodicCheckTimer;
445
+ // safe delete project state dir
446
+ static safeDeleteProjectStateDir(e) {
447
+ if (!e)
448
+ throw new Error("Should provide project context");
449
+ try {
450
+ const s = b(H, e), o = b(H, `@del-${e}`);
451
+ ve(s, o);
452
+ } catch (s) {
453
+ f.error("Failed to safe delete project state dir:", s);
454
+ }
455
+ }
456
+ static async getProjectIds() {
457
+ return (await U.findAll({ attributes: ["id"], raw: !0 }))?.map((e) => e.id);
458
+ }
459
+ /** @deprecated 不再使用这个 getter 了,仅作为兼容性处理,请使用 getProjectIds 代替 */
460
+ static get projectIds() {
461
+ return se("*/", {
462
+ cwd: H,
463
+ ignore: ["@del-*", "@tmp-*", ".*", "staging", "production", "@backup-*", "undefined"]
464
+ // Ignore temp directories and hidden files
465
+ });
466
+ }
467
+ /** @deprecated 不再使用这个 getter 了,仅作为兼容性处理 */
468
+ static get allShared() {
469
+ return this.projectIds.map((e) => C.shared(e));
470
+ }
471
+ static shared(e) {
472
+ if (!e)
473
+ throw new Error("Should provide project context");
474
+ let s = C.sharedInstances[e];
475
+ return s || (s = new C({
476
+ path: b(H, e)
477
+ }), C.sharedInstances[e] = s, s);
478
+ }
479
+ // 轻量级 production 状态获取,不加载 draft 数据
480
+ static async getProductionState(e) {
481
+ const s = await U.findByPk(e, {
482
+ attributes: ["productionState"]
483
+ });
484
+ if (we(s?.productionState)) {
485
+ const o = b(H, e, "production"), a = await qe(o, { includeResources: !0 }) ?? Xt();
486
+ if (!a?.config?.defaultLocale) {
487
+ a.config ??= {};
488
+ const r = ye.env.languages?.map((n) => ({ locale: n.code, name: n.name })) || [];
489
+ a.config.defaultLocale = r[0]?.locale;
490
+ }
491
+ return a;
492
+ }
493
+ return s?.productionState;
494
+ }
495
+ destroy() {
496
+ this.cancelRelease(), this.save({ flush: !0 }), this.conns.forEach((s, o) => this.closeConn(o)), this.awareness.destroy();
497
+ const e = k(this.options.path);
498
+ delete C.sharedInstances[e], super.destroy();
499
+ }
500
+ initObserver() {
501
+ xt(this.syncedStore), Gt(this.syncedStore);
502
+ }
503
+ get draftYjsFilePath() {
504
+ return b(this.options.path, "draft.yjs");
505
+ }
506
+ static async getStateByProjectId(e, s) {
507
+ if (s === "draft") {
508
+ const o = C.shared(e);
509
+ return JSON.parse(JSON.stringify(o.syncedStore));
510
+ }
511
+ return C.getProductionState(e);
512
+ }
513
+ async getState(e) {
514
+ if (e === "draft")
515
+ return JSON.parse(JSON.stringify(this.syncedStore));
516
+ const s = k(this.options.path);
517
+ return C.getProductionState(s);
518
+ }
519
+ async setState(e, s) {
520
+ const o = await ts(s, { exportAssets: !1, includeResources: !0 }), a = this.getPublishDir(e);
521
+ if (F(L(a), { recursive: !0 }), _e(a, { force: !0, recursive: !0 }), ve(o, a), e === "production") {
522
+ const r = k(this.options.path);
523
+ C.pageUrlMapCache.delete(r);
524
+ const n = Ee(s);
525
+ await U.update({ productionState: n }, { where: { id: r } });
526
+ }
527
+ }
528
+ getPublishDir(e) {
529
+ return b(this.options.path, e);
530
+ }
531
+ syncedStore;
532
+ conns = /* @__PURE__ */ new Map();
533
+ awareness;
534
+ // 延迟释放定时器
535
+ releaseTimer;
536
+ awarenessChangeHandler = ({ added: e, updated: s, removed: o }, a) => {
537
+ const r = e.concat(s, o);
538
+ if (a !== null) {
539
+ const p = this.conns.get(a);
540
+ p && (e.forEach((y) => {
541
+ p.add(y);
542
+ }), o.forEach((y) => {
543
+ p.delete(y);
544
+ }));
545
+ }
546
+ const n = D.createEncoder();
547
+ D.writeVarUint(n, me), D.writeVarUint8Array(n, De(this.awareness, r));
548
+ const l = D.toUint8Array(n);
549
+ this.conns.forEach((p, y) => this.send(y, l));
550
+ };
551
+ updateHandler = (e) => {
552
+ const s = D.createEncoder();
553
+ D.writeVarUint(s, Z), vt(s, e);
554
+ const o = D.toUint8Array(s);
555
+ this.conns.forEach((a, r) => this.send(r, o));
556
+ };
557
+ ensureDataStructure = () => {
558
+ const { supportedLocales: e, pages: s, pageIds: o, config: a, routes: r, routeIds: n } = this.syncedStore;
559
+ {
560
+ const l = new Set(Object.keys(s));
561
+ let p = 0;
562
+ for (; p < o.length; ) {
563
+ const y = o[p];
564
+ l.has(y) ? (l.delete(y), p++) : o.splice(p, 1);
565
+ }
566
+ }
567
+ {
568
+ const l = new Set(Object.keys(r));
569
+ let p = 0;
570
+ for (; p < n.length; ) {
571
+ const y = n[p];
572
+ l.has(y) ? (l.delete(y), p++) : n.splice(p, 1);
573
+ }
574
+ }
575
+ e.splice(0, e.length), e.push(...ye.env.languages.map((l) => ({ locale: l.code, name: l.name }))), a.defaultLocale = e[0]?.locale;
576
+ {
577
+ let l = 0;
578
+ const p = /* @__PURE__ */ new Set();
579
+ for (; l < e.length; ) {
580
+ const { locale: y } = e[l];
581
+ p.has(y) ? e.splice(l, 1) : (l++, p.add(y));
582
+ }
583
+ }
584
+ };
585
+ send = (e, s) => {
586
+ e.readyState !== Yt && e.readyState !== Wt && this.closeConn(e);
587
+ try {
588
+ e.send(s, (o) => {
589
+ o && this.closeConn(e);
590
+ });
591
+ } catch {
592
+ this.closeConn(e);
593
+ }
594
+ };
595
+ closeConn = (e) => {
596
+ if (e.removeAllListeners(), this.conns.has(e)) {
597
+ const s = this.conns.get(e);
598
+ this.conns.delete(e), s && Ot(this.awareness, Array.from(s), null);
599
+ }
600
+ e.close(), this.checkAndScheduleRelease();
601
+ };
602
+ // 检查并调度延迟释放
603
+ checkAndScheduleRelease() {
604
+ this.conns.size === 0 && this.scheduleRelease();
605
+ }
606
+ // 调度延迟释放
607
+ scheduleRelease() {
608
+ this.cancelRelease();
609
+ const e = k(this.options.path);
610
+ this.releaseTimer = setTimeout(() => {
611
+ f.info(`[SiteState] releasing instance due to no active connections: ${e}`), this.conns.size === 0 && (this.releaseTimer = void 0, this.destroy());
612
+ }, C.RELEASE_DELAY), f.info(`[SiteState] scheduled release for project ${e} in ${C.RELEASE_DELAY / 1e3}s`);
613
+ }
614
+ // 取消延迟释放
615
+ cancelRelease() {
616
+ if (this.releaseTimer) {
617
+ clearTimeout(this.releaseTimer), this.releaseTimer = void 0;
618
+ const e = k(this.options.path);
619
+ f.info(`[SiteState] cancelled scheduled release for project ${e}`);
620
+ }
621
+ }
622
+ autoSave = Fe(() => {
623
+ F(L(this.draftYjsFilePath), { recursive: !0 }), te(this.draftYjsFilePath, N.encodeStateAsUpdate(this));
624
+ }, Ht);
625
+ save = ({ flush: e = !1 } = {}) => {
626
+ this.autoSave(), e && this.autoSave.flush();
627
+ };
628
+ publish = async ({ mode: e, routes: s }) => {
629
+ const o = k(this.options.path);
630
+ await as(o);
631
+ const a = await this.getState("draft"), r = await this.getState("production");
632
+ await Me(a, r, { routes: s, mergeMode: "replace", deleteRoutes: !0, publishMode: e }), r.config.publishedAt = (/* @__PURE__ */ new Date()).getTime(), Bt(this.syncedStore, s), await this.setState(e, r), await this.clearPageCacheForRoutes(s, r);
633
+ };
634
+ mergeState = async (e, s) => {
635
+ const o = JSON.parse(JSON.stringify(s));
636
+ e.config.fontFamily ??= {};
637
+ const a = o.config?.fontFamily, r = e.config?.fontFamily;
638
+ e.config.fontFamily.title = a?.title || r?.title, e.config.fontFamily.description = a?.description || r?.description, await new Promise((n, l) => {
639
+ this.transact(async () => {
640
+ try {
641
+ const p = await Me(e, s);
642
+ n(p);
643
+ } catch (p) {
644
+ l(p);
645
+ }
646
+ });
647
+ });
648
+ };
649
+ clearPageCacheForRoutes = async (e, s) => {
650
+ const o = k(this.options.path), r = (await U.findByPk(o))?.slug || o;
651
+ let n = e;
652
+ (!n || n.length === 0) && (n = s.pageIds ?? []), f.info(`[SiteState] clearing page cache for project ${o}, routes:`, n || []);
653
+ const l = s.supportedLocales.map((w) => w.locale), p = [], y = n.filter((w) => s.pageIds?.includes(w));
654
+ for (const w of y) {
655
+ const I = s.pages[w].slug;
656
+ r && r !== o && (r === "/" ? p.push(I) : p.push(`/${r}${I}`)), p.push(`/${o}${I}`);
657
+ }
658
+ if (p.length > 0)
659
+ try {
660
+ const w = zt(p, l);
661
+ f.info(`[SiteState] cleared ${w} page cache entries for project ${o}, routes:`, n);
662
+ } catch {
663
+ }
664
+ };
665
+ addConnection = (e) => {
666
+ if (this.conns.has(e))
667
+ return;
668
+ this.cancelRelease(), e.binaryType = "arraybuffer", this.conns.set(e, /* @__PURE__ */ new Set()), e.on("message", (a) => this.messageListener(e, new Uint8Array(a)));
669
+ let s = !0;
670
+ const o = setInterval(() => {
671
+ if (!s)
672
+ this.conns.has(e) && this.closeConn(e), clearInterval(o);
673
+ else if (this.conns.has(e)) {
674
+ s = !1;
675
+ try {
676
+ e.ping();
677
+ } catch {
678
+ this.closeConn(e), clearInterval(o);
679
+ }
680
+ }
681
+ }, Jt);
682
+ e.on("close", () => {
683
+ this.closeConn(e), clearInterval(o);
684
+ }), e.on("pong", () => {
685
+ s = !0;
686
+ });
687
+ {
688
+ const a = D.createEncoder();
689
+ D.writeVarUint(a, Z), Rt(a, this), this.send(e, D.toUint8Array(a));
690
+ const r = this.awareness.getStates();
691
+ if (r.size > 0) {
692
+ const n = D.createEncoder();
693
+ D.writeVarUint(n, me), D.writeVarUint8Array(n, De(this.awareness, Array.from(r.keys()))), this.send(e, D.toUint8Array(n));
694
+ }
695
+ }
696
+ };
697
+ messageListener = (e, s) => {
698
+ try {
699
+ const o = D.createEncoder(), a = de.createDecoder(s), r = de.readVarUint(a);
700
+ switch (r) {
701
+ case Z:
702
+ D.writeVarUint(o, Z), jt(a, o, this, null), D.length(o) > 1 && (this.ensureDataStructure(), this.send(e, D.toUint8Array(o)));
703
+ break;
704
+ case me: {
705
+ Ct(this.awareness, de.readVarUint8Array(a), e);
706
+ break;
707
+ }
708
+ default:
709
+ f.warn(`Unsupported messageType ${r}`);
710
+ }
711
+ } catch (o) {
712
+ f.error(o);
713
+ }
714
+ this.save();
715
+ };
716
+ // 这个方法还是需要动态的,因为可能会动态修改 projectSlug、语言之类的
717
+ static async pageUrlMap(e, s) {
718
+ let o = [];
719
+ s ? o = [s] : o = await this.getProjectIds();
720
+ let a = {};
721
+ if (e === "production" && o?.length) {
722
+ const r = new Map(o?.map((n) => [n, !0]) || []);
723
+ for (const n of o) {
724
+ const l = C.pageUrlMapCache.get(n);
725
+ l && (a = { ...a, ...l }, r.delete(n));
726
+ }
727
+ o = Array.from(r.keys());
728
+ }
729
+ if (o?.length) {
730
+ const r = await U.findAll({
731
+ where: {
732
+ id: {
733
+ [Ge.in]: o
734
+ }
735
+ }
736
+ });
737
+ await Promise.all(
738
+ r?.map(async (n) => {
739
+ const l = n.id, p = n.slug || l, y = {}, w = e === "production" && n?.productionState ? n.productionState : await C.getStateByProjectId(n.id, e), R = yt(
740
+ E.env.languages?.map((u) => u.code) || [],
741
+ w.supportedLocales?.map((u) => u.locale) || []
742
+ ), I = (u, c) => {
743
+ p && (y[Y("/", p, u)] = {
744
+ ...c,
745
+ shouldRedirect: !0,
746
+ mainPage: !0
747
+ }), y[Y("/", l, u)] = {
748
+ ...c,
749
+ shouldRedirect: !0,
750
+ mainPage: !0
751
+ };
752
+ for (const g of R) {
753
+ const O = { ...c, locale: g };
754
+ y[Y("/", g, l, u)] = O, p && (y[Y("/", g, p, u)] = O);
755
+ }
756
+ };
757
+ if (e === "draft")
758
+ for (const u of w.routeIds || []) {
759
+ const c = w?.routes?.[u];
760
+ if (!c) continue;
761
+ if (c.params && c.params.length > 0) {
762
+ const m = Ie({
763
+ basePath: c.path,
764
+ params: c.params,
765
+ routeId: c.id,
766
+ paramsOptions: c.paramsOptions,
767
+ currentIndex: 0,
768
+ currentParams: [],
769
+ currentOptionIds: [],
770
+ result: []
771
+ });
772
+ for (const d of m) {
773
+ const h = d.path, A = {
774
+ projectId: l,
775
+ projectSlug: p,
776
+ pageSlug: h,
777
+ pageId: c.displayTemplateId || "",
778
+ routeId: u,
779
+ // default locale
780
+ defaultLocale: R?.[0],
781
+ locales: R,
782
+ publishedAt: w.config.publishedAt,
783
+ isPublic: c.isPublic && d?.routeMetaData?.isPublic
784
+ };
785
+ I(h, A);
786
+ }
787
+ }
788
+ const g = c.path, O = {
789
+ projectId: l,
790
+ projectSlug: p,
791
+ pageSlug: g,
792
+ pageId: c.displayTemplateId || "",
793
+ routeId: u,
794
+ // default locale
795
+ defaultLocale: R?.[0],
796
+ locales: R,
797
+ publishedAt: w.config.publishedAt,
798
+ isPublic: c.isPublic
799
+ };
800
+ I(g, O);
801
+ }
802
+ for (const u of w.pageIds || []) {
803
+ const c = w.pages[u];
804
+ if (!c || e === "production" && !c.isPublic)
805
+ continue;
806
+ const g = c.slug, O = n.slug || l, m = {
807
+ projectId: l,
808
+ projectSlug: O,
809
+ pageSlug: g,
810
+ pageId: u,
811
+ // default locale
812
+ defaultLocale: R?.[0],
813
+ locales: R,
814
+ publishedAt: w.config.publishedAt,
815
+ isPublic: c.isPublic,
816
+ templateConfig: c.templateConfig
817
+ };
818
+ I(g, m);
819
+ }
820
+ e === "production" && C.pageUrlMapCache.set(l, y), a = { ...a, ...y };
821
+ })
822
+ );
823
+ }
824
+ return a;
825
+ }
826
+ getDocumentSize() {
827
+ return N.encodeStateAsUpdate(this).byteLength;
828
+ }
829
+ static getInstancesSizeInfo() {
830
+ const e = [];
831
+ for (const [s, o] of Object.entries(C.sharedInstances)) {
832
+ const a = o.getDocumentSize();
833
+ e.push({
834
+ projectId: s,
835
+ sizeInBytes: a,
836
+ sizeInMB: `${(a / (1024 * 1024)).toFixed(2)} MB`,
837
+ activeConnections: o.conns.size
838
+ });
839
+ }
840
+ return e;
841
+ }
842
+ // 启动定期检查
843
+ static startPeriodicCheck() {
844
+ this.periodicCheckTimer || (this.periodicCheckTimer = setInterval(() => {
845
+ this.performPeriodicCheck();
846
+ }, this.PERIODIC_CHECK_INTERVAL), f.info(
847
+ `[SiteState] periodic check started, interval: ${this.PERIODIC_CHECK_INTERVAL / (60 * 60 * 1e3)} hours`
848
+ ));
849
+ }
850
+ // 停止定期检查
851
+ static stopPeriodicCheck() {
852
+ this.periodicCheckTimer && (clearInterval(this.periodicCheckTimer), this.periodicCheckTimer = void 0, f.info("[SiteState] periodic check stopped"));
853
+ }
854
+ // 执行定期检查
855
+ static performPeriodicCheck() {
856
+ const e = Object.keys(C.sharedInstances).length, s = [], o = [];
857
+ for (const [a, r] of Object.entries(C.sharedInstances))
858
+ r.conns.size === 0 ? s.push({ projectId: a, instance: r }) : o.push({ projectId: a, connections: r.conns.size });
859
+ if (f.info(
860
+ `[SiteState] periodic check summary: total instances: ${e}, with connections: ${o.length}, without connections: ${s.length}`
861
+ ), s.length > 0) {
862
+ f.info(
863
+ `[SiteState] releasing ${s.length} instances without connections:`,
864
+ s.map((r) => r.projectId)
865
+ );
866
+ let a = 0;
867
+ for (const { projectId: r, instance: n } of s)
868
+ try {
869
+ f.info(`[SiteState] releasing instance due to periodic check: ${r}`), n.destroy(), a++;
870
+ } catch (l) {
871
+ f.error(`[SiteState] failed to release instance ${r} during periodic check:`, l);
872
+ }
873
+ f.info(
874
+ `[SiteState] periodic check completed: ${a}/${s.length} instances released successfully`
875
+ );
876
+ } else e > 0 ? f.debug("[SiteState] periodic check: all instances have active connections") : f.debug("[SiteState] periodic check: no instances exist");
877
+ }
878
+ }
879
+ async function Qt(t, e, s) {
880
+ if (!t || !M(t) || !G(t).isFile())
881
+ return null;
882
+ let o = s[t];
883
+ return o || (o = (async () => {
884
+ try {
885
+ return (await qt({
886
+ filePath: t,
887
+ fileName: e
888
+ }))?.data?.filename;
889
+ } catch (a) {
890
+ return f.error(`Failed to upload asset ${t}:`, a), null;
891
+ }
892
+ })(), s[t] = o), o;
893
+ }
894
+ const Zt = async (t, e) => {
895
+ const s = k(t), o = await gt({
896
+ name: Ve,
897
+ path: Y("/uploads", s),
898
+ responseType: "stream",
899
+ method: "GET"
900
+ });
901
+ if (o.status >= 200 && o.status < 400) {
902
+ const a = pt(e);
903
+ await Et(o.data, a);
904
+ } else
905
+ throw new Error(`download asset failed ${o.status}`);
906
+ }, es = async (t, e) => {
907
+ await Promise.all(
908
+ t.map(async (s) => {
909
+ try {
910
+ await Zt(s, b(e, k(s)));
911
+ } catch (o) {
912
+ f.error(`Failed to export assets: ${s}, ${o}`);
913
+ }
914
+ })
915
+ );
916
+ };
917
+ function Ke(t) {
918
+ return Oe.test(t) ? [t] : X.test(t) ? (Ue.lastIndex = 0, Array.from(t.matchAll(Ue)).map((s) => s[1]).filter((s) => !!s)) : [];
919
+ }
920
+ async function ee(t, e, s) {
921
+ const { getFilename: o, exportAssets: a } = s, r = b(e, o(t));
922
+ if (F(L(r), { recursive: !0 }), te(r, B.stringify(t)), a) {
923
+ const l = ae(
924
+ t,
925
+ (p) => typeof p == "string" && (Oe.test(p) || X.test(p))
926
+ ).map((p) => {
927
+ const y = be(t, p);
928
+ return Ke(y);
929
+ }).flat().filter(Boolean);
930
+ await es(l, L(r));
931
+ }
932
+ }
933
+ const Se = new Ae({
934
+ max: 100,
935
+ ttl: 1 * 60 * 1e3
936
+ // 1 minute
937
+ });
938
+ async function $e(t, e, s) {
939
+ const o = ae(
940
+ t,
941
+ (l) => typeof l == "string" && (Oe.test(l) || X.test(l))
942
+ ), a = St(2), r = o.map(
943
+ (l) => a(async () => {
944
+ try {
945
+ const p = be(t, l), y = Ke(p);
946
+ for (const w of y) {
947
+ const R = k(w), I = s.getFilePath(w, l), u = I ? `${I}:${R}` : R, c = Se.get(u);
948
+ if (c) {
949
+ X.test(p) || je(t, l, c);
950
+ return;
951
+ }
952
+ const g = await Qt(I, R, e);
953
+ g && (X.test(p) || je(t, l, g), Se.set(u, g));
954
+ }
955
+ } catch (p) {
956
+ f.error(`Failed to process upload for path ${l.join(".")}:`, p.message || p.reason);
957
+ }
958
+ })
959
+ ), n = await Promise.allSettled(r);
960
+ s.onFinish?.(n);
961
+ }
962
+ async function ts(t, {
963
+ exportAssets: e,
964
+ pageIds: s = "all",
965
+ componentIds: o = "all",
966
+ rawConfig: a,
967
+ includeResources: r = !1,
968
+ routeIds: n = "all"
969
+ } = {}) {
970
+ const l = s === "all" ? t.pageIds : s, p = dt({
971
+ state: t,
972
+ pageIds: l,
973
+ componentIds: o === "all" ? Object.keys(t.components) : o
974
+ });
975
+ Object.entries(t.components).forEach(([i, S]) => {
976
+ S.data?.renderer?.type === "component-template" && p.push(i);
977
+ });
978
+ const y = n === "all" ? t.routeIds : n, w = (i) => ({
979
+ id: i.id,
980
+ name: i.name,
981
+ isTemplateSection: i.isTemplateSection ?? !1,
982
+ templateDescription: i.templateDescription,
983
+ /** @deprecated 已经废弃,llmConfig 从 component / resources.component 中获取 */
984
+ // llmConfig: section.llmConfig,
985
+ component: i.component,
986
+ config: i.config,
987
+ visibility: i.visibility,
988
+ sections: i?.sectionIds ? T(
989
+ i?.sectionIds?.map((S) => {
990
+ const v = i.sections?.[S];
991
+ return v && w(v);
992
+ })
993
+ ) : void 0
994
+ /** @deprecated 已经废弃,数据在 page.dataSource 中管理 */
995
+ // properties: section.locales?.[locale] ?? {},
996
+ }), R = (i, S) => ({
997
+ id: i.id,
998
+ createdAt: i.createdAt,
999
+ updatedAt: i.updatedAt,
1000
+ publishedAt: i.publishedAt,
1001
+ isPublic: i.isPublic ?? !0,
1002
+ templateConfig: i.templateConfig,
1003
+ meta: i.locales?.[S] ?? {},
1004
+ sections: T(
1005
+ i.sectionIds.map((v) => {
1006
+ const x = i.sections[v];
1007
+ return x && w(x);
1008
+ })
1009
+ ),
1010
+ // 将 dataSource.sectionId.locale 转换为 dataSource.sectionId
1011
+ dataSource: Object.fromEntries(
1012
+ Object.entries(i.dataSource || {}).map(([v, x]) => [v, x?.[S] ?? {}])
1013
+ )
1014
+ }), I = (i) => ({
1015
+ id: i.id,
1016
+ createdAt: i.createdAt,
1017
+ updatedAt: i.updatedAt,
1018
+ publishedAt: i.publishedAt,
1019
+ path: i.path,
1020
+ handler: i.handler,
1021
+ isPublic: i.isPublic ?? !0,
1022
+ params: i.params ?? [],
1023
+ enabledGenerate: i.enabledGenerate ?? !1,
1024
+ displayTemplateId: i.displayTemplateId,
1025
+ dataSource: i.dataSource
1026
+ }), u = T(
1027
+ y.map((i) => {
1028
+ const S = t.routes[i];
1029
+ return S && I(S);
1030
+ })
1031
+ ), c = T(
1032
+ t.supportedLocales.map((i) => i.locale).flatMap(
1033
+ (i) => l.map((S) => {
1034
+ const v = t.pages[S];
1035
+ return v && {
1036
+ locale: i,
1037
+ slug: v.slug,
1038
+ page: R(v, i)
1039
+ };
1040
+ })
1041
+ )
1042
+ ), g = ze(), O = b(g, "pages");
1043
+ F(O, { recursive: !0 });
1044
+ const m = b(g, "components");
1045
+ F(m, { recursive: !0 });
1046
+ const d = b(g, "routes");
1047
+ F(d, { recursive: !0 });
1048
+ for (const { locale: i, slug: S, page: v } of c)
1049
+ await ee(v, O, {
1050
+ getFilename: () => `${re(S) || "index"}.${i}.yml`,
1051
+ exportAssets: e
1052
+ });
1053
+ for (const i of u)
1054
+ await ee(i, d, {
1055
+ // getFilename: () => `${sanitizeSlug(route.path)}.yml`,
1056
+ getFilename: () => `${re(i.path) || "index"}.yml`,
1057
+ exportAssets: e
1058
+ });
1059
+ for (const i of p) {
1060
+ const S = t.components[i]?.data;
1061
+ S && await ee(S, m, {
1062
+ getFilename: (v) => `${v.name || "unnamed"}.${v.id}.yml`,
1063
+ exportAssets: e
1064
+ });
1065
+ }
1066
+ const h = b(g, ".blocklet/pages/pages.config.yml");
1067
+ F(L(h), { recursive: !0 });
1068
+ const A = {
1069
+ pages: T(
1070
+ l.map((i) => {
1071
+ const S = t.pages[i];
1072
+ return S && { id: i, slug: S.slug };
1073
+ })
1074
+ ),
1075
+ routes: T(
1076
+ y.map((i) => {
1077
+ const S = t.routes[i];
1078
+ return S && { id: i, path: S.path };
1079
+ })
1080
+ ),
1081
+ components: T(
1082
+ p.map((i) => {
1083
+ const S = t.components[i]?.data;
1084
+ return S && {
1085
+ id: i,
1086
+ name: S.name
1087
+ };
1088
+ })
1089
+ ),
1090
+ ...r ? {
1091
+ resources: {
1092
+ components: T(
1093
+ Object.keys(t.resources?.components || {}).filter((i) => p.includes(i)).map((i) => ({
1094
+ id: i,
1095
+ name: t.resources?.components?.[i]?.component?.name
1096
+ }))
1097
+ )
1098
+ }
1099
+ } : {},
1100
+ supportedLocales: t.supportedLocales,
1101
+ config: t.config
1102
+ };
1103
+ te(h, B.stringify(A));
1104
+ const P = b(g, "config.source.json");
1105
+ if (a && te(P, JSON.stringify(a)), r) {
1106
+ const i = b(g, "resources"), S = b(i, "components");
1107
+ F(S, { recursive: !0 });
1108
+ for (const z of Object.keys(t?.resources?.components ?? {}).filter(
1109
+ ($) => p.includes($)
1110
+ )) {
1111
+ const $ = t.resources?.components?.[z]?.component;
1112
+ $ && await ee($, S, {
1113
+ getFilename: (K) => `${K.name || "unnamed"}.${K.id}.yml`,
1114
+ exportAssets: e
1115
+ });
1116
+ }
1117
+ const v = b(g, "chunks");
1118
+ F(v, { recursive: !0 });
1119
+ const x = ss();
1120
+ for (const z of Object.keys(t?.resources?.components ?? {}).filter(
1121
+ ($) => p.includes($)
1122
+ )) {
1123
+ const $ = t.resources?.components?.[z]?.component;
1124
+ if ($ && $.renderer?.type === "react-component") {
1125
+ const K = $.renderer?.chunks ?? [];
1126
+ if (K?.length > 0)
1127
+ for (const pe of K) {
1128
+ const Ce = b(v, pe), ue = x?.[pe];
1129
+ try {
1130
+ ue && M(ue) && !M(Ce) && ct(ue, Ce);
1131
+ } catch (Ze) {
1132
+ f.error(`copy chunk ${pe} error`, Ze.message);
1133
+ }
1134
+ }
1135
+ }
1136
+ }
1137
+ }
1138
+ return g;
1139
+ }
1140
+ async function qe(t, { importAssets: e, includeResources: s } = {}) {
1141
+ if (!M(t))
1142
+ return null;
1143
+ let o, a = !1;
1144
+ try {
1145
+ G(t).isDirectory() ? o = t : /\.(tgz|gz|tar)$/.test(t) && (a = !0, o = ze(), await bt({ file: t, C: o }));
1146
+ const r = se("**/.blocklet/pages/pages.config.yml", { cwd: o, absolute: !0 }).at(0), n = r && b(L(r), "../../pages"), l = r && b(L(r), "../../components"), p = r && b(L(r), "../../routes");
1147
+ if (!r)
1148
+ return null;
1149
+ const y = B.parse(J(r).toString()), w = (m, d, h) => {
1150
+ let A = b(m, `${d}${h ? `.${h}` : ""}.yml`);
1151
+ return (!M(A) || !G(A).isFile()) && (A = b(m, d, `index${h ? `.${h}` : ""}.yml`), !M(A) || !G(A)) ? null : B.parse(J(A).toString());
1152
+ }, R = (m, d) => {
1153
+ try {
1154
+ const h = se(`*.${d}.yml`, { cwd: m, absolute: !0 })[0];
1155
+ return h ? B.parse(J(h).toString()) : null;
1156
+ } catch (h) {
1157
+ f.error("parse component error", h);
1158
+ }
1159
+ return null;
1160
+ }, I = (m, d) => {
1161
+ let h = b(m, `${d}.yml`);
1162
+ return (!M(h) || !G(h).isFile()) && (h = b(m, d, "index.yml"), !M(h) || !G(h)) ? null : B.parse(J(h).toString());
1163
+ }, u = T(
1164
+ y.pages.map(({ slug: m }) => {
1165
+ const d = T(
1166
+ y.supportedLocales.map(({ locale: P }) => {
1167
+ const i = n ? w(n, re(m), P) : void 0;
1168
+ if (i)
1169
+ return { locale: P, page: i };
1170
+ const S = n ? w(n, m, P) : void 0;
1171
+ return S && { locale: P, page: S };
1172
+ })
1173
+ ), h = d[0]?.page;
1174
+ if (!h)
1175
+ return null;
1176
+ const A = h.sections.map(ut);
1177
+ return {
1178
+ id: h.id || Re(),
1179
+ createdAt: h.createdAt,
1180
+ updatedAt: h.updatedAt,
1181
+ publishedAt: h.publishedAt,
1182
+ isPublic: h.isPublic ?? !0,
1183
+ templateConfig: h.templateConfig,
1184
+ slug: m,
1185
+ sections: Object.fromEntries(A.map((P) => [P.id, P])),
1186
+ sectionIds: A.map((P) => P.id),
1187
+ locales: Object.fromEntries(d.map(({ locale: P, page: i }) => [P, i.meta])),
1188
+ dataSource: h.dataSource ? Object.fromEntries(
1189
+ // 获取 dataSource 中所有 section ID
1190
+ [...new Set(d.flatMap(({ page: P }) => Object.keys(P.dataSource ?? {})))].map((P) => [
1191
+ P,
1192
+ Object.fromEntries(
1193
+ d.map(({ locale: i, page: S }) => {
1194
+ const v = S.dataSource?.[P];
1195
+ return [i, v || {}];
1196
+ })
1197
+ )
1198
+ ])
1199
+ ) : Object.fromEntries(
1200
+ // 获取所有 section ID
1201
+ [...new Set(d.flatMap(({ page: P }) => P.sections.map((i) => i.id)))].map((P) => [
1202
+ P,
1203
+ Object.fromEntries(
1204
+ d.map(({ locale: i, page: S }) => {
1205
+ const v = S.dataSource?.[P];
1206
+ if (v)
1207
+ return [i, v];
1208
+ const x = S.sections.find((z) => z.id === P);
1209
+ return [i, x?.properties || {}];
1210
+ })
1211
+ )
1212
+ ])
1213
+ )
1214
+ };
1215
+ })
1216
+ ), c = T(
1217
+ y?.routes?.map(({ path: m }) => {
1218
+ const d = p ? I(p, re(m)) : void 0;
1219
+ return {
1220
+ ...d,
1221
+ id: d?.id || Re(),
1222
+ createdAt: d?.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1223
+ updatedAt: d?.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
1224
+ publishedAt: (/* @__PURE__ */ new Date(0)).toISOString(),
1225
+ path: d?.path ?? `/${d?.id}`,
1226
+ params: d?.params,
1227
+ handler: d?.handler ?? "Pages Kit",
1228
+ isPublic: d?.isPublic ?? !0,
1229
+ enabledGenerate: d?.enabledGenerate ?? !1,
1230
+ displayTemplateId: d?.displayTemplateId ?? void 0,
1231
+ dataSource: d?.dataSource ?? {}
1232
+ };
1233
+ }) ?? []
1234
+ ), g = l ? T(y.components?.map(({ id: m }) => R(l, m)) ?? []) : [];
1235
+ if (e) {
1236
+ const m = (...d) => {
1237
+ f.info(`[${a ? k(t) : k(b(t, "../../../../"))}] importAssets:`, ...d);
1238
+ };
1239
+ try {
1240
+ m("wait image-bin api ready"), await At({
1241
+ resources: [`${ft(et)}/api/sdk/uploads`],
1242
+ validateStatus: (A) => A >= 200 && A <= 500
1243
+ }), m("image-bin api is ready");
1244
+ const d = {}, h = {};
1245
+ m("start to upload assets"), await Promise.allSettled([
1246
+ $e(g, d, {
1247
+ getFilePath: (A) => l && b(l, A),
1248
+ onFinish: (A) => {
1249
+ m(`upload ${A.length} component assets`);
1250
+ }
1251
+ }),
1252
+ $e(u, h, {
1253
+ getFilePath: (A, P) => {
1254
+ const i = be(u, P.slice(0, 1));
1255
+ return n && b(n, L(i.slug), A);
1256
+ },
1257
+ onFinish: (A) => {
1258
+ m(`upload ${A.length} page assets`);
1259
+ }
1260
+ })
1261
+ ]), m("upload assets done"), Se.clear(), global.gc && global.gc();
1262
+ } catch (d) {
1263
+ m("Error during asset import:", d);
1264
+ }
1265
+ }
1266
+ const O = {};
1267
+ if (s) {
1268
+ const m = r && b(L(r), "../../resources/components"), d = T(
1269
+ y.resources?.components?.map(({ id: h }) => R(m, h)) ?? []
1270
+ );
1271
+ d.length > 0 && (O.components = Object.fromEntries(
1272
+ d.map((h, A) => [h.id, { index: A, component: h }])
1273
+ ));
1274
+ }
1275
+ return {
1276
+ supportedLocales: y.supportedLocales,
1277
+ pageIds: u.map((m) => m.id),
1278
+ components: Object.fromEntries(g.map((m, d) => [m.id, { index: d, data: m }])),
1279
+ pages: Object.fromEntries(u.map((m) => [m.id, m])),
1280
+ config: y.config || {},
1281
+ resources: O,
1282
+ routeIds: c.map((m) => m.id),
1283
+ routes: Object.fromEntries(c.map((m) => [m.id, m])),
1284
+ dataSourceIds: [],
1285
+ dataSources: {}
1286
+ };
1287
+ } finally {
1288
+ a && o && _e(o, { force: !0, recursive: !0 });
1289
+ }
1290
+ }
1291
+ async function Me(t, e, {
1292
+ routes: s,
1293
+ mergeMode: o = "byUpdateTime",
1294
+ deleteRoutes: a = !1,
1295
+ publishMode: r = void 0
1296
+ } = {}) {
1297
+ try {
1298
+ r && tt(r);
1299
+ } catch (I) {
1300
+ f.error("clear preload page cache error", { error: I });
1301
+ }
1302
+ const { pages: n, pageIds: l, routeIds: p, routes: y, supportedLocales: w } = t;
1303
+ if (r === "production") {
1304
+ let I = s ?? [], u = null;
1305
+ for (const c of p ?? []) {
1306
+ const g = y?.[c];
1307
+ if (g?.params && g?.params.length > 0 && g?.paramsOptions && g?.paramsOptions.length > 0) {
1308
+ const O = Ie({
1309
+ basePath: g.path,
1310
+ params: g.params,
1311
+ routeId: g.id,
1312
+ paramsOptions: g.paramsOptions,
1313
+ currentIndex: 0,
1314
+ currentParams: [],
1315
+ currentOptionIds: [],
1316
+ result: []
1317
+ }), m = Object.fromEntries(O.map((d) => [`${c}-${d.paramOptionIds.join("-")}`, d]));
1318
+ u = { ...u || {}, ...m }, s || (I = [...I, ...O.map((d) => `${c}-${d.paramOptionIds.join("-")}`)]);
1319
+ } else s || I.push(c);
1320
+ }
1321
+ f.info("routeIds to be published: ", I);
1322
+ for (const c of I) {
1323
+ let g = c;
1324
+ if (g.includes("-")) {
1325
+ const [d] = g.split("-");
1326
+ g = d;
1327
+ }
1328
+ const O = y?.[g];
1329
+ if (!O) {
1330
+ const d = e.pageIds.indexOf(g);
1331
+ d !== -1 && a && (e.pageIds.splice(d, 1), delete e.pages[g]);
1332
+ for (const h of e.pageIds)
1333
+ h.includes(`${g}-`) && (e.pageIds.splice(e.pageIds.indexOf(h), 1), delete e.pages[h]);
1334
+ f.info("delete main route page", g);
1335
+ continue;
1336
+ }
1337
+ if (c.includes("-") && !u?.[c]) {
1338
+ const d = e.pageIds.indexOf(c);
1339
+ d !== -1 && a && (e.pageIds.splice(d, 1), delete e.pages[c]), f.info("delete page", c);
1340
+ continue;
1341
+ }
1342
+ if (!O.displayTemplateId) {
1343
+ f.info("no display template", c);
1344
+ continue;
1345
+ }
1346
+ const m = n[O.displayTemplateId];
1347
+ if (!m) {
1348
+ f.info("no template page", c);
1349
+ continue;
1350
+ }
1351
+ if (e.pageIds.includes(c)) {
1352
+ if (f.info("has need update page", c), o === "replace")
1353
+ e.pages[c] = fe({
1354
+ page: m,
1355
+ route: O,
1356
+ state: t,
1357
+ routeId: c,
1358
+ routePathInfo: u?.[c]
1359
+ }), f.info("replace page", c);
1360
+ else if (o === "byUpdateTime") {
1361
+ const d = e.pages[O.id];
1362
+ (!d || O.updatedAt && O.updatedAt > d.updatedAt) && (e.pages[c] = fe({
1363
+ page: m,
1364
+ route: O,
1365
+ state: t,
1366
+ routeId: c,
1367
+ routePathInfo: u?.[c]
1368
+ }), f.info("replace page by update time", c));
1369
+ }
1370
+ } else
1371
+ e.pageIds.push(c), e.pages[c] = fe({
1372
+ page: m,
1373
+ route: O,
1374
+ state: t,
1375
+ routeId: c,
1376
+ routePathInfo: u?.[c]
1377
+ }), f.info("add page", c);
1378
+ }
1379
+ if (a && !s)
1380
+ for (const c of e.pageIds)
1381
+ I?.includes(c) || (delete e.pages[c], f.info("delete page", c)), e.pageIds = [...e.pageIds].filter((g) => I?.includes(g));
1382
+ } else {
1383
+ for (const I of l) {
1384
+ const u = n[I];
1385
+ if (u)
1386
+ if (e.pageIds.includes(u.id)) {
1387
+ if (o === "replace")
1388
+ e.pages[u.id] = u;
1389
+ else if (o === "byUpdateTime") {
1390
+ const c = e.pages[u.id];
1391
+ (!c || u.updatedAt && u.updatedAt > c.updatedAt) && (e.pages[u.id] = u);
1392
+ }
1393
+ } else
1394
+ e.pageIds.push(u.id), e.pages[u.id] = u;
1395
+ }
1396
+ for (const I of p) {
1397
+ const u = y[I];
1398
+ if (u)
1399
+ if (e.routeIds.includes(u.id)) {
1400
+ if (o === "replace")
1401
+ e.routes[u.id] = u;
1402
+ else if (o === "byUpdateTime") {
1403
+ const c = e.routes[u.id];
1404
+ (!c || u.updatedAt && u.updatedAt > c.updatedAt) && (e.routes[u.id] = u);
1405
+ }
1406
+ } else
1407
+ e.routeIds.push(u.id), e.routes[u.id] = u;
1408
+ }
1409
+ }
1410
+ if (e.supportedLocales.splice(0, e.supportedLocales.length), e.supportedLocales.push(...Ee(w)), a)
1411
+ for (const I of Object.keys(e.components))
1412
+ delete e.components[I];
1413
+ let R = JSON.parse(JSON.stringify(t.components));
1414
+ R = Object.fromEntries(
1415
+ await Promise.all(
1416
+ Object.entries(R).map(async ([I, u]) => {
1417
+ const c = await He(u?.data);
1418
+ return [
1419
+ I,
1420
+ {
1421
+ ...u,
1422
+ data: c
1423
+ }
1424
+ ];
1425
+ })
1426
+ )
1427
+ ), Object.assign(e.components, R), Object.assign(e.config, JSON.parse(JSON.stringify(t.config))), we(t.resources.components) || (e.resources.components = JSON.parse(JSON.stringify(t.resources.components || {})));
1428
+ }
1429
+ const He = st(
1430
+ async (t) => {
1431
+ if (!we(t?.properties))
1432
+ return t;
1433
+ if (t?.renderer?.type === "react-component") {
1434
+ const { script: e, PROPERTIES_SCHEMA: s } = t?.renderer || {};
1435
+ if (s || e && e.includes("PROPERTIES_SCHEMA"))
1436
+ try {
1437
+ const o = await ot(
1438
+ e ?? "",
1439
+ "PROPERTIES_SCHEMA",
1440
+ t.id,
1441
+ s
1442
+ );
1443
+ o && o.length > 0 && t && (t.properties = {}, o.forEach((a, r) => {
1444
+ t?.properties && (t.properties[a.id] = {
1445
+ index: r,
1446
+ data: a
1447
+ });
1448
+ }));
1449
+ } catch (o) {
1450
+ f.error("getPropertiesFromCode error", { componentId: t.id, name: t.name }, { error: o });
1451
+ }
1452
+ }
1453
+ return t;
1454
+ },
1455
+ {
1456
+ subdir: "getPropertiesFromCode"
1457
+ }
1458
+ );
1459
+ let ne, Q, ie, ce;
1460
+ const Je = () => mt({
1461
+ types: [
1462
+ { did: Ve, type: ke },
1463
+ { did: Lt, type: ke }
1464
+ ]
1465
+ }), ss = () => {
1466
+ const t = Je(), e = {};
1467
+ return t.forEach((s) => {
1468
+ const o = se("**/.blocklet/pages/pages.config.yml", { cwd: s.path, absolute: !0 }).at(0), a = o && b(L(o), "../../chunks");
1469
+ if (a && M(a)) {
1470
+ const r = lt(a);
1471
+ for (const n of r)
1472
+ e[n] = b(a, n);
1473
+ }
1474
+ }), e;
1475
+ };
1476
+ function Ye() {
1477
+ return ne = (async () => {
1478
+ const t = Je();
1479
+ Q = (await Promise.all(
1480
+ t.map(async (s) => {
1481
+ const o = s.path ? await qe(s.path, { importAssets: !1 }) : void 0;
1482
+ return o ? { blockletId: s.did, state: o, blockletTitle: s.title } : void 0;
1483
+ })
1484
+ )).filter((s) => !!s), ie = Q.reduce(
1485
+ (s, o) => Object.assign(
1486
+ s,
1487
+ Object.fromEntries(
1488
+ Object.values(o.state.pages).map((a) => a ? [a?.id, { page: a, blockletId: o.blockletId }] : [])
1489
+ )
1490
+ ),
1491
+ {}
1492
+ );
1493
+ const e = Q.reduce(
1494
+ (s, o) => Object.assign(
1495
+ s,
1496
+ Object.fromEntries(
1497
+ Object.values(o.state.components).map((a) => [a.data.id, { blockletId: o.blockletId, component: a.data }])
1498
+ )
1499
+ ),
1500
+ {}
1501
+ );
1502
+ ce = Object.fromEntries(
1503
+ await Promise.all(
1504
+ Object.entries(e).map(async ([s, o]) => {
1505
+ const a = await He(o.component);
1506
+ return [
1507
+ s,
1508
+ {
1509
+ ...o,
1510
+ component: a
1511
+ }
1512
+ ];
1513
+ })
1514
+ )
1515
+ );
1516
+ })(), ne;
1517
+ }
1518
+ function os(t) {
1519
+ const e = Fe(
1520
+ async () => {
1521
+ await Ye().catch((s) => {
1522
+ f.error("load resource states error", { error: s });
1523
+ }), await t?.({
1524
+ states: Q,
1525
+ pages: ie,
1526
+ components: ce
1527
+ });
1528
+ },
1529
+ 3e3,
1530
+ // 3s
1531
+ { leading: !1, trailing: !0 }
1532
+ );
1533
+ return e(), E.events.on(E.Events.componentAdded, e), E.events.on(E.Events.componentRemoved, e), E.events.on(E.Events.componentStarted, e), E.events.on(E.Events.componentStopped, e), E.events.on(E.Events.componentUpdated, e), E.events.on(he, e), () => {
1534
+ E.events.off(E.Events.componentAdded, e), E.events.off(E.Events.componentRemoved, e), E.events.off(E.Events.componentStarted, e), E.events.off(E.Events.componentStopped, e), E.events.off(E.Events.componentUpdated, e), E.events.off(he, e);
1535
+ };
1536
+ }
1537
+ const We = Symbol.for("GLOBAL_RESOURCE_STATES_LISTENER_KEY"), Xe = Symbol.for("GLOBAL_ENV_UPDATE_LISTENER_KEY"), le = globalThis;
1538
+ le[We]?.();
1539
+ le[We] = os(async ({ pages: t, components: e }) => {
1540
+ const s = await C.getProjectIds();
1541
+ f.info(`start update resource states projects(${s.length})`, s), await Promise.race([
1542
+ new Promise((o) => {
1543
+ setTimeout(() => {
1544
+ o({});
1545
+ }, 30 * 1e3);
1546
+ }),
1547
+ Promise.all(
1548
+ s.map(async (o) => {
1549
+ Qe({
1550
+ projectId: o,
1551
+ pages: t,
1552
+ components: e
1553
+ });
1554
+ })
1555
+ )
1556
+ ]).catch((o) => {
1557
+ f.error("update resource states failed:", o);
1558
+ });
1559
+ });
1560
+ le[Xe]?.();
1561
+ le[Xe] = () => {
1562
+ const t = () => {
1563
+ C.pageUrlMapCache.clear(), f.info("[Cache CLEAR ALL] clear all page url map cache by env update");
1564
+ };
1565
+ return E.events.on(E.Events.envUpdate, t), () => {
1566
+ E.events.off(E.Events.envUpdate, t);
1567
+ };
1568
+ };
1569
+ C.startPeriodicCheck();
1570
+ process.on("beforeExit", () => {
1571
+ C.stopPeriodicCheck();
1572
+ });
1573
+ process.on("SIGINT", () => {
1574
+ C.stopPeriodicCheck(), process.exit(0);
1575
+ });
1576
+ process.on("SIGTERM", () => {
1577
+ C.stopPeriodicCheck(), process.exit(0);
1578
+ });
1579
+ async function Qe({
1580
+ projectId: t,
1581
+ pages: e,
1582
+ components: s
1583
+ }) {
1584
+ const o = C.sharedInstances[t];
1585
+ if (!o) {
1586
+ f.info(`projectId: ${t} not found in sharedInstances`);
1587
+ return;
1588
+ }
1589
+ if (o.syncedStore.resources.pages = e, (await U.findByPk(t))?.useAllResources)
1590
+ o.syncedStore.resources.components = s;
1591
+ else {
1592
+ const n = (await Pe.findAll({ where: { projectId: t } })).map((p) => p.componentId), l = Object.fromEntries(
1593
+ Object.entries(s || {}).filter(([p]) => n.includes(p))
1594
+ );
1595
+ o.syncedStore.resources.components = l;
1596
+ }
1597
+ f.info(`update [${t}] resource states:`, {
1598
+ pages: Object.keys(o.syncedStore.resources.pages || {}).length,
1599
+ components: Object.keys(o.syncedStore.resources.components || {}).length
1600
+ });
1601
+ }
1602
+ async function as(t) {
1603
+ return Qe({
1604
+ projectId: t,
1605
+ pages: ie,
1606
+ components: ce
1607
+ });
1608
+ }
1609
+ async function _s() {
1610
+ f.info("trigger reload all project resource"), E.events.emit(he);
1611
+ }
1612
+ async function Fs({
1613
+ ensureLoaded: t = !0
1614
+ } = {}) {
1615
+ return t && (ne ??= Ye(), await ne), { states: Q, pages: ie, components: ce };
1616
+ }
1617
+ export {
1618
+ Ve as C,
1619
+ U as P,
1620
+ ke as R,
1621
+ C as S,
1622
+ H as a,
1623
+ Ms as b,
1624
+ Ns as c,
1625
+ Xt as d,
1626
+ Zt as e,
1627
+ es as f,
1628
+ Fs as g,
1629
+ qe as h,
1630
+ os as i,
1631
+ _s as j,
1632
+ Me as m,
1633
+ ts as t,
1634
+ as as u
1635
+ };