@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 +90 -19
- package/dist/index.d.cts +24 -3
- package/dist/index.d.ts +24 -3
- package/dist/index.js +86 -15
- package/package.json +1 -1
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
|
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
|
-
/**
|
|
35889
|
-
|
|
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()},
|
|
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
|
-
*
|
|
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.
|
|
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.
|
|
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/
|
|
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
|
|
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 =
|
|
36333
|
-
(0,
|
|
36334
|
-
(0,
|
|
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
|
-
/**
|
|
154
|
-
private readonly
|
|
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
|
-
*
|
|
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
|
-
/**
|
|
154
|
-
private readonly
|
|
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
|
-
*
|
|
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
|
|
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 =
|
|
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 =
|
|
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
|
|
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(
|
|
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 =
|
|
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
|
-
/**
|
|
35866
|
-
|
|
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()},
|
|
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
|
-
*
|
|
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.
|
|
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.
|
|
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/
|
|
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 =
|
|
36380
|
+
PlatformModule = _ts_decorate16([
|
|
36310
36381
|
Global(),
|
|
36311
36382
|
Module3({})
|
|
36312
36383
|
], PlatformModule);
|