@lark-apaas/fullstack-nestjs-core 1.1.33-alpha.5 → 1.1.33-alpha.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -20638,7 +20638,7 @@ var require_view = __commonJS({
20638
20638
  var dirname2 = path2.dirname;
20639
20639
  var basename = path2.basename;
20640
20640
  var extname2 = path2.extname;
20641
- var join3 = path2.join;
20641
+ var join4 = path2.join;
20642
20642
  var resolve2 = path2.resolve;
20643
20643
  module2.exports = View;
20644
20644
  function View(name, options) {
@@ -20687,12 +20687,12 @@ var require_view = __commonJS({
20687
20687
  }, "render");
20688
20688
  View.prototype.resolve = /* @__PURE__ */ __name(function resolve3(dir, file) {
20689
20689
  var ext = this.ext;
20690
- var path3 = join3(dir, file);
20690
+ var path3 = join4(dir, file);
20691
20691
  var stat = tryStat(path3);
20692
20692
  if (stat && stat.isFile()) {
20693
20693
  return path3;
20694
20694
  }
20695
- path3 = join3(dir, basename(file, ext), "index" + ext);
20695
+ path3 = join4(dir, basename(file, ext), "index" + ext);
20696
20696
  stat = tryStat(path3);
20697
20697
  if (stat && stat.isFile()) {
20698
20698
  return path3;
@@ -21814,7 +21814,7 @@ var require_send = __commonJS({
21814
21814
  var Stream = require("stream");
21815
21815
  var util = require("util");
21816
21816
  var extname2 = path2.extname;
21817
- var join3 = path2.join;
21817
+ var join4 = path2.join;
21818
21818
  var normalize2 = path2.normalize;
21819
21819
  var resolve2 = path2.resolve;
21820
21820
  var sep = path2.sep;
@@ -22031,7 +22031,7 @@ var require_send = __commonJS({
22031
22031
  return res;
22032
22032
  }
22033
22033
  parts = path3.split(sep);
22034
- path3 = normalize2(join3(root, path3));
22034
+ path3 = normalize2(join4(root, path3));
22035
22035
  } else {
22036
22036
  if (UP_PATH_REGEXP.test(path3)) {
22037
22037
  debug('malicious path "%s"', path3);
@@ -22169,7 +22169,7 @@ var require_send = __commonJS({
22169
22169
  if (err) return self.onStatError(err);
22170
22170
  return self.error(404);
22171
22171
  }
22172
- var p = join3(path3, self._index[i]);
22172
+ var p = join4(path3, self._index[i]);
22173
22173
  debug('stat "%s"', p);
22174
22174
  fs3.stat(p, function(err2, stat) {
22175
22175
  if (err2) return next(err2);
@@ -34424,7 +34424,7 @@ __export(index_exports, {
34424
34424
  module.exports = __toCommonJS(index_exports);
34425
34425
 
34426
34426
  // src/modules/platform/module.ts
34427
- var import_common15 = require("@nestjs/common");
34427
+ var import_common16 = require("@nestjs/common");
34428
34428
  var import_core2 = require("@nestjs/core");
34429
34429
  var import_nestjs_common6 = require("@lark-apaas/nestjs-common");
34430
34430
  var import_config2 = require("@nestjs/config");
@@ -35831,6 +35831,7 @@ var import_swagger2 = require("@nestjs/swagger");
35831
35831
  // src/modules/html-hot-update/html-hot-update.service.ts
35832
35832
  var import_common12 = require("@nestjs/common");
35833
35833
  var import_node_fs = require("fs");
35834
+ var import_node_fs2 = require("fs");
35834
35835
  var import_node_path = require("path");
35835
35836
  var import_nestjs_common5 = require("@lark-apaas/nestjs-common");
35836
35837
  function _ts_decorate12(decorators, target, key, desc) {
@@ -35877,6 +35878,7 @@ var Mutex = class Mutex2 {
35877
35878
  }
35878
35879
  }
35879
35880
  };
35881
+ var HOT_UPDATE_HTML_DIR = "/tmp/html-hot-update";
35880
35882
  var HtmlHotUpdateService = class _HtmlHotUpdateService {
35881
35883
  static {
35882
35884
  __name(this, "HtmlHotUpdateService");
@@ -35885,8 +35887,10 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35885
35887
  logger = new import_common12.Logger(_HtmlHotUpdateService.name);
35886
35888
  /** 文件锁:冷启动更新和 innerapi 主动更新共用 */
35887
35889
  fileLock = new Mutex();
35888
- /** 本地 HTML 文件目录(dist/dist/client,与 build.sh [4/5] 对齐) */
35889
- localHtmlDir = (0, import_node_path.join)(process.cwd(), "dist", "client");
35890
+ /** 热更新 HTML 目录(可写) */
35891
+ hotUpdateDir = HOT_UPDATE_HTML_DIR;
35892
+ /** 原始 HTML 产物目录(只读,部署时打包的) */
35893
+ originalHtmlDir = (0, import_node_path.join)(process.cwd(), "dist", "client");
35890
35894
  constructor(httpClient) {
35891
35895
  this.httpClient = httpClient;
35892
35896
  }
@@ -35899,7 +35903,7 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35899
35903
  */
35900
35904
  async onModuleInit() {
35901
35905
  const appID = this.getAppID();
35902
- this.logger.log(`[DEBUG] onModuleInit env: CLIENT_BASE_PATH=${process.env.CLIENT_BASE_PATH || "(empty)"}, NODE_ENV=${process.env.NODE_ENV || "(empty)"}, cwd=${process.cwd()}, localHtmlDir=${this.localHtmlDir}, appID=${appID || "(empty)"}`);
35906
+ this.logger.log(`[DEBUG] onModuleInit env: CLIENT_BASE_PATH=${process.env.CLIENT_BASE_PATH || "(empty)"}, NODE_ENV=${process.env.NODE_ENV || "(empty)"}, cwd=${process.cwd()}, hotUpdateDir=${this.hotUpdateDir}, originalHtmlDir=${this.originalHtmlDir}, appID=${appID || "(empty)"}`);
35903
35907
  if (!appID) {
35904
35908
  this.logger.warn("Skip HTML hot update on startup: appID not found");
35905
35909
  return;
@@ -35919,6 +35923,36 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35919
35923
  }
35920
35924
  }
35921
35925
  /**
35926
+ * 解析 HTML 文件路径(带 fallback)
35927
+ *
35928
+ * 优先返回热更新目录中的文件,不存在则 fallback 到原始产物目录。
35929
+ * 供 NestJS 视图渲染使用。
35930
+ *
35931
+ * @example
35932
+ * const htmlPath = htmlHotUpdateService.resolveHtmlPath('index.html');
35933
+ * // 热更新存在: /tmp/html-hot-update/index.html
35934
+ * // 热更新不存在: /opt/bytefaas/dist/client/index.html(原始产物)
35935
+ */
35936
+ resolveHtmlPath(fileName) {
35937
+ const hotPath = (0, import_node_path.join)(this.hotUpdateDir, fileName);
35938
+ if ((0, import_node_fs2.existsSync)(hotPath)) {
35939
+ return hotPath;
35940
+ }
35941
+ return (0, import_node_path.join)(this.originalHtmlDir, fileName);
35942
+ }
35943
+ /**
35944
+ * 获取 HTML views 目录列表(热更新目录优先)
35945
+ *
35946
+ * 供 NestJS setBaseViewsDir 使用:
35947
+ * app.setBaseViewsDir(htmlHotUpdateService.getViewsDirs());
35948
+ */
35949
+ getViewsDirs() {
35950
+ return [
35951
+ this.hotUpdateDir,
35952
+ this.originalHtmlDir
35953
+ ];
35954
+ }
35955
+ /**
35922
35956
  * 从远端获取最新 HTML 文件并更新本地
35923
35957
  *
35924
35958
  * 调用方:
@@ -35934,7 +35968,7 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35934
35968
  return this.writeHtmlFiles(fileMap);
35935
35969
  }
35936
35970
  /**
35937
- * 将文件内容写入本地 HTML 目录(带文件锁)
35971
+ * 将文件内容写入热更新目录(带文件锁)
35938
35972
  */
35939
35973
  async writeHtmlFiles(fileMap) {
35940
35974
  const result = {
@@ -35945,12 +35979,12 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35945
35979
  if (entries.length === 0) {
35946
35980
  return result;
35947
35981
  }
35948
- this.logger.log(`[DEBUG] writeHtmlFiles: acquiring lock, ${entries.length} files to write, dir=${this.localHtmlDir}`);
35982
+ this.logger.log(`[DEBUG] writeHtmlFiles: acquiring lock, ${entries.length} files to write, dir=${this.hotUpdateDir}`);
35949
35983
  await this.fileLock.acquire();
35950
35984
  try {
35951
35985
  for (const [filePath, content] of entries) {
35952
35986
  try {
35953
- const localPath = (0, import_node_path.join)(this.localHtmlDir, filePath);
35987
+ const localPath = (0, import_node_path.join)(this.hotUpdateDir, filePath);
35954
35988
  await import_node_fs.promises.mkdir((0, import_node_path.dirname)(localPath), {
35955
35989
  recursive: true
35956
35990
  });
@@ -36164,7 +36198,10 @@ HtmlHotUpdateModule = _ts_decorate14([
36164
36198
  })
36165
36199
  ], HtmlHotUpdateModule);
36166
36200
 
36167
- // src/modules/platform/module.ts
36201
+ // src/middlewares/html-hot-update-view/index.ts
36202
+ var import_common15 = require("@nestjs/common");
36203
+ var import_node_fs3 = require("fs");
36204
+ var import_node_path2 = require("path");
36168
36205
  function _ts_decorate15(decorators, target, key, desc) {
36169
36206
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
36170
36207
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -36172,6 +36209,40 @@ function _ts_decorate15(decorators, target, key, desc) {
36172
36209
  return c > 3 && r && Object.defineProperty(target, key, r), r;
36173
36210
  }
36174
36211
  __name(_ts_decorate15, "_ts_decorate");
36212
+ var HOT_UPDATE_DIR = "/tmp/html-hot-update";
36213
+ var HtmlHotUpdateViewMiddleware = class _HtmlHotUpdateViewMiddleware {
36214
+ static {
36215
+ __name(this, "HtmlHotUpdateViewMiddleware");
36216
+ }
36217
+ logger = new import_common15.Logger(_HtmlHotUpdateViewMiddleware.name);
36218
+ use(req, res, next) {
36219
+ if (process.env.NODE_ENV !== "production") {
36220
+ return next();
36221
+ }
36222
+ const originalRender = res.render.bind(res);
36223
+ res.render = (view, options, callback) => {
36224
+ const hotPath = (0, import_node_path2.join)(HOT_UPDATE_DIR, `${view}.html`);
36225
+ if ((0, import_node_fs3.existsSync)(hotPath)) {
36226
+ this.logger.log(`[DEBUG] render hot-updated HTML: ${hotPath}`);
36227
+ return originalRender(hotPath, options, callback);
36228
+ }
36229
+ return originalRender(view, options, callback);
36230
+ };
36231
+ next();
36232
+ }
36233
+ };
36234
+ HtmlHotUpdateViewMiddleware = _ts_decorate15([
36235
+ (0, import_common15.Injectable)()
36236
+ ], HtmlHotUpdateViewMiddleware);
36237
+
36238
+ // src/modules/platform/module.ts
36239
+ function _ts_decorate16(decorators, target, key, desc) {
36240
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
36241
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
36242
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
36243
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
36244
+ }
36245
+ __name(_ts_decorate16, "_ts_decorate");
36175
36246
  var PLATFORM_MODULE_OPTIONS = /* @__PURE__ */ Symbol("PLATFORM_MODULE_OPTIONS");
36176
36247
  var PlatformModule = class _PlatformModule {
36177
36248
  static {
@@ -36256,7 +36327,7 @@ var PlatformModule = class _PlatformModule {
36256
36327
  },
36257
36328
  {
36258
36329
  provide: import_core2.APP_PIPE,
36259
- useValue: new import_common15.ValidationPipe({
36330
+ useValue: new import_common16.ValidationPipe({
36260
36331
  transform: true,
36261
36332
  transformOptions: {
36262
36333
  enableImplicitConversion: true
@@ -36316,7 +36387,7 @@ var PlatformModule = class _PlatformModule {
36316
36387
  consumer.apply(UserContextMiddleware, RequestContextMiddleware, import_nestjs_logger2.LoggerContextMiddleware, import_nestjs_observable.ObservableTraceMiddleware, ...DISABLE_DATAPASS ? [] : [
36317
36388
  import_nestjs_datapaas.SqlExecutionContextMiddleware
36318
36389
  ]).forRoutes("/*");
36319
- consumer.apply(CsrfTokenMiddleware, ViewContextMiddleware).exclude("/api/(.*)", "/static/(.*)").forRoutes("*");
36390
+ consumer.apply(CsrfTokenMiddleware, ViewContextMiddleware, HtmlHotUpdateViewMiddleware).exclude("/api/(.*)", "/static/(.*)").forRoutes("*");
36320
36391
  if (options.enableCsrf !== false) {
36321
36392
  const csrfRoutes = options.csrfRoutes || "/api/*";
36322
36393
  if (Array.isArray(csrfRoutes)) {
@@ -36329,9 +36400,9 @@ var PlatformModule = class _PlatformModule {
36329
36400
  }
36330
36401
  }
36331
36402
  };
36332
- PlatformModule = _ts_decorate15([
36333
- (0, import_common15.Global)(),
36334
- (0, import_common15.Module)({})
36403
+ PlatformModule = _ts_decorate16([
36404
+ (0, import_common16.Global)(),
36405
+ (0, import_common16.Module)({})
36335
36406
  ], PlatformModule);
36336
36407
 
36337
36408
  // src/setup.ts
package/dist/index.d.cts CHANGED
@@ -150,8 +150,10 @@ declare class HtmlHotUpdateService implements OnModuleInit {
150
150
  private readonly logger;
151
151
  /** 文件锁:冷启动更新和 innerapi 主动更新共用 */
152
152
  private readonly fileLock;
153
- /** 本地 HTML 文件目录(dist/dist/client,与 build.sh [4/5] 对齐) */
154
- private readonly localHtmlDir;
153
+ /** 热更新 HTML 目录(可写) */
154
+ private readonly hotUpdateDir;
155
+ /** 原始 HTML 产物目录(只读,部署时打包的) */
156
+ private readonly originalHtmlDir;
155
157
  constructor(httpClient: PlatformHttpClient);
156
158
  /**
157
159
  * 任务一:冷启动时尝试更新 HTML 文件列表
@@ -161,6 +163,25 @@ declare class HtmlHotUpdateService implements OnModuleInit {
161
163
  * - 超时 3s,避免拉长冷启动耗时
162
164
  */
163
165
  onModuleInit(): Promise<void>;
166
+ /**
167
+ * 解析 HTML 文件路径(带 fallback)
168
+ *
169
+ * 优先返回热更新目录中的文件,不存在则 fallback 到原始产物目录。
170
+ * 供 NestJS 视图渲染使用。
171
+ *
172
+ * @example
173
+ * const htmlPath = htmlHotUpdateService.resolveHtmlPath('index.html');
174
+ * // 热更新存在: /tmp/html-hot-update/index.html
175
+ * // 热更新不存在: /opt/bytefaas/dist/client/index.html(原始产物)
176
+ */
177
+ resolveHtmlPath(fileName: string): string;
178
+ /**
179
+ * 获取 HTML views 目录列表(热更新目录优先)
180
+ *
181
+ * 供 NestJS setBaseViewsDir 使用:
182
+ * app.setBaseViewsDir(htmlHotUpdateService.getViewsDirs());
183
+ */
184
+ getViewsDirs(): string[];
164
185
  /**
165
186
  * 从远端获取最新 HTML 文件并更新本地
166
187
  *
@@ -170,7 +191,7 @@ declare class HtmlHotUpdateService implements OnModuleInit {
170
191
  */
171
192
  updateFromRemote(appID: string, commitID?: string): Promise<HtmlHotUpdateResult>;
172
193
  /**
173
- * 将文件内容写入本地 HTML 目录(带文件锁)
194
+ * 将文件内容写入热更新目录(带文件锁)
174
195
  */
175
196
  writeHtmlFiles(fileMap: Record<string, string>): Promise<HtmlHotUpdateResult>;
176
197
  /**
package/dist/index.d.ts CHANGED
@@ -150,8 +150,10 @@ declare class HtmlHotUpdateService implements OnModuleInit {
150
150
  private readonly logger;
151
151
  /** 文件锁:冷启动更新和 innerapi 主动更新共用 */
152
152
  private readonly fileLock;
153
- /** 本地 HTML 文件目录(dist/dist/client,与 build.sh [4/5] 对齐) */
154
- private readonly localHtmlDir;
153
+ /** 热更新 HTML 目录(可写) */
154
+ private readonly hotUpdateDir;
155
+ /** 原始 HTML 产物目录(只读,部署时打包的) */
156
+ private readonly originalHtmlDir;
155
157
  constructor(httpClient: PlatformHttpClient);
156
158
  /**
157
159
  * 任务一:冷启动时尝试更新 HTML 文件列表
@@ -161,6 +163,25 @@ declare class HtmlHotUpdateService implements OnModuleInit {
161
163
  * - 超时 3s,避免拉长冷启动耗时
162
164
  */
163
165
  onModuleInit(): Promise<void>;
166
+ /**
167
+ * 解析 HTML 文件路径(带 fallback)
168
+ *
169
+ * 优先返回热更新目录中的文件,不存在则 fallback 到原始产物目录。
170
+ * 供 NestJS 视图渲染使用。
171
+ *
172
+ * @example
173
+ * const htmlPath = htmlHotUpdateService.resolveHtmlPath('index.html');
174
+ * // 热更新存在: /tmp/html-hot-update/index.html
175
+ * // 热更新不存在: /opt/bytefaas/dist/client/index.html(原始产物)
176
+ */
177
+ resolveHtmlPath(fileName: string): string;
178
+ /**
179
+ * 获取 HTML views 目录列表(热更新目录优先)
180
+ *
181
+ * 供 NestJS setBaseViewsDir 使用:
182
+ * app.setBaseViewsDir(htmlHotUpdateService.getViewsDirs());
183
+ */
184
+ getViewsDirs(): string[];
164
185
  /**
165
186
  * 从远端获取最新 HTML 文件并更新本地
166
187
  *
@@ -170,7 +191,7 @@ declare class HtmlHotUpdateService implements OnModuleInit {
170
191
  */
171
192
  updateFromRemote(appID: string, commitID?: string): Promise<HtmlHotUpdateResult>;
172
193
  /**
173
- * 将文件内容写入本地 HTML 目录(带文件锁)
194
+ * 将文件内容写入热更新目录(带文件锁)
174
195
  */
175
196
  writeHtmlFiles(fileMap: Record<string, string>): Promise<HtmlHotUpdateResult>;
176
197
  /**
package/dist/index.js CHANGED
@@ -20637,7 +20637,7 @@ var require_view = __commonJS({
20637
20637
  var dirname2 = path2.dirname;
20638
20638
  var basename = path2.basename;
20639
20639
  var extname2 = path2.extname;
20640
- var join3 = path2.join;
20640
+ var join4 = path2.join;
20641
20641
  var resolve2 = path2.resolve;
20642
20642
  module.exports = View;
20643
20643
  function View(name, options) {
@@ -20686,12 +20686,12 @@ var require_view = __commonJS({
20686
20686
  }, "render");
20687
20687
  View.prototype.resolve = /* @__PURE__ */ __name(function resolve3(dir, file) {
20688
20688
  var ext = this.ext;
20689
- var path3 = join3(dir, file);
20689
+ var path3 = join4(dir, file);
20690
20690
  var stat = tryStat(path3);
20691
20691
  if (stat && stat.isFile()) {
20692
20692
  return path3;
20693
20693
  }
20694
- path3 = join3(dir, basename(file, ext), "index" + ext);
20694
+ path3 = join4(dir, basename(file, ext), "index" + ext);
20695
20695
  stat = tryStat(path3);
20696
20696
  if (stat && stat.isFile()) {
20697
20697
  return path3;
@@ -21813,7 +21813,7 @@ var require_send = __commonJS({
21813
21813
  var Stream = __require("stream");
21814
21814
  var util = __require("util");
21815
21815
  var extname2 = path2.extname;
21816
- var join3 = path2.join;
21816
+ var join4 = path2.join;
21817
21817
  var normalize2 = path2.normalize;
21818
21818
  var resolve2 = path2.resolve;
21819
21819
  var sep = path2.sep;
@@ -22030,7 +22030,7 @@ var require_send = __commonJS({
22030
22030
  return res;
22031
22031
  }
22032
22032
  parts = path3.split(sep);
22033
- path3 = normalize2(join3(root, path3));
22033
+ path3 = normalize2(join4(root, path3));
22034
22034
  } else {
22035
22035
  if (UP_PATH_REGEXP.test(path3)) {
22036
22036
  debug('malicious path "%s"', path3);
@@ -22168,7 +22168,7 @@ var require_send = __commonJS({
22168
22168
  if (err) return self.onStatError(err);
22169
22169
  return self.error(404);
22170
22170
  }
22171
- var p = join3(path3, self._index[i]);
22171
+ var p = join4(path3, self._index[i]);
22172
22172
  debug('stat "%s"', p);
22173
22173
  fs3.stat(p, function(err2, stat) {
22174
22174
  if (err2) return next(err2);
@@ -35808,6 +35808,7 @@ import { ApiExcludeController as ApiExcludeController2 } from "@nestjs/swagger";
35808
35808
  // src/modules/html-hot-update/html-hot-update.service.ts
35809
35809
  import { Injectable as Injectable10, Logger as Logger5, Inject as Inject3 } from "@nestjs/common";
35810
35810
  import { promises as fs2 } from "fs";
35811
+ import { existsSync as existsSync2 } from "fs";
35811
35812
  import { join as join2, dirname } from "path";
35812
35813
  import { PLATFORM_HTTP_CLIENT as PLATFORM_HTTP_CLIENT3 } from "@lark-apaas/nestjs-common";
35813
35814
  function _ts_decorate12(decorators, target, key, desc) {
@@ -35854,6 +35855,7 @@ var Mutex = class Mutex2 {
35854
35855
  }
35855
35856
  }
35856
35857
  };
35858
+ var HOT_UPDATE_HTML_DIR = "/tmp/html-hot-update";
35857
35859
  var HtmlHotUpdateService = class _HtmlHotUpdateService {
35858
35860
  static {
35859
35861
  __name(this, "HtmlHotUpdateService");
@@ -35862,8 +35864,10 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35862
35864
  logger = new Logger5(_HtmlHotUpdateService.name);
35863
35865
  /** 文件锁:冷启动更新和 innerapi 主动更新共用 */
35864
35866
  fileLock = new Mutex();
35865
- /** 本地 HTML 文件目录(dist/dist/client,与 build.sh [4/5] 对齐) */
35866
- localHtmlDir = join2(process.cwd(), "dist", "client");
35867
+ /** 热更新 HTML 目录(可写) */
35868
+ hotUpdateDir = HOT_UPDATE_HTML_DIR;
35869
+ /** 原始 HTML 产物目录(只读,部署时打包的) */
35870
+ originalHtmlDir = join2(process.cwd(), "dist", "client");
35867
35871
  constructor(httpClient) {
35868
35872
  this.httpClient = httpClient;
35869
35873
  }
@@ -35876,7 +35880,7 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35876
35880
  */
35877
35881
  async onModuleInit() {
35878
35882
  const appID = this.getAppID();
35879
- this.logger.log(`[DEBUG] onModuleInit env: CLIENT_BASE_PATH=${process.env.CLIENT_BASE_PATH || "(empty)"}, NODE_ENV=${process.env.NODE_ENV || "(empty)"}, cwd=${process.cwd()}, localHtmlDir=${this.localHtmlDir}, appID=${appID || "(empty)"}`);
35883
+ this.logger.log(`[DEBUG] onModuleInit env: CLIENT_BASE_PATH=${process.env.CLIENT_BASE_PATH || "(empty)"}, NODE_ENV=${process.env.NODE_ENV || "(empty)"}, cwd=${process.cwd()}, hotUpdateDir=${this.hotUpdateDir}, originalHtmlDir=${this.originalHtmlDir}, appID=${appID || "(empty)"}`);
35880
35884
  if (!appID) {
35881
35885
  this.logger.warn("Skip HTML hot update on startup: appID not found");
35882
35886
  return;
@@ -35896,6 +35900,36 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35896
35900
  }
35897
35901
  }
35898
35902
  /**
35903
+ * 解析 HTML 文件路径(带 fallback)
35904
+ *
35905
+ * 优先返回热更新目录中的文件,不存在则 fallback 到原始产物目录。
35906
+ * 供 NestJS 视图渲染使用。
35907
+ *
35908
+ * @example
35909
+ * const htmlPath = htmlHotUpdateService.resolveHtmlPath('index.html');
35910
+ * // 热更新存在: /tmp/html-hot-update/index.html
35911
+ * // 热更新不存在: /opt/bytefaas/dist/client/index.html(原始产物)
35912
+ */
35913
+ resolveHtmlPath(fileName) {
35914
+ const hotPath = join2(this.hotUpdateDir, fileName);
35915
+ if (existsSync2(hotPath)) {
35916
+ return hotPath;
35917
+ }
35918
+ return join2(this.originalHtmlDir, fileName);
35919
+ }
35920
+ /**
35921
+ * 获取 HTML views 目录列表(热更新目录优先)
35922
+ *
35923
+ * 供 NestJS setBaseViewsDir 使用:
35924
+ * app.setBaseViewsDir(htmlHotUpdateService.getViewsDirs());
35925
+ */
35926
+ getViewsDirs() {
35927
+ return [
35928
+ this.hotUpdateDir,
35929
+ this.originalHtmlDir
35930
+ ];
35931
+ }
35932
+ /**
35899
35933
  * 从远端获取最新 HTML 文件并更新本地
35900
35934
  *
35901
35935
  * 调用方:
@@ -35911,7 +35945,7 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35911
35945
  return this.writeHtmlFiles(fileMap);
35912
35946
  }
35913
35947
  /**
35914
- * 将文件内容写入本地 HTML 目录(带文件锁)
35948
+ * 将文件内容写入热更新目录(带文件锁)
35915
35949
  */
35916
35950
  async writeHtmlFiles(fileMap) {
35917
35951
  const result = {
@@ -35922,12 +35956,12 @@ var HtmlHotUpdateService = class _HtmlHotUpdateService {
35922
35956
  if (entries.length === 0) {
35923
35957
  return result;
35924
35958
  }
35925
- this.logger.log(`[DEBUG] writeHtmlFiles: acquiring lock, ${entries.length} files to write, dir=${this.localHtmlDir}`);
35959
+ this.logger.log(`[DEBUG] writeHtmlFiles: acquiring lock, ${entries.length} files to write, dir=${this.hotUpdateDir}`);
35926
35960
  await this.fileLock.acquire();
35927
35961
  try {
35928
35962
  for (const [filePath, content] of entries) {
35929
35963
  try {
35930
- const localPath = join2(this.localHtmlDir, filePath);
35964
+ const localPath = join2(this.hotUpdateDir, filePath);
35931
35965
  await fs2.mkdir(dirname(localPath), {
35932
35966
  recursive: true
35933
35967
  });
@@ -36141,7 +36175,10 @@ HtmlHotUpdateModule = _ts_decorate14([
36141
36175
  })
36142
36176
  ], HtmlHotUpdateModule);
36143
36177
 
36144
- // src/modules/platform/module.ts
36178
+ // src/middlewares/html-hot-update-view/index.ts
36179
+ import { Injectable as Injectable11, Logger as Logger7 } from "@nestjs/common";
36180
+ import { existsSync as existsSync3 } from "fs";
36181
+ import { join as join3 } from "path";
36145
36182
  function _ts_decorate15(decorators, target, key, desc) {
36146
36183
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
36147
36184
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -36149,6 +36186,40 @@ function _ts_decorate15(decorators, target, key, desc) {
36149
36186
  return c > 3 && r && Object.defineProperty(target, key, r), r;
36150
36187
  }
36151
36188
  __name(_ts_decorate15, "_ts_decorate");
36189
+ var HOT_UPDATE_DIR = "/tmp/html-hot-update";
36190
+ var HtmlHotUpdateViewMiddleware = class _HtmlHotUpdateViewMiddleware {
36191
+ static {
36192
+ __name(this, "HtmlHotUpdateViewMiddleware");
36193
+ }
36194
+ logger = new Logger7(_HtmlHotUpdateViewMiddleware.name);
36195
+ use(req, res, next) {
36196
+ if (process.env.NODE_ENV !== "production") {
36197
+ return next();
36198
+ }
36199
+ const originalRender = res.render.bind(res);
36200
+ res.render = (view, options, callback) => {
36201
+ const hotPath = join3(HOT_UPDATE_DIR, `${view}.html`);
36202
+ if (existsSync3(hotPath)) {
36203
+ this.logger.log(`[DEBUG] render hot-updated HTML: ${hotPath}`);
36204
+ return originalRender(hotPath, options, callback);
36205
+ }
36206
+ return originalRender(view, options, callback);
36207
+ };
36208
+ next();
36209
+ }
36210
+ };
36211
+ HtmlHotUpdateViewMiddleware = _ts_decorate15([
36212
+ Injectable11()
36213
+ ], HtmlHotUpdateViewMiddleware);
36214
+
36215
+ // src/modules/platform/module.ts
36216
+ function _ts_decorate16(decorators, target, key, desc) {
36217
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
36218
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
36219
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
36220
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
36221
+ }
36222
+ __name(_ts_decorate16, "_ts_decorate");
36152
36223
  var PLATFORM_MODULE_OPTIONS = /* @__PURE__ */ Symbol("PLATFORM_MODULE_OPTIONS");
36153
36224
  var PlatformModule = class _PlatformModule {
36154
36225
  static {
@@ -36293,7 +36364,7 @@ var PlatformModule = class _PlatformModule {
36293
36364
  consumer.apply(UserContextMiddleware, RequestContextMiddleware, LoggerContextMiddleware, ObservableTraceMiddleware, ...DISABLE_DATAPASS ? [] : [
36294
36365
  SqlExecutionContextMiddleware
36295
36366
  ]).forRoutes("/*");
36296
- consumer.apply(CsrfTokenMiddleware, ViewContextMiddleware).exclude("/api/(.*)", "/static/(.*)").forRoutes("*");
36367
+ consumer.apply(CsrfTokenMiddleware, ViewContextMiddleware, HtmlHotUpdateViewMiddleware).exclude("/api/(.*)", "/static/(.*)").forRoutes("*");
36297
36368
  if (options.enableCsrf !== false) {
36298
36369
  const csrfRoutes = options.csrfRoutes || "/api/*";
36299
36370
  if (Array.isArray(csrfRoutes)) {
@@ -36306,7 +36377,7 @@ var PlatformModule = class _PlatformModule {
36306
36377
  }
36307
36378
  }
36308
36379
  };
36309
- PlatformModule = _ts_decorate15([
36380
+ PlatformModule = _ts_decorate16([
36310
36381
  Global(),
36311
36382
  Module3({})
36312
36383
  ], PlatformModule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-nestjs-core",
3
- "version": "1.1.33-alpha.5",
3
+ "version": "1.1.33-alpha.6",
4
4
  "description": "FullStack Nestjs Core",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",