@lark-apaas/fullstack-nestjs-core 1.1.56-alpha.2 → 1.1.56-beta.0

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
@@ -14894,10 +14894,10 @@ var require_object_inspect = __commonJS({
14894
14894
  }
14895
14895
  if (!isDate(obj) && !isRegExp(obj)) {
14896
14896
  var ys = arrObjKeys(obj, inspect);
14897
- var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
14897
+ var isPlainObject2 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
14898
14898
  var protoTag = obj instanceof Object ? "" : "null prototype";
14899
- var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
14900
- var constructorTag = isPlainObject || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
14899
+ var stringTag = !isPlainObject2 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
14900
+ var constructorTag = isPlainObject2 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
14901
14901
  var tag = constructorTag + (stringTag || protoTag ? "[" + $join.call($concat.call([], stringTag || [], protoTag || []), ": ") + "] " : "");
14902
14902
  if (ys.length === 0) {
14903
14903
  return tag + "{}";
@@ -34423,7 +34423,11 @@ __export(index_exports, {
34423
34423
  UserContextMiddleware: () => UserContextMiddleware,
34424
34424
  ViewContextMiddleware: () => ViewContextMiddleware,
34425
34425
  configureApp: () => configureApp,
34426
- createLegacyPathRedirectMiddleware: () => createLegacyPathRedirectMiddleware
34426
+ createLegacyPathRedirectMiddleware: () => createLegacyPathRedirectMiddleware,
34427
+ safeEscape: () => safeEscape,
34428
+ safeEscapeDeep: () => safeEscapeDeep,
34429
+ safeStringParse: () => safeStringParse,
34430
+ safeStringify: () => safeStringify
34427
34431
  });
34428
34432
  module.exports = __toCommonJS(index_exports);
34429
34433
 
@@ -34436,7 +34440,6 @@ var import_nestjs_observable = require("@lark-apaas/nestjs-observable");
34436
34440
  var import_axios2 = require("@nestjs/axios");
34437
34441
  var import_nestjs_logger2 = require("@lark-apaas/nestjs-logger");
34438
34442
  var import_nestjs_datapaas = require("@lark-apaas/nestjs-datapaas");
34439
- var import_nestjs = require("@lark-apaas/cache-service/nestjs");
34440
34443
  var import_nestjs_authnpaas = require("@lark-apaas/nestjs-authnpaas");
34441
34444
  var import_nestjs_http_forwarder = require("@lark-apaas/nestjs-http-forwarder");
34442
34445
  var import_nestjs_trigger = require("@lark-apaas/nestjs-trigger");
@@ -34560,6 +34563,19 @@ var import_common3 = require("@nestjs/common");
34560
34563
  var import_nestjs_common = require("@lark-apaas/nestjs-common");
34561
34564
 
34562
34565
  // src/utils/safe-stringify.ts
34566
+ function safeStringify(obj) {
34567
+ const json2 = JSON.stringify(obj);
34568
+ return safeEscape(json2);
34569
+ }
34570
+ __name(safeStringify, "safeStringify");
34571
+ function safeStringParse(str, defaultValue = null) {
34572
+ try {
34573
+ return JSON.parse(str);
34574
+ } catch (e) {
34575
+ return defaultValue;
34576
+ }
34577
+ }
34578
+ __name(safeStringParse, "safeStringParse");
34563
34579
  function safeEscape(s) {
34564
34580
  return s.replace(/[<>&='"\n\r\u2028\u2029]/g, function(c) {
34565
34581
  switch (c.charCodeAt(0)) {
@@ -34601,6 +34617,40 @@ function safeEscape(s) {
34601
34617
  });
34602
34618
  }
34603
34619
  __name(safeEscape, "safeEscape");
34620
+ function safeEscapeDeep(value) {
34621
+ return safeEscapeDeepInner(value, /* @__PURE__ */ new WeakSet());
34622
+ }
34623
+ __name(safeEscapeDeep, "safeEscapeDeep");
34624
+ var plainProtos = /* @__PURE__ */ new Set([
34625
+ Object.prototype,
34626
+ null
34627
+ ]);
34628
+ function isPlainObject(v) {
34629
+ if (v === null || typeof v !== "object") return false;
34630
+ return plainProtos.has(Object.getPrototypeOf(v));
34631
+ }
34632
+ __name(isPlainObject, "isPlainObject");
34633
+ function safeEscapeDeepInner(value, seen) {
34634
+ if (typeof value === "string") {
34635
+ return safeEscape(value);
34636
+ }
34637
+ if (Array.isArray(value)) {
34638
+ if (seen.has(value)) return value;
34639
+ seen.add(value);
34640
+ return value.map((v) => safeEscapeDeepInner(v, seen));
34641
+ }
34642
+ if (isPlainObject(value)) {
34643
+ if (seen.has(value)) return value;
34644
+ seen.add(value);
34645
+ const out = {};
34646
+ for (const k of Object.keys(value)) {
34647
+ out[k] = safeEscapeDeepInner(value[k], seen);
34648
+ }
34649
+ return out;
34650
+ }
34651
+ return value;
34652
+ }
34653
+ __name(safeEscapeDeepInner, "safeEscapeDeepInner");
34604
34654
 
34605
34655
  // src/middlewares/view-context/middleware.ts
34606
34656
  function _ts_decorate3(decorators, target, key, desc) {
@@ -34668,7 +34718,10 @@ var ViewContextMiddleware = class _ViewContextMiddleware {
34668
34718
  tenantId,
34669
34719
  environment,
34670
34720
  showBadge: appInfo?.show_badge !== false,
34671
- appPublished: appPublishedData ?? null,
34721
+ // 上游 get_published_v2 返回的整包数据里可能含用户可输入字段(如 app_description),
34722
+ // 用户输入 </script> / 引号 / 换行等会破坏下游 <script> raw 注入的 JSON.stringify 结果,
34723
+ // 深度 escape 所有 string 字段兜底;浏览器 JSON.parse 后仍还原为原字符串,前端无感。
34724
+ appPublished: appPublishedData ? safeEscapeDeep(appPublishedData) : null,
34672
34725
  basename
34673
34726
  };
34674
34727
  res.locals = {
@@ -36403,22 +36456,6 @@ var PlatformModule = class _PlatformModule {
36403
36456
  }, "useFactory")
36404
36457
  })
36405
36458
  ],
36406
- import_nestjs.NestjsCacheModule.forRootAsync({
36407
- inject: [
36408
- import_nestjs_logger2.AppLogger
36409
- ],
36410
- useFactory: /* @__PURE__ */ __name((...args) => {
36411
- const appLogger = args[0];
36412
- const connectionString = process.env.SUDA_CACHE_URL ?? "";
36413
- if (!connectionString) {
36414
- appLogger.warn("SUDA_CACHE_URL is empty, cache-service will be effectively disabled until it is set.", "PlatformModule");
36415
- }
36416
- return {
36417
- connectionString,
36418
- connectionTokenFilePath: "/var/run/secrets/zti/credential"
36419
- };
36420
- }, "useFactory")
36421
- }),
36422
36459
  import_nestjs_authnpaas.AuthNPaasModule.forRoot(),
36423
36460
  import_nestjs_authzpaas.AuthZPaasModule.forRoot({
36424
36461
  ...options.authz || {}
@@ -36638,6 +36675,10 @@ var import_nestjs_authzpaas2 = require("@lark-apaas/nestjs-authzpaas");
36638
36675
  ViewContextMiddleware,
36639
36676
  configureApp,
36640
36677
  createLegacyPathRedirectMiddleware,
36678
+ safeEscape,
36679
+ safeEscapeDeep,
36680
+ safeStringParse,
36681
+ safeStringify,
36641
36682
  ...require("@lark-apaas/nestjs-authnpaas"),
36642
36683
  ...require("@lark-apaas/nestjs-capability"),
36643
36684
  ...require("@lark-apaas/nestjs-datapaas"),
package/dist/index.d.cts CHANGED
@@ -411,4 +411,29 @@ declare class PlatformHttpClientService {
411
411
  private registerInterceptorsForClient;
412
412
  }
413
413
 
414
- export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, HtmlHotUpdateModule, HtmlHotUpdateService, type PlatformHttpClientOptions, PlatformHttpClientService, PlatformModule, type PlatformModuleOptions, StaticModule, UserContextMiddleware, ViewContextMiddleware, configureApp, createLegacyPathRedirectMiddleware };
414
+ /**
415
+ * 安全转义的 Json Stringify,模版渲染的 JSON 对象需要调用 safeStringify,而不是用原生的 JSON.stringify。
416
+ * 抄 gson 的实现: https://github.com/google/gson/blob/49ddab9eeb6cbac686711deca6001d40e8d8500d/gson/src/main/java/com/google/gson/stream/JsonWriter.java
417
+ * 将 json 的敏感字符转换为 unicode, 避免 xss
418
+ */
419
+ declare function safeStringify(obj: any): string;
420
+ declare function safeStringParse<T>(str: string, defaultValue?: any): T;
421
+ declare function safeEscape(s: string): string;
422
+ /**
423
+ * 深度递归 safeEscape:仅处理 plain object / array / string,其他类型(number /
424
+ * boolean / null / undefined / Date / Map / Set / Buffer / class 实例 …)原样返回,
425
+ * 避免把非 plain 对象打散成 `{}`。命中循环引用时对已访问节点原样返回,不再递归。
426
+ *
427
+ * ⚠️ 用途约定:产物是**给 JS 源码字面量语境**用的(例如把整段结果作为
428
+ * `<script>window.x = ${result}</script>` 直接注入)。转义后的 `<` 是 6 个字面
429
+ * 字符(含反斜杠),依赖 JS 引擎在 parse 字符串字面量时把它解回 `<`。
430
+ *
431
+ * 若下游再对结果做一次 `JSON.stringify`(如 EJS `<%- JSON.stringify(...) %>`),
432
+ * `\` 会被 JSON 再次转义为 `\\` —— 这仍然能阻止 `</script>` 提前闭合 <script> 块
433
+ * (核心目标),但**浏览器端 JSON.parse 拿到的字符串会含字面 `<` 序列而非
434
+ * `<`**。这是 SDK 与下游的既有契约(现存 `safeEscape(appDescription)` 也是同样性质)。
435
+ * 前端如需还原可自行 `JSON.parse('"' + v + '"')`。
436
+ */
437
+ declare function safeEscapeDeep<T>(value: T): T;
438
+
439
+ export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, HtmlHotUpdateModule, HtmlHotUpdateService, type PlatformHttpClientOptions, PlatformHttpClientService, PlatformModule, type PlatformModuleOptions, StaticModule, UserContextMiddleware, ViewContextMiddleware, configureApp, createLegacyPathRedirectMiddleware, safeEscape, safeEscapeDeep, safeStringParse, safeStringify };
package/dist/index.d.ts CHANGED
@@ -411,4 +411,29 @@ declare class PlatformHttpClientService {
411
411
  private registerInterceptorsForClient;
412
412
  }
413
413
 
414
- export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, HtmlHotUpdateModule, HtmlHotUpdateService, type PlatformHttpClientOptions, PlatformHttpClientService, PlatformModule, type PlatformModuleOptions, StaticModule, UserContextMiddleware, ViewContextMiddleware, configureApp, createLegacyPathRedirectMiddleware };
414
+ /**
415
+ * 安全转义的 Json Stringify,模版渲染的 JSON 对象需要调用 safeStringify,而不是用原生的 JSON.stringify。
416
+ * 抄 gson 的实现: https://github.com/google/gson/blob/49ddab9eeb6cbac686711deca6001d40e8d8500d/gson/src/main/java/com/google/gson/stream/JsonWriter.java
417
+ * 将 json 的敏感字符转换为 unicode, 避免 xss
418
+ */
419
+ declare function safeStringify(obj: any): string;
420
+ declare function safeStringParse<T>(str: string, defaultValue?: any): T;
421
+ declare function safeEscape(s: string): string;
422
+ /**
423
+ * 深度递归 safeEscape:仅处理 plain object / array / string,其他类型(number /
424
+ * boolean / null / undefined / Date / Map / Set / Buffer / class 实例 …)原样返回,
425
+ * 避免把非 plain 对象打散成 `{}`。命中循环引用时对已访问节点原样返回,不再递归。
426
+ *
427
+ * ⚠️ 用途约定:产物是**给 JS 源码字面量语境**用的(例如把整段结果作为
428
+ * `<script>window.x = ${result}</script>` 直接注入)。转义后的 `<` 是 6 个字面
429
+ * 字符(含反斜杠),依赖 JS 引擎在 parse 字符串字面量时把它解回 `<`。
430
+ *
431
+ * 若下游再对结果做一次 `JSON.stringify`(如 EJS `<%- JSON.stringify(...) %>`),
432
+ * `\` 会被 JSON 再次转义为 `\\` —— 这仍然能阻止 `</script>` 提前闭合 <script> 块
433
+ * (核心目标),但**浏览器端 JSON.parse 拿到的字符串会含字面 `<` 序列而非
434
+ * `<`**。这是 SDK 与下游的既有契约(现存 `safeEscape(appDescription)` 也是同样性质)。
435
+ * 前端如需还原可自行 `JSON.parse('"' + v + '"')`。
436
+ */
437
+ declare function safeEscapeDeep<T>(value: T): T;
438
+
439
+ export { type ApiNotFoundResponse, CsrfMiddleware, CsrfTokenMiddleware, FileService, HtmlHotUpdateModule, HtmlHotUpdateService, type PlatformHttpClientOptions, PlatformHttpClientService, PlatformModule, type PlatformModuleOptions, StaticModule, UserContextMiddleware, ViewContextMiddleware, configureApp, createLegacyPathRedirectMiddleware, safeEscape, safeEscapeDeep, safeStringParse, safeStringify };
package/dist/index.js CHANGED
@@ -14893,10 +14893,10 @@ var require_object_inspect = __commonJS({
14893
14893
  }
14894
14894
  if (!isDate(obj) && !isRegExp(obj)) {
14895
14895
  var ys = arrObjKeys(obj, inspect);
14896
- var isPlainObject = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
14896
+ var isPlainObject2 = gPO ? gPO(obj) === Object.prototype : obj instanceof Object || obj.constructor === Object;
14897
14897
  var protoTag = obj instanceof Object ? "" : "null prototype";
14898
- var stringTag = !isPlainObject && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
14899
- var constructorTag = isPlainObject || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
14898
+ var stringTag = !isPlainObject2 && toStringTag && Object(obj) === obj && toStringTag in obj ? $slice.call(toStr(obj), 8, -1) : protoTag ? "Object" : "";
14899
+ var constructorTag = isPlainObject2 || typeof obj.constructor !== "function" ? "" : obj.constructor.name ? obj.constructor.name + " " : "";
14900
14900
  var tag = constructorTag + (stringTag || protoTag ? "[" + $join.call($concat.call([], stringTag || [], protoTag || []), ": ") + "] " : "");
14901
14901
  if (ys.length === 0) {
14902
14902
  return tag + "{}";
@@ -34409,7 +34409,6 @@ import { NestjsObservableModule as ObservableModule, Observable, ObservableTrace
34409
34409
  import { HttpModule } from "@nestjs/axios";
34410
34410
  import { LoggerModule, AppLogger as AppLogger2, LoggerContextMiddleware } from "@lark-apaas/nestjs-logger";
34411
34411
  import { DataPaasModule, SqlExecutionContextMiddleware } from "@lark-apaas/nestjs-datapaas";
34412
- import { NestjsCacheModule } from "@lark-apaas/cache-service/nestjs";
34413
34412
  import { AuthNPaasModule } from "@lark-apaas/nestjs-authnpaas";
34414
34413
  import { HttpForwarderModule } from "@lark-apaas/nestjs-http-forwarder";
34415
34414
  import { AutomationModule } from "@lark-apaas/nestjs-trigger";
@@ -34533,6 +34532,19 @@ import { Inject, Injectable as Injectable3, Logger } from "@nestjs/common";
34533
34532
  import { PLATFORM_HTTP_CLIENT } from "@lark-apaas/nestjs-common";
34534
34533
 
34535
34534
  // src/utils/safe-stringify.ts
34535
+ function safeStringify(obj) {
34536
+ const json2 = JSON.stringify(obj);
34537
+ return safeEscape(json2);
34538
+ }
34539
+ __name(safeStringify, "safeStringify");
34540
+ function safeStringParse(str, defaultValue = null) {
34541
+ try {
34542
+ return JSON.parse(str);
34543
+ } catch (e) {
34544
+ return defaultValue;
34545
+ }
34546
+ }
34547
+ __name(safeStringParse, "safeStringParse");
34536
34548
  function safeEscape(s) {
34537
34549
  return s.replace(/[<>&='"\n\r\u2028\u2029]/g, function(c) {
34538
34550
  switch (c.charCodeAt(0)) {
@@ -34574,6 +34586,40 @@ function safeEscape(s) {
34574
34586
  });
34575
34587
  }
34576
34588
  __name(safeEscape, "safeEscape");
34589
+ function safeEscapeDeep(value) {
34590
+ return safeEscapeDeepInner(value, /* @__PURE__ */ new WeakSet());
34591
+ }
34592
+ __name(safeEscapeDeep, "safeEscapeDeep");
34593
+ var plainProtos = /* @__PURE__ */ new Set([
34594
+ Object.prototype,
34595
+ null
34596
+ ]);
34597
+ function isPlainObject(v) {
34598
+ if (v === null || typeof v !== "object") return false;
34599
+ return plainProtos.has(Object.getPrototypeOf(v));
34600
+ }
34601
+ __name(isPlainObject, "isPlainObject");
34602
+ function safeEscapeDeepInner(value, seen) {
34603
+ if (typeof value === "string") {
34604
+ return safeEscape(value);
34605
+ }
34606
+ if (Array.isArray(value)) {
34607
+ if (seen.has(value)) return value;
34608
+ seen.add(value);
34609
+ return value.map((v) => safeEscapeDeepInner(v, seen));
34610
+ }
34611
+ if (isPlainObject(value)) {
34612
+ if (seen.has(value)) return value;
34613
+ seen.add(value);
34614
+ const out = {};
34615
+ for (const k of Object.keys(value)) {
34616
+ out[k] = safeEscapeDeepInner(value[k], seen);
34617
+ }
34618
+ return out;
34619
+ }
34620
+ return value;
34621
+ }
34622
+ __name(safeEscapeDeepInner, "safeEscapeDeepInner");
34577
34623
 
34578
34624
  // src/middlewares/view-context/middleware.ts
34579
34625
  function _ts_decorate3(decorators, target, key, desc) {
@@ -34641,7 +34687,10 @@ var ViewContextMiddleware = class _ViewContextMiddleware {
34641
34687
  tenantId,
34642
34688
  environment,
34643
34689
  showBadge: appInfo?.show_badge !== false,
34644
- appPublished: appPublishedData ?? null,
34690
+ // 上游 get_published_v2 返回的整包数据里可能含用户可输入字段(如 app_description),
34691
+ // 用户输入 </script> / 引号 / 换行等会破坏下游 <script> raw 注入的 JSON.stringify 结果,
34692
+ // 深度 escape 所有 string 字段兜底;浏览器 JSON.parse 后仍还原为原字符串,前端无感。
34693
+ appPublished: appPublishedData ? safeEscapeDeep(appPublishedData) : null,
34645
34694
  basename
34646
34695
  };
34647
34696
  res.locals = {
@@ -36376,22 +36425,6 @@ var PlatformModule = class _PlatformModule {
36376
36425
  }, "useFactory")
36377
36426
  })
36378
36427
  ],
36379
- NestjsCacheModule.forRootAsync({
36380
- inject: [
36381
- AppLogger2
36382
- ],
36383
- useFactory: /* @__PURE__ */ __name((...args) => {
36384
- const appLogger = args[0];
36385
- const connectionString = process.env.SUDA_CACHE_URL ?? "";
36386
- if (!connectionString) {
36387
- appLogger.warn("SUDA_CACHE_URL is empty, cache-service will be effectively disabled until it is set.", "PlatformModule");
36388
- }
36389
- return {
36390
- connectionString,
36391
- connectionTokenFilePath: "/var/run/secrets/zti/credential"
36392
- };
36393
- }, "useFactory")
36394
- }),
36395
36428
  AuthNPaasModule.forRoot(),
36396
36429
  AuthZPaasModule.forRoot({
36397
36430
  ...options.authz || {}
@@ -36609,7 +36642,11 @@ export {
36609
36642
  UserContextMiddleware,
36610
36643
  ViewContextMiddleware,
36611
36644
  configureApp,
36612
- createLegacyPathRedirectMiddleware
36645
+ createLegacyPathRedirectMiddleware,
36646
+ safeEscape,
36647
+ safeEscapeDeep,
36648
+ safeStringParse,
36649
+ safeStringify
36613
36650
  };
36614
36651
  /*! Bundled license information:
36615
36652
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lark-apaas/fullstack-nestjs-core",
3
- "version": "1.1.56-alpha.2",
3
+ "version": "1.1.56-beta.0",
4
4
  "description": "FullStack Nestjs Core",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -39,11 +39,10 @@
39
39
  "prepublishOnly": "npm run build"
40
40
  },
41
41
  "dependencies": {
42
- "@lark-apaas/cache-service": "0.1.1-alpha.1",
43
42
  "@lark-apaas/file-service": "^0.1.2",
44
43
  "@lark-apaas/http-client": "^0.1.7",
45
- "@lark-apaas/nestjs-authnpaas": "^1.0.4",
46
- "@lark-apaas/nestjs-authzpaas": "^0.1.9",
44
+ "@lark-apaas/nestjs-authnpaas": "^1.0.5",
45
+ "@lark-apaas/nestjs-authzpaas": "^0.1.12",
47
46
  "@lark-apaas/nestjs-capability": "^0.1.14",
48
47
  "@lark-apaas/nestjs-common": "^0.1.9",
49
48
  "@lark-apaas/nestjs-datapaas": "^1.0.21",