@blocklet/pages-kit-inner-components 0.6.7 → 0.6.8

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