@blocklet/pages-kit-inner-components 0.7.3 → 0.7.5

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