@rsdoctor/components 1.5.11 → 2.0.0-alpha.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.
Files changed (107) hide show
  1. package/dist/components/Alert/types.d.ts +2 -2
  2. package/dist/components/Alerts/bundle-alert.d.ts +1 -1
  3. package/dist/components/Alerts/bundle-alert.mjs.map +1 -1
  4. package/dist/components/Alerts/overlay.mjs.map +1 -1
  5. package/dist/components/Charts/done.mjs +2 -2
  6. package/dist/components/Charts/done.mjs.map +1 -1
  7. package/dist/components/Charts/minify.mjs +2 -2
  8. package/dist/components/Charts/minify.mjs.map +1 -1
  9. package/dist/components/Configuration/builder.d.ts +1 -5
  10. package/dist/components/Configuration/builder.mjs.map +1 -1
  11. package/dist/components/Layout/index.d.ts +2 -2
  12. package/dist/components/Layout/index.mjs.map +1 -1
  13. package/dist/components/Layout/menus.mjs +7 -7
  14. package/dist/components/Layout/menus.mjs.map +1 -1
  15. package/dist/components/Loader/Analysis/files.mjs.map +1 -1
  16. package/dist/components/Loader/Analysis/index.d.ts +1 -7
  17. package/dist/components/Loader/Analysis/index.mjs.map +1 -1
  18. package/dist/components/Loader/executions.d.ts +1 -1
  19. package/dist/components/Loader/executions.mjs.map +1 -1
  20. package/dist/components/Manifest/api.d.ts +2 -2
  21. package/dist/components/Manifest/api.mjs +2 -2
  22. package/dist/components/Manifest/api.mjs.map +1 -1
  23. package/dist/components/Opener/code.d.ts +1 -1
  24. package/dist/components/Opener/code.mjs.map +1 -1
  25. package/dist/components/Opener/ide.d.ts +1 -1
  26. package/dist/components/Opener/ide.mjs.map +1 -1
  27. package/dist/components/Overall/bundle.d.ts +1 -1
  28. package/dist/components/Overall/bundle.mjs.map +1 -1
  29. package/dist/components/Plugins/plugins.d.ts +18 -0
  30. package/dist/components/Plugins/{webpack.mjs → plugins.mjs} +4 -4
  31. package/dist/components/Plugins/plugins.mjs.map +1 -0
  32. package/dist/components/TextDrawer/index.d.ts +1 -1
  33. package/dist/components/TextDrawer/index.mjs.map +1 -1
  34. package/dist/components/base/CodeViewer/index.mjs +2 -2
  35. package/dist/components/base/CodeViewer/index.mjs.map +1 -1
  36. package/dist/components/base/DiffViewer/index.mjs +1 -1
  37. package/dist/components/base/DiffViewer/index.mjs.map +1 -1
  38. package/dist/pages/{WebpackLoaders → Loaders}/Analysis/constants.d.ts +1 -1
  39. package/dist/pages/{WebpackLoaders → Loaders}/Analysis/constants.mjs +1 -1
  40. package/dist/pages/Loaders/Analysis/constants.mjs.map +1 -0
  41. package/dist/pages/Loaders/Analysis/index.mjs.map +1 -0
  42. package/dist/pages/{WebpackLoaders → Loaders}/Overall/constants.d.ts +1 -1
  43. package/dist/pages/{WebpackLoaders → Loaders}/Overall/constants.mjs +1 -1
  44. package/dist/pages/Loaders/Overall/constants.mjs.map +1 -0
  45. package/dist/pages/Loaders/Overall/index.mjs.map +1 -0
  46. package/dist/pages/Loaders/constants.d.ts +2 -0
  47. package/dist/pages/{WebpackLoaders → Loaders}/constants.mjs +1 -1
  48. package/dist/pages/Loaders/constants.mjs.map +1 -0
  49. package/dist/pages/ModuleAnalyze/chunks.mjs.map +1 -1
  50. package/dist/pages/{WebpackPlugins → Plugins}/constants.d.ts +1 -1
  51. package/dist/pages/{WebpackPlugins → Plugins}/constants.mjs +1 -1
  52. package/dist/pages/Plugins/constants.mjs.map +1 -0
  53. package/dist/pages/Plugins/index.css.map +1 -0
  54. package/dist/pages/{WebpackPlugins → Plugins}/index.mjs +2 -2
  55. package/dist/pages/Plugins/index.mjs.map +1 -0
  56. package/dist/pages/Resources/BundleDiff/DiffContainer/modules.mjs +2 -2
  57. package/dist/pages/Resources/BundleDiff/DiffContainer/modules.mjs.map +1 -1
  58. package/dist/pages/Resources/BundleDiff/DiffContainer/row.mjs +1 -1
  59. package/dist/pages/Resources/BundleDiff/DiffContainer/row.mjs.map +1 -1
  60. package/dist/pages/Resources/BundleDiff/DiffContainer/types.d.ts +1 -1
  61. package/dist/pages/Resources/BundleDiff/DiffServerAPIProvider/index.d.ts +1 -1
  62. package/dist/pages/Resources/BundleDiff/DiffServerAPIProvider/index.mjs.map +1 -1
  63. package/dist/pages/TreeShaking/editor.mjs +2 -2
  64. package/dist/pages/TreeShaking/editor.mjs.map +1 -1
  65. package/dist/pages/index.d.ts +3 -3
  66. package/dist/pages/index.mjs +4 -4
  67. package/dist/utils/data/base.d.ts +2 -2
  68. package/dist/utils/data/base.mjs.map +1 -1
  69. package/dist/utils/data/local.d.ts +10 -3
  70. package/dist/utils/data/local.mjs +37 -24
  71. package/dist/utils/data/local.mjs.map +1 -1
  72. package/dist/utils/data/local.test.d.ts +1 -0
  73. package/dist/utils/data/local.test.mjs +89 -0
  74. package/dist/utils/data/local.test.mjs.map +1 -0
  75. package/dist/utils/file.d.ts +3 -3
  76. package/dist/utils/file.mjs.map +1 -1
  77. package/dist/utils/hooks.d.ts +1 -1
  78. package/dist/utils/request.mjs +4 -3
  79. package/dist/utils/request.mjs.map +1 -1
  80. package/dist/utils/request.test.mjs +23 -0
  81. package/dist/utils/request.test.mjs.map +1 -1
  82. package/dist/utils/routes.mjs +1 -1
  83. package/dist/utils/routes.mjs.map +1 -1
  84. package/dist/utils/socket.d.ts +12 -2
  85. package/dist/utils/socket.mjs +155 -23
  86. package/dist/utils/socket.mjs.map +1 -1
  87. package/dist/utils/socket.test.d.ts +1 -0
  88. package/dist/utils/socket.test.mjs +167 -0
  89. package/dist/utils/socket.test.mjs.map +1 -0
  90. package/package.json +11 -12
  91. package/dist/components/Plugins/webpack.d.ts +0 -18
  92. package/dist/components/Plugins/webpack.mjs.map +0 -1
  93. package/dist/pages/WebpackLoaders/Analysis/constants.mjs.map +0 -1
  94. package/dist/pages/WebpackLoaders/Analysis/index.mjs.map +0 -1
  95. package/dist/pages/WebpackLoaders/Overall/constants.mjs.map +0 -1
  96. package/dist/pages/WebpackLoaders/Overall/index.mjs.map +0 -1
  97. package/dist/pages/WebpackLoaders/constants.d.ts +0 -2
  98. package/dist/pages/WebpackLoaders/constants.mjs.map +0 -1
  99. package/dist/pages/WebpackPlugins/constants.mjs.map +0 -1
  100. package/dist/pages/WebpackPlugins/index.css.map +0 -1
  101. package/dist/pages/WebpackPlugins/index.mjs.map +0 -1
  102. /package/dist/pages/{WebpackLoaders → Loaders}/Analysis/index.d.ts +0 -0
  103. /package/dist/pages/{WebpackLoaders → Loaders}/Analysis/index.mjs +0 -0
  104. /package/dist/pages/{WebpackLoaders → Loaders}/Overall/index.d.ts +0 -0
  105. /package/dist/pages/{WebpackLoaders → Loaders}/Overall/index.mjs +0 -0
  106. /package/dist/pages/{WebpackPlugins → Plugins}/index.css +0 -0
  107. /package/dist/pages/{WebpackPlugins → Plugins}/index.d.ts +0 -0
@@ -2,7 +2,8 @@ import { Manifest } from "@rsdoctor/utils/common";
2
2
  import { SDK } from "@rsdoctor/types";
3
3
  import { get } from "es-toolkit/compat";
4
4
  import { BaseDataLoader } from "./base.mjs";
5
- import { getSocket } from "../socket.mjs";
5
+ import { postServerAPI } from "../request.mjs";
6
+ import { requestServerAPI, subscribeServerAPI, unsubscribeServerAPI } from "../socket.mjs";
6
7
  function _define_property(obj, key, value) {
7
8
  if (key in obj) Object.defineProperty(obj, key, {
8
9
  value: value,
@@ -25,12 +26,11 @@ class LocalServerDataLoader extends BaseDataLoader {
25
26
  let res = data;
26
27
  if (Manifest.isShardingData(res)) {
27
28
  if (!this.shardingDataMap.has(key)) {
28
- const task = new Promise((resolve)=>{
29
- getSocket().emit(SDK.ServerAPI.API.LoadDataByKey, {
30
- key
31
- }, (res)=>{
32
- resolve(res.res);
33
- });
29
+ const task = postServerAPI(SDK.ServerAPI.API.LoadDataByKey, {
30
+ key
31
+ }).catch((err)=>{
32
+ this.log("loadData error: ", res, key);
33
+ throw err;
34
34
  });
35
35
  this.shardingDataMap.set(key, task);
36
36
  }
@@ -45,31 +45,44 @@ class LocalServerDataLoader extends BaseDataLoader {
45
45
  const [api, body] = args;
46
46
  const key = body ? `${api}_${JSON.stringify(body)}` : `${api}`;
47
47
  const socketPort = this.get('__SOCKET__PORT__') ?? '';
48
- return this.limit(key, async ()=>new Promise((resolve)=>{
49
- getSocket(socketPort).emit(api, body, (res)=>{
50
- resolve(res.res);
51
- });
52
- }));
48
+ return this.limit(key, async ()=>{
49
+ try {
50
+ return await requestServerAPI(api, body, socketPort);
51
+ } catch (err) {
52
+ this.log("loadAPI error: ", key);
53
+ throw err;
54
+ }
55
+ });
53
56
  }
54
57
  dispose() {
55
58
  super.dispose();
56
- this.events.forEach((evs, api)=>{
57
- evs.forEach((ev)=>{
58
- this.removeOnDataUpdate(api, ev);
59
+ this.events.forEach(({ api, body, listeners })=>{
60
+ listeners.forEach((listener)=>{
61
+ this.removeOnDataUpdate(api, body, listener);
59
62
  });
60
- evs.clear();
63
+ listeners.clear();
61
64
  });
62
65
  this.events.clear();
63
66
  }
64
- onDataUpdate(api, fn) {
65
- if (!this.events.has(api)) this.events.set(api, new Set());
66
- if (this.events.get(api).has(fn)) return;
67
- this.events.get(api).add(fn);
68
- getSocket().on(api, fn);
67
+ onDataUpdate(api, body, fn) {
68
+ const normalizedBody = body ?? null;
69
+ const key = `${api}::${JSON.stringify(normalizedBody)}`;
70
+ if (!this.events.has(key)) this.events.set(key, {
71
+ api,
72
+ body: normalizedBody,
73
+ listeners: new Set()
74
+ });
75
+ const subscription = this.events.get(key);
76
+ if (subscription.listeners.has(fn)) return;
77
+ subscription.listeners.add(fn);
78
+ const socketPort = this.get('__SOCKET__PORT__') ?? '';
79
+ subscribeServerAPI(api, normalizedBody, fn, socketPort);
69
80
  }
70
- removeOnDataUpdate(api, fn) {
71
- getSocket().off(api, fn);
72
- this.events.get(api).delete(fn);
81
+ removeOnDataUpdate(api, body, fn) {
82
+ const key = `${api}::${JSON.stringify(body ?? null)}`;
83
+ const socketPort = this.get('__SOCKET__PORT__') ?? '';
84
+ unsubscribeServerAPI(api, body, fn, socketPort);
85
+ this.events.get(key)?.listeners.delete(fn);
73
86
  }
74
87
  constructor(...args){
75
88
  super(...args), _define_property(this, "events", new Map());
@@ -1 +1 @@
1
- {"version":3,"file":"utils/data/local.mjs","sources":["../../../src/utils/data/local.ts"],"sourcesContent":["import { Manifest as ManifestShared } from '@rsdoctor/utils/common';\nimport { Common, Manifest, SDK } from '@rsdoctor/types';\nimport { get } from 'es-toolkit/compat';\nimport { BaseDataLoader } from './base';\nimport { getSocket } from '../socket';\n\nexport class LocalServerDataLoader extends BaseDataLoader {\n protected events: Map<\n SDK.ServerAPI.API | SDK.ServerAPI.APIExtends,\n Set<Common.Function>\n > = new Map();\n\n public isLocal() {\n return true;\n }\n\n public async loadData<T extends keyof Manifest.RsdoctorManifestData>(\n key: T,\n ): Promise<void | Manifest.RsdoctorManifestData[T]>;\n\n public async loadData(key: string): Promise<unknown> {\n return this.limit(key, async () => {\n const [scope, ...rest] = this.getKeys(key);\n const data = this.getData(scope as keyof Manifest.RsdoctorManifestData);\n\n if (!data) return;\n\n let res: unknown = data;\n\n // sharding files\n if (ManifestShared.isShardingData(res)) {\n if (!this.shardingDataMap.has(key)) {\n const task = new Promise((resolve) => {\n getSocket().emit(\n SDK.ServerAPI.API.LoadDataByKey,\n { key },\n (\n res: SDK.ServerAPI.SocketResponseType<SDK.ServerAPI.API.LoadDataByKey>,\n ) => {\n resolve(res.res);\n },\n );\n });\n // const task = postServerAPI(SDK.ServerAPI.API.LoadDataByKey, { key }).catch((err) => {\n // this.log(`loadData error: `, res, key);\n // throw err;\n // });\n // save with every key\n this.shardingDataMap.set(key, task);\n }\n\n res = await this.shardingDataMap.get(key);\n this.shardingDataMap.delete(key);\n return res;\n }\n\n return rest.length > 0 ? get(res, this.joinKeys(rest)) : res;\n });\n }\n\n public async loadAPI<\n T extends SDK.ServerAPI.API,\n B extends\n SDK.ServerAPI.InferRequestBodyType<T> = SDK.ServerAPI.InferRequestBodyType<T>,\n R extends\n SDK.ServerAPI.InferResponseType<T> = SDK.ServerAPI.InferResponseType<T>,\n >(...args: B extends void ? [api: T] : [api: T, body: B]): Promise<R> {\n const [api, body] = args;\n // request limitation key\n const key = body ? `${api}_${JSON.stringify(body)}` : `${api}`;\n const socketPort = this.get('__SOCKET__PORT__') ?? '';\n\n return this.limit(key, async () => {\n return new Promise((resolve) => {\n getSocket(socketPort).emit(\n api,\n body,\n (res: SDK.ServerAPI.SocketResponseType<T>) => {\n resolve(res.res as R);\n },\n );\n });\n // const res = await postServerAPI(...args).catch((err) => {\n // this.log(`loadAPI error: `, key);\n // throw err;\n // });\n\n // return res as R;\n });\n }\n\n public dispose() {\n super.dispose();\n this.events.forEach((evs, api) => {\n evs.forEach((ev) => {\n this.removeOnDataUpdate(api, ev);\n });\n evs.clear();\n });\n this.events.clear();\n }\n\n /**\n * add event listener when received data from server.\n */\n public onDataUpdate<T extends SDK.ServerAPI.API | SDK.ServerAPI.APIExtends>(\n api: T,\n fn: (response: SDK.ServerAPI.SocketResponseType<T>) => void,\n ) {\n if (!this.events.has(api)) {\n this.events.set(api, new Set());\n }\n\n if (this.events.get(api)!.has(fn)) {\n return;\n }\n\n this.events.get(api)!.add(fn);\n getSocket().on(api as string, fn);\n }\n\n public removeOnDataUpdate<\n T extends SDK.ServerAPI.API | SDK.ServerAPI.APIExtends,\n >(api: T, fn: (response: SDK.ServerAPI.SocketResponseType<T>) => void) {\n getSocket().off(api as string, fn);\n this.events.get(api)!.delete(fn);\n }\n}\n"],"names":["LocalServerDataLoader","BaseDataLoader","key","scope","rest","data","res","ManifestShared","task","Promise","resolve","getSocket","SDK","get","args","api","body","JSON","socketPort","evs","ev","fn","Set","Map"],"mappings":";;;;;;;;;;;;;;;AAMO,MAAMA,8BAA8BC;IAMlC,UAAU;QACf,OAAO;IACT;IAMA,MAAa,SAASC,GAAW,EAAoB;QACnD,OAAO,IAAI,CAAC,KAAK,CAACA,KAAK;YACrB,MAAM,CAACC,OAAO,GAAGC,KAAK,GAAG,IAAI,CAAC,OAAO,CAACF;YACtC,MAAMG,OAAO,IAAI,CAAC,OAAO,CAACF;YAE1B,IAAI,CAACE,MAAM;YAEX,IAAIC,MAAeD;YAGnB,IAAIE,SAAAA,cAA6B,CAACD,MAAM;gBACtC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAACJ,MAAM;oBAClC,MAAMM,OAAO,IAAIC,QAAQ,CAACC;wBACxBC,YAAY,IAAI,CACdC,IAAI,SAAS,CAAC,GAAG,CAAC,aAAa,EAC/B;4BAAEV;wBAAI,GACN,CACEI;4BAEAI,QAAQJ,IAAI,GAAG;wBACjB;oBAEJ;oBAMA,IAAI,CAAC,eAAe,CAAC,GAAG,CAACJ,KAAKM;gBAChC;gBAEAF,MAAM,MAAM,IAAI,CAAC,eAAe,CAAC,GAAG,CAACJ;gBACrC,IAAI,CAAC,eAAe,CAAC,MAAM,CAACA;gBAC5B,OAAOI;YACT;YAEA,OAAOF,KAAK,MAAM,GAAG,IAAIS,IAAIP,KAAK,IAAI,CAAC,QAAQ,CAACF,SAASE;QAC3D;IACF;IAEA,MAAa,QAMX,GAAGQ,IAAmD,EAAc;QACpE,MAAM,CAACC,KAAKC,KAAK,GAAGF;QAEpB,MAAMZ,MAAMc,OAAO,GAAGD,IAAI,CAAC,EAAEE,KAAK,SAAS,CAACD,OAAO,GAAG,GAAGD,KAAK;QAC9D,MAAMG,aAAa,IAAI,CAAC,GAAG,CAAC,uBAAuB;QAEnD,OAAO,IAAI,CAAC,KAAK,CAAChB,KAAK,UACd,IAAIO,QAAQ,CAACC;gBAClBC,UAAUO,YAAY,IAAI,CACxBH,KACAC,MACA,CAACV;oBACCI,QAAQJ,IAAI,GAAG;gBACjB;YAEJ;IAQJ;IAEO,UAAU;QACf,KAAK,CAAC;QACN,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAACa,KAAKJ;YACxBI,IAAI,OAAO,CAAC,CAACC;gBACX,IAAI,CAAC,kBAAkB,CAACL,KAAKK;YAC/B;YACAD,IAAI,KAAK;QACX;QACA,IAAI,CAAC,MAAM,CAAC,KAAK;IACnB;IAKO,aACLJ,GAAM,EACNM,EAA2D,EAC3D;QACA,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAACN,MACnB,IAAI,CAAC,MAAM,CAAC,GAAG,CAACA,KAAK,IAAIO;QAG3B,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAACP,KAAM,GAAG,CAACM,KAC5B;QAGF,IAAI,CAAC,MAAM,CAAC,GAAG,CAACN,KAAM,GAAG,CAACM;QAC1BV,YAAY,EAAE,CAACI,KAAeM;IAChC;IAEO,mBAELN,GAAM,EAAEM,EAA2D,EAAE;QACrEV,YAAY,GAAG,CAACI,KAAeM;QAC/B,IAAI,CAAC,MAAM,CAAC,GAAG,CAACN,KAAM,MAAM,CAACM;IAC/B;;QAxHK,gBACL,uBAAU,UAGN,IAAIE;;AAqHV"}
1
+ {"version":3,"file":"utils/data/local.mjs","sources":["../../../src/utils/data/local.ts"],"sourcesContent":["import { Manifest as ManifestShared } from '@rsdoctor/utils/common';\nimport { Common, Manifest, SDK } from '@rsdoctor/types';\nimport { get } from 'es-toolkit/compat';\nimport { BaseDataLoader } from './base';\nimport { postServerAPI } from '../request';\nimport {\n requestServerAPI,\n subscribeServerAPI,\n unsubscribeServerAPI,\n} from '../socket';\n\ntype DataUpdateAPI = SDK.ServerAPI.API | SDK.ServerAPI.APIExtends;\n\ntype DataUpdateSubscription = {\n api: DataUpdateAPI;\n body: SDK.ServerAPI.InferRequestBodyType<DataUpdateAPI, null> | null;\n listeners: Set<Common.Function>;\n};\n\nexport class LocalServerDataLoader extends BaseDataLoader {\n protected events: Map<string, DataUpdateSubscription> = new Map();\n\n public isLocal() {\n return true;\n }\n\n public async loadData<T extends keyof Manifest.RsdoctorManifestData>(\n key: T,\n ): Promise<void | Manifest.RsdoctorManifestData[T]>;\n\n public async loadData(key: string): Promise<unknown> {\n return this.limit(key, async () => {\n const [scope, ...rest] = this.getKeys(key);\n const data = this.getData(scope as keyof Manifest.RsdoctorManifestData);\n\n if (!data) return;\n\n let res: unknown = data;\n\n // sharding files\n if (ManifestShared.isShardingData(res)) {\n if (!this.shardingDataMap.has(key)) {\n const task = postServerAPI(SDK.ServerAPI.API.LoadDataByKey, {\n key,\n }).catch((err) => {\n this.log(`loadData error: `, res, key);\n throw err;\n });\n // save with every key\n this.shardingDataMap.set(key, task);\n }\n\n res = await this.shardingDataMap.get(key);\n this.shardingDataMap.delete(key);\n return res;\n }\n\n return rest.length > 0 ? get(res, this.joinKeys(rest)) : res;\n });\n }\n\n public async loadAPI<\n T extends SDK.ServerAPI.API,\n B extends SDK.ServerAPI.InferRequestBodyType<T> =\n SDK.ServerAPI.InferRequestBodyType<T>,\n R extends SDK.ServerAPI.InferResponseType<T> =\n SDK.ServerAPI.InferResponseType<T>,\n >(...args: B extends void ? [api: T] : [api: T, body: B]): Promise<R> {\n const [api, body] = args;\n // request limitation key\n const key = body ? `${api}_${JSON.stringify(body)}` : `${api}`;\n const socketPort = this.get('__SOCKET__PORT__') ?? '';\n\n return this.limit(key, async () => {\n try {\n return (await requestServerAPI(\n api,\n body as SDK.ServerAPI.InferRequestBodyType<T>,\n socketPort,\n )) as R;\n } catch (err) {\n this.log(`loadAPI error: `, key);\n throw err;\n }\n });\n }\n\n public dispose() {\n super.dispose();\n this.events.forEach(({ api, body, listeners }) => {\n listeners.forEach((listener) => {\n this.removeOnDataUpdate(api, body, listener);\n });\n listeners.clear();\n });\n this.events.clear();\n }\n\n /**\n * add event listener when received data from server.\n */\n public onDataUpdate<T extends SDK.ServerAPI.API | SDK.ServerAPI.APIExtends>(\n api: T,\n body: SDK.ServerAPI.InferRequestBodyType<T, null> | null,\n fn: (response: SDK.ServerAPI.SocketResponseType<T>) => void,\n ) {\n const normalizedBody = body ?? null;\n const key = `${api}::${JSON.stringify(normalizedBody)}`;\n if (!this.events.has(key)) {\n this.events.set(key, {\n api,\n body: normalizedBody,\n listeners: new Set(),\n });\n }\n\n const subscription = this.events.get(key)!;\n if (subscription.listeners.has(fn)) {\n return;\n }\n\n subscription.listeners.add(fn);\n const socketPort = this.get('__SOCKET__PORT__') ?? '';\n subscribeServerAPI(api, normalizedBody, fn, socketPort);\n }\n\n public removeOnDataUpdate<\n T extends SDK.ServerAPI.API | SDK.ServerAPI.APIExtends,\n >(\n api: T,\n body: SDK.ServerAPI.InferRequestBodyType<T, null> | null,\n fn: (response: SDK.ServerAPI.SocketResponseType<T>) => void,\n ) {\n const key = `${api}::${JSON.stringify(body ?? null)}`;\n const socketPort = this.get('__SOCKET__PORT__') ?? '';\n unsubscribeServerAPI(api, body, fn, socketPort);\n this.events.get(key)?.listeners.delete(fn);\n }\n}\n"],"names":["LocalServerDataLoader","BaseDataLoader","key","scope","rest","data","res","ManifestShared","task","postServerAPI","SDK","err","get","args","api","body","JSON","socketPort","requestServerAPI","listeners","listener","fn","normalizedBody","Set","subscription","subscribeServerAPI","unsubscribeServerAPI","Map"],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,89 @@
1
+ import { afterEach, describe, expect, it, rs } from "@rstest/core";
2
+ import { SDK } from "@rsdoctor/types";
3
+ import { LocalServerDataLoader } from "./local.mjs";
4
+ function _define_property(obj, key, value) {
5
+ if (key in obj) Object.defineProperty(obj, key, {
6
+ value: value,
7
+ enumerable: true,
8
+ configurable: true,
9
+ writable: true
10
+ });
11
+ else obj[key] = value;
12
+ return obj;
13
+ }
14
+ class MockWebSocket {
15
+ addEventListener(event, listener) {
16
+ if (!this.listeners.has(event)) this.listeners.set(event, new Set());
17
+ this.listeners.get(event).add(listener);
18
+ }
19
+ send(message) {
20
+ this.sentMessages.push(message);
21
+ }
22
+ trigger(event, data) {
23
+ if ('open' === event) this.readyState = 1;
24
+ this.listeners.get(event)?.forEach((listener)=>listener(void 0 === data ? void 0 : {
25
+ data
26
+ }));
27
+ }
28
+ constructor(url){
29
+ _define_property(this, "url", void 0);
30
+ _define_property(this, "readyState", void 0);
31
+ _define_property(this, "sentMessages", void 0);
32
+ _define_property(this, "listeners", void 0);
33
+ this.url = url;
34
+ this.readyState = 0;
35
+ this.sentMessages = [];
36
+ this.listeners = new Map();
37
+ MockWebSocket.instances.push(this);
38
+ }
39
+ }
40
+ _define_property(MockWebSocket, "instances", []);
41
+ describe('LocalServerDataLoader', ()=>{
42
+ const originalFetch = globalThis.fetch;
43
+ const originalWebSocket = globalThis.WebSocket;
44
+ afterEach(()=>{
45
+ globalThis.fetch = originalFetch;
46
+ globalThis.WebSocket = originalWebSocket;
47
+ MockWebSocket.instances = [];
48
+ rs.restoreAllMocks();
49
+ });
50
+ it("disposes subscriptions when request body strings contain delimiters", ()=>{
51
+ const loader = new LocalServerDataLoader({
52
+ data: {}
53
+ });
54
+ loader.onDataUpdate(SDK.ServerAPI.API.GetModuleByName, {
55
+ name: 'foo::bar'
56
+ }, rs.fn());
57
+ expect(()=>loader.dispose()).not.toThrow();
58
+ });
59
+ it('loads APIs through websocket requests', async ()=>{
60
+ globalThis.WebSocket = MockWebSocket;
61
+ const fetchMock = rs.fn();
62
+ globalThis.fetch = fetchMock;
63
+ const loader = new LocalServerDataLoader({
64
+ data: {},
65
+ __SOCKET__PORT__: '3083'
66
+ });
67
+ const task = loader.loadAPI(SDK.ServerAPI.API.GetAllModuleGraph, {});
68
+ const socket = MockWebSocket.instances[0];
69
+ socket.trigger('open');
70
+ const request = JSON.parse(socket.sentMessages[0]);
71
+ socket.trigger('message', JSON.stringify({
72
+ type: 'response',
73
+ id: request.id,
74
+ payload: [
75
+ {
76
+ id: 1
77
+ }
78
+ ]
79
+ }));
80
+ await expect(task).resolves.toStrictEqual([
81
+ {
82
+ id: 1
83
+ }
84
+ ]);
85
+ expect(fetchMock).not.toHaveBeenCalled();
86
+ });
87
+ });
88
+
89
+ //# sourceMappingURL=local.test.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils/data/local.test.mjs","sources":["../../../src/utils/data/local.test.ts"],"sourcesContent":["import { afterEach, describe, expect, it, rs } from '@rstest/core';\nimport { SDK } from '@rsdoctor/types';\nimport { LocalServerDataLoader } from './local';\n\nclass MockWebSocket {\n static instances: MockWebSocket[] = [];\n\n public readyState = 0;\n\n public sentMessages: string[] = [];\n\n private listeners = new Map<\n string,\n Set<(event?: { data: string }) => void>\n >();\n\n constructor(public url: string) {\n MockWebSocket.instances.push(this);\n }\n\n addEventListener(\n event: string,\n listener: (event?: { data: string }) => void,\n ) {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set());\n }\n this.listeners.get(event)!.add(listener);\n }\n\n send(message: string) {\n this.sentMessages.push(message);\n }\n\n trigger(event: string, data?: string) {\n if (event === 'open') {\n this.readyState = 1;\n }\n this.listeners\n .get(event)\n ?.forEach((listener) =>\n listener(data === undefined ? undefined : { data }),\n );\n }\n}\n\ndescribe('LocalServerDataLoader', () => {\n const originalFetch = globalThis.fetch;\n const originalWebSocket = globalThis.WebSocket;\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n globalThis.WebSocket = originalWebSocket;\n MockWebSocket.instances = [];\n rs.restoreAllMocks();\n });\n\n it('disposes subscriptions when request body strings contain delimiters', () => {\n const loader = new LocalServerDataLoader({\n data: {},\n } as any);\n\n loader.onDataUpdate(\n SDK.ServerAPI.API.GetModuleByName,\n { name: 'foo::bar' } as any,\n rs.fn(),\n );\n\n expect(() => loader.dispose()).not.toThrow();\n });\n\n it('loads APIs through websocket requests', async () => {\n globalThis.WebSocket = MockWebSocket as any;\n const fetchMock = rs.fn();\n globalThis.fetch = fetchMock as typeof fetch;\n const loader = new LocalServerDataLoader({\n data: {},\n __SOCKET__PORT__: '3083',\n } as any);\n\n const task = loader.loadAPI(SDK.ServerAPI.API.GetAllModuleGraph, {} as any);\n const socket = MockWebSocket.instances[0];\n socket.trigger('open');\n const request = JSON.parse(socket.sentMessages[0]);\n\n socket.trigger(\n 'message',\n JSON.stringify({\n type: 'response',\n id: request.id,\n payload: [{ id: 1 }],\n }),\n );\n\n await expect(task).resolves.toStrictEqual([{ id: 1 }]);\n expect(fetchMock).not.toHaveBeenCalled();\n });\n});\n"],"names":["MockWebSocket","event","listener","Set","message","data","undefined","url","Map","describe","originalFetch","globalThis","originalWebSocket","afterEach","rs","it","loader","LocalServerDataLoader","SDK","expect","fetchMock","task","socket","request","JSON"],"mappings":";;;;;;;;;;;;;AAIA,MAAMA;IAgBJ,iBACEC,KAAa,EACbC,QAA4C,EAC5C;QACA,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAACD,QACtB,IAAI,CAAC,SAAS,CAAC,GAAG,CAACA,OAAO,IAAIE;QAEhC,IAAI,CAAC,SAAS,CAAC,GAAG,CAACF,OAAQ,GAAG,CAACC;IACjC;IAEA,KAAKE,OAAe,EAAE;QACpB,IAAI,CAAC,YAAY,CAAC,IAAI,CAACA;IACzB;IAEA,QAAQH,KAAa,EAAEI,IAAa,EAAE;QACpC,IAAIJ,AAAU,WAAVA,OACF,IAAI,CAAC,UAAU,GAAG;QAEpB,IAAI,CAAC,SAAS,CACX,GAAG,CAACA,QACH,QAAQ,CAACC,WACTA,SAASG,AAASC,WAATD,OAAqBC,SAAY;gBAAED;YAAK;IAEvD;IA3BA,YAAmBE,GAAW,CAAE;;QAThC,uBAAO,cAAP;QAEA,uBAAO,gBAAP;QAEA,uBAAQ,aAAR;aAKmBA,GAAG,GAAHA;aATZ,UAAU,GAAG;aAEb,YAAY,GAAa,EAAE;aAE1B,SAAS,GAAG,IAAIC;QAMtBR,cAAc,SAAS,CAAC,IAAI,CAAC,IAAI;IACnC;AA0BF;AAvCE,iBADIA,eACG,aAA6B,EAAE;AAyCxCS,SAAS,yBAAyB;IAChC,MAAMC,gBAAgBC,WAAW,KAAK;IACtC,MAAMC,oBAAoBD,WAAW,SAAS;IAE9CE,UAAU;QACRF,WAAW,KAAK,GAAGD;QACnBC,WAAW,SAAS,GAAGC;QACvBZ,cAAc,SAAS,GAAG,EAAE;QAC5Bc,GAAG,eAAe;IACpB;IAEAC,GAAG,uEAAuE;QACxE,MAAMC,SAAS,IAAIC,sBAAsB;YACvC,MAAM,CAAC;QACT;QAEAD,OAAO,YAAY,CACjBE,IAAI,SAAS,CAAC,GAAG,CAAC,eAAe,EACjC;YAAE,MAAM;QAAW,GACnBJ,GAAG,EAAE;QAGPK,OAAO,IAAMH,OAAO,OAAO,IAAI,GAAG,CAAC,OAAO;IAC5C;IAEAD,GAAG,yCAAyC;QAC1CJ,WAAW,SAAS,GAAGX;QACvB,MAAMoB,YAAYN,GAAG,EAAE;QACvBH,WAAW,KAAK,GAAGS;QACnB,MAAMJ,SAAS,IAAIC,sBAAsB;YACvC,MAAM,CAAC;YACP,kBAAkB;QACpB;QAEA,MAAMI,OAAOL,OAAO,OAAO,CAACE,IAAI,SAAS,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;QAClE,MAAMI,SAAStB,cAAc,SAAS,CAAC,EAAE;QACzCsB,OAAO,OAAO,CAAC;QACf,MAAMC,UAAUC,KAAK,KAAK,CAACF,OAAO,YAAY,CAAC,EAAE;QAEjDA,OAAO,OAAO,CACZ,WACAE,KAAK,SAAS,CAAC;YACb,MAAM;YACN,IAAID,QAAQ,EAAE;YACd,SAAS;gBAAC;oBAAE,IAAI;gBAAE;aAAE;QACtB;QAGF,MAAMJ,OAAOE,MAAM,QAAQ,CAAC,aAAa,CAAC;YAAC;gBAAE,IAAI;YAAE;SAAE;QACrDF,OAAOC,WAAW,GAAG,CAAC,gBAAgB;IACxC;AACF"}
@@ -11,13 +11,13 @@ export type DataNode = FieldDataNode<{
11
11
  };
12
12
  export declare const rootDirname: (file: string, sep?: string) => string | null;
13
13
  export declare function mapFileKey(arr: DataNode[], depth?: number, filter?: (node: DataNode) => boolean): DataNode['key'][];
14
- export declare function flattenDirectory(n: DataNode, parent: DataNode, sep: string | undefined, inlinedResourcePathKey: keyof DataNode, dirTitle?: (_dir: DataNode, defaultTitle: string) => JSX.Element | string): void;
14
+ export declare function flattenDirectory(n: DataNode, parent: DataNode, sep: string | undefined, inlinedResourcePathKey: keyof DataNode, dirTitle?: (_dir: DataNode, defaultTitle: string) => React.JSX.Element | string): void;
15
15
  export declare function createFileStructures({ files, inlinedResourcePathKey, fileTitle, dirTitle, page, }: {
16
16
  files: string[];
17
17
  cwd?: string;
18
18
  inlinedResourcePathKey?: keyof DataNode;
19
- dirTitle?(dir: DataNode, defaultTitle: string): JSX.Element | string;
20
- fileTitle?(file: string, basename: string): JSX.Element | string;
19
+ dirTitle?(dir: DataNode, defaultTitle: string): React.JSX.Element | string;
20
+ fileTitle?(file: string, basename: string): React.JSX.Element | string;
21
21
  page?: 'bundle' | 'other';
22
22
  }): DataNode[];
23
23
  export declare function beautifyPath(path: string, cwd: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"utils/file.mjs","sources":["../../src/utils/file.tsx"],"sourcesContent":["import { get } from 'es-toolkit/compat';\nimport { Common, SDK } from '@rsdoctor/types';\nimport { message, Space, TreeNodeProps, UploadFile } from 'antd';\nimport { FieldDataNode } from 'rc-tree';\nimport {\n FolderOpenTwoTone,\n FolderTwoTone,\n FileOutlined,\n RightOutlined,\n} from '@ant-design/icons';\nimport { getFileCom } from 'src/components/FileTree';\n\nexport type DataNode = FieldDataNode<{\n key: string | number;\n title?: React.ReactNode | ((data: DataNode) => React.ReactNode);\n}> & { __BASENAME__?: any; __RESOURCEPATH__?: any; children?: DataNode[] };\n\nexport const rootDirname = (file: string, sep = '/'): string | null => {\n const idx = file?.indexOf(sep);\n if (idx === -1) {\n return null;\n }\n if (idx === 0) {\n return sep + (rootDirname(file?.slice(1), sep) || '');\n }\n return file?.slice(0, idx);\n};\n\nexport function mapFileKey(\n arr: DataNode[],\n depth = 2,\n filter: (node: DataNode) => boolean = () => true,\n): DataNode['key'][] {\n let d = 0;\n const res: DataNode['key'][] = [];\n let parent: DataNode[] = arr;\n while (d < depth) {\n parent.filter(filter).forEach((e) => {\n if (!e.isLeaf) {\n res.push(e.key);\n }\n });\n parent = parent.reduce<DataNode[]>(\n (t, e) => t.concat(e.children || []),\n [],\n );\n if (!parent.length) break;\n d++;\n }\n return res;\n}\n\nconst basenameKey = '__BASENAME__';\n\nexport function flattenDirectory(\n n: DataNode,\n parent: DataNode,\n sep = '/',\n inlinedResourcePathKey: keyof DataNode,\n dirTitle = (_dir: DataNode, defaultTitle: string): JSX.Element | string =>\n defaultTitle,\n) {\n if (n.isLeaf) return;\n if (parent.children && parent.children.length === 1) {\n const defaultTitle = [parent[basenameKey], n[basenameKey]].join(sep);\n parent[inlinedResourcePathKey] = n[inlinedResourcePathKey];\n parent[basenameKey] = defaultTitle;\n parent.key = [parent.key, n.key].join('-');\n parent.children = n.children;\n parent.title = dirTitle(parent, defaultTitle);\n\n if (n.children) {\n n.children.forEach((c) => {\n flattenDirectory(c, parent, sep, inlinedResourcePathKey, dirTitle);\n });\n }\n } else {\n // parent has more than 1 child.\n n.title = dirTitle(n, n[basenameKey]);\n\n if (n.children) {\n n.children.forEach((c) => {\n flattenDirectory(c, n, sep, inlinedResourcePathKey, dirTitle);\n });\n }\n }\n}\n\nexport function createFileStructures({\n files,\n inlinedResourcePathKey = '__RESOURCEPATH__',\n fileTitle = (_file: string, basename: string) => basename,\n dirTitle = (_dir: DataNode, defaultTitle: string) => defaultTitle,\n page = 'other',\n}: {\n files: string[];\n cwd?: string;\n inlinedResourcePathKey?: keyof DataNode;\n dirTitle?(dir: DataNode, defaultTitle: string): JSX.Element | string;\n fileTitle?(file: string, basename: string): JSX.Element | string;\n page?: 'bundle' | 'other';\n}): DataNode[] {\n // Normalize all paths to use forward slash as internal separator for consistency\n // This ensures Windows paths (using backslash) are properly converted to forward slashes\n const normalizedFiles = files.map((file) => {\n // Always convert backslashes to forward slashes for internal processing\n return file.replace(/\\\\/g, '/');\n });\n\n // Use forward slash as the internal separator for consistency\n const internalSep = '/';\n const sepRegexp = new RegExp(internalSep);\n\n const res = normalizedFiles.reduce<DataNode>(\n (t, file) => {\n let dir = rootDirname(file, internalSep);\n let basename = dir ? file?.slice(dir.length + 1) : file;\n let parent: DataNode = t;\n\n while (dir) {\n // find the match directory.\n let exist = parent.children!.find((e) => e.title === dir) as DataNode;\n if (!exist) {\n const p = [parent[inlinedResourcePathKey], dir]\n .filter(Boolean)\n .join(internalSep);\n exist = {\n title: dir,\n icon:\n page === 'bundle'\n ? (props) => getFileIcon(props as TreeNodeProps, false)\n : null,\n // key: [parent.key, parent.children!.length].join('-'),\n key: p,\n children: [],\n [inlinedResourcePathKey]: p,\n [basenameKey]: dir,\n };\n parent.children!.push(exist);\n }\n\n parent = exist;\n dir = rootDirname(basename, internalSep);\n basename = dir\n ? basename.slice(dir.length).replace(sepRegexp, '')\n : basename;\n }\n\n // uniq\n if (parent.children!.some((e) => get(e, inlinedResourcePathKey) === file))\n return t;\n\n parent.children!.push({\n title() {\n return fileTitle(file, basename);\n },\n icon:\n page === 'bundle'\n ? (props) => getFileIcon(props as TreeNodeProps)\n : null,\n key: file,\n isLeaf: true,\n [inlinedResourcePathKey]: file,\n [basenameKey]: basename,\n });\n\n return t;\n },\n { key: '0', children: [] },\n ).children!;\n\n res.forEach((e) => {\n if (e.children) {\n e.children.forEach((item) =>\n flattenDirectory(\n item,\n e,\n internalSep,\n inlinedResourcePathKey,\n dirTitle,\n ),\n );\n }\n });\n\n return res;\n}\n\nexport function beautifyPath(path: string, cwd: string) {\n if (path.startsWith(cwd)) {\n return path.replace(cwd, '.');\n }\n\n return path;\n}\n\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: UploadFile,\n): Promise<T>;\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: Blob,\n): Promise<T>;\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: unknown,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const { result } = reader;\n try {\n const json = JSON.parse(result!.toString());\n resolve(json);\n } catch (err) {\n message.error('json parse error');\n reject(err);\n }\n };\n reader.onerror = () => {\n const msg = 'upload json file error, please try again.';\n message.error(msg);\n reject(new Error(msg));\n };\n reader.readAsText(((file as UploadFile).originFileObj || file) as Blob);\n });\n}\n\n/**\n * beautify module path, will replace cwd & last 'node_modules'\n */\nexport function beautifyModulePath(modulePath: string, cwd: string) {\n const res = beautifyPath(modulePath, cwd);\n\n const str = '/node_modules/';\n\n const idx = res.lastIndexOf(str);\n\n if (idx > -1) {\n return {\n alias: res.slice(idx + str.length),\n inNodeModules: true,\n };\n }\n\n return {\n alias: res,\n inNodeModules: false,\n };\n}\n\nexport function getFileIcon(props: TreeNodeProps, addRowIcon = true) {\n const { data } = props;\n const expanded = props.expanded;\n if (data?.children) {\n return (\n <Space>\n {addRowIcon ? (\n <RightOutlined\n className={`file-tree-switcher-arrow ${expanded ? 'file-tree-switcher-arrow-expand' : ''}`}\n />\n ) : (\n <></>\n )}\n {expanded ? <FolderOpenTwoTone /> : <FolderTwoTone />}\n </Space>\n );\n }\n if (props.eventKey && typeof props.eventKey === 'string') {\n return getFileCom(props.eventKey);\n }\n return <FileOutlined />;\n}\n\ntype TreeNode = {\n name: string;\n value?: number;\n children?: TreeNode[];\n path?: string;\n sourceSize?: number;\n bundledSize?: number;\n gzipSize?: number;\n id?: string | number;\n // Internal helper, not exported\n _map?: Map<string, TreeNode>;\n};\n\nexport function buildTreemapData(\n modules: SDK.ModuleData[],\n rootName = 'dist',\n): TreeNode {\n const root: TreeNode = { name: rootName, children: [], _map: new Map() };\n\n for (const mod of modules) {\n const parts = mod.path.split(/[\\\\/]/).filter(Boolean);\n let current = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (i === parts.length - 1) {\n // File node\n if (!current.children) current.children = [];\n current.children.push({\n name: part,\n path: mod.path,\n sourceSize: mod.size?.sourceSize ?? 0,\n bundledSize: mod.size?.parsedSize ?? 0,\n gzipSize: mod.size?.gzipSize ?? 0,\n id: mod.id,\n });\n } else {\n // Directory node\n if (!current._map) current._map = new Map();\n let child = current._map.get(part);\n if (!child) {\n child = { name: part, children: [], _map: new Map() };\n current.children!.push(child);\n current._map.set(part, child);\n }\n current = child;\n }\n }\n }\n\n // Clean up _map property\n function clean(node: TreeNode) {\n delete node._map;\n if (node.children) node.children.forEach(clean);\n }\n clean(root);\n\n return root;\n}\n\nfunction flattenSingleChildDirs(node: TreeNode): TreeNode {\n // Return directly if leaf node\n if (!node.children || node.children.length === 0) return node;\n\n let current = node;\n // As long as children has only one child and it's not a leaf, merge\n while (\n current.children &&\n current.children.length === 1 &&\n !current.children[0].sourceSize // Not a leaf\n ) {\n current = {\n name: current.name + '/' + current.children[0].name,\n children: current.children[0].children,\n };\n }\n\n // Recursively process all child nodes\n if (current.children) {\n current.children = current.children.map(flattenSingleChildDirs);\n }\n return current;\n}\n\nfunction sumDirValue(node: TreeNode): {\n sourceSize: number;\n bundledSize: number;\n gzipSize: number;\n} {\n if (!node.children || node.children.length === 0) {\n // Leaf node, just return value\n return {\n sourceSize: node.sourceSize ?? 0,\n bundledSize: node.bundledSize ?? 0,\n gzipSize: node.gzipSize ?? 0,\n };\n }\n // Recursively sum all child nodes\n let sourceSum = 0;\n let bundledSum = 0;\n let gzipSum = 0;\n for (const child of node.children) {\n const { sourceSize, bundledSize, gzipSize } = sumDirValue(child);\n sourceSum += sourceSize;\n bundledSum += bundledSize;\n gzipSum += gzipSize;\n }\n node.sourceSize = sourceSum;\n node.bundledSize = bundledSum;\n node.gzipSize = gzipSum;\n return { sourceSize: sourceSum, bundledSize: bundledSum, gzipSize: gzipSum };\n}\n\nexport function flattenTreemapData(\n modules: SDK.ModuleData[],\n rootName = 'dist',\n): TreeNode {\n const rawTree = buildTreemapData(modules, rootName);\n const flattenedTree = flattenSingleChildDirs(rawTree);\n sumDirValue(flattenedTree); // Recursive sum\n return flattenedTree;\n}\n"],"names":["rootDirname","file","sep","idx","mapFileKey","arr","depth","filter","d","res","parent","e","t","basenameKey","flattenDirectory","n","inlinedResourcePathKey","dirTitle","_dir","defaultTitle","c","createFileStructures","files","fileTitle","_file","basename","page","normalizedFiles","internalSep","sepRegexp","RegExp","dir","exist","p","Boolean","props","getFileIcon","get","item","beautifyPath","path","cwd","readJSONByFileReader","Promise","resolve","reject","reader","FileReader","result","json","JSON","err","message","msg","Error","beautifyModulePath","modulePath","str","addRowIcon","data","expanded","Space","RightOutlined","FolderOpenTwoTone","FolderTwoTone","getFileCom","FileOutlined","buildTreemapData","modules","rootName","root","Map","mod","parts","current","i","part","child","clean","node","flattenSingleChildDirs","sumDirValue","sourceSum","bundledSum","gzipSum","sourceSize","bundledSize","gzipSize","flattenTreemapData","rawTree","flattenedTree"],"mappings":"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"}
1
+ {"version":3,"file":"utils/file.mjs","sources":["../../src/utils/file.tsx"],"sourcesContent":["import { get } from 'es-toolkit/compat';\nimport { Common, SDK } from '@rsdoctor/types';\nimport { message, Space, TreeNodeProps, UploadFile } from 'antd';\nimport { FieldDataNode } from 'rc-tree';\nimport {\n FolderOpenTwoTone,\n FolderTwoTone,\n FileOutlined,\n RightOutlined,\n} from '@ant-design/icons';\nimport { getFileCom } from 'src/components/FileTree';\n\nexport type DataNode = FieldDataNode<{\n key: string | number;\n title?: React.ReactNode | ((data: DataNode) => React.ReactNode);\n}> & { __BASENAME__?: any; __RESOURCEPATH__?: any; children?: DataNode[] };\n\nexport const rootDirname = (file: string, sep = '/'): string | null => {\n const idx = file?.indexOf(sep);\n if (idx === -1) {\n return null;\n }\n if (idx === 0) {\n return sep + (rootDirname(file?.slice(1), sep) || '');\n }\n return file?.slice(0, idx);\n};\n\nexport function mapFileKey(\n arr: DataNode[],\n depth = 2,\n filter: (node: DataNode) => boolean = () => true,\n): DataNode['key'][] {\n let d = 0;\n const res: DataNode['key'][] = [];\n let parent: DataNode[] = arr;\n while (d < depth) {\n parent.filter(filter).forEach((e) => {\n if (!e.isLeaf) {\n res.push(e.key);\n }\n });\n parent = parent.reduce<DataNode[]>(\n (t, e) => t.concat(e.children || []),\n [],\n );\n if (!parent.length) break;\n d++;\n }\n return res;\n}\n\nconst basenameKey = '__BASENAME__';\n\nexport function flattenDirectory(\n n: DataNode,\n parent: DataNode,\n sep = '/',\n inlinedResourcePathKey: keyof DataNode,\n dirTitle = (\n _dir: DataNode,\n defaultTitle: string,\n ): React.JSX.Element | string => defaultTitle,\n) {\n if (n.isLeaf) return;\n if (parent.children && parent.children.length === 1) {\n const defaultTitle = [parent[basenameKey], n[basenameKey]].join(sep);\n parent[inlinedResourcePathKey] = n[inlinedResourcePathKey];\n parent[basenameKey] = defaultTitle;\n parent.key = [parent.key, n.key].join('-');\n parent.children = n.children;\n parent.title = dirTitle(parent, defaultTitle);\n\n if (n.children) {\n n.children.forEach((c) => {\n flattenDirectory(c, parent, sep, inlinedResourcePathKey, dirTitle);\n });\n }\n } else {\n // parent has more than 1 child.\n n.title = dirTitle(n, n[basenameKey]);\n\n if (n.children) {\n n.children.forEach((c) => {\n flattenDirectory(c, n, sep, inlinedResourcePathKey, dirTitle);\n });\n }\n }\n}\n\nexport function createFileStructures({\n files,\n inlinedResourcePathKey = '__RESOURCEPATH__',\n fileTitle = (_file: string, basename: string) => basename,\n dirTitle = (_dir: DataNode, defaultTitle: string) => defaultTitle,\n page = 'other',\n}: {\n files: string[];\n cwd?: string;\n inlinedResourcePathKey?: keyof DataNode;\n dirTitle?(dir: DataNode, defaultTitle: string): React.JSX.Element | string;\n fileTitle?(file: string, basename: string): React.JSX.Element | string;\n page?: 'bundle' | 'other';\n}): DataNode[] {\n // Normalize all paths to use forward slash as internal separator for consistency\n // This ensures Windows paths (using backslash) are properly converted to forward slashes\n const normalizedFiles = files.map((file) => {\n // Always convert backslashes to forward slashes for internal processing\n return file.replace(/\\\\/g, '/');\n });\n\n // Use forward slash as the internal separator for consistency\n const internalSep = '/';\n const sepRegexp = new RegExp(internalSep);\n\n const res = normalizedFiles.reduce<DataNode>(\n (t, file) => {\n let dir = rootDirname(file, internalSep);\n let basename = dir ? file?.slice(dir.length + 1) : file;\n let parent: DataNode = t;\n\n while (dir) {\n // find the match directory.\n let exist = parent.children!.find((e) => e.title === dir) as DataNode;\n if (!exist) {\n const p = [parent[inlinedResourcePathKey], dir]\n .filter(Boolean)\n .join(internalSep);\n exist = {\n title: dir,\n icon:\n page === 'bundle'\n ? (props) => getFileIcon(props as TreeNodeProps, false)\n : null,\n // key: [parent.key, parent.children!.length].join('-'),\n key: p,\n children: [],\n [inlinedResourcePathKey]: p,\n [basenameKey]: dir,\n };\n parent.children!.push(exist);\n }\n\n parent = exist;\n dir = rootDirname(basename, internalSep);\n basename = dir\n ? basename.slice(dir.length).replace(sepRegexp, '')\n : basename;\n }\n\n // uniq\n if (parent.children!.some((e) => get(e, inlinedResourcePathKey) === file))\n return t;\n\n parent.children!.push({\n title() {\n return fileTitle(file, basename);\n },\n icon:\n page === 'bundle'\n ? (props) => getFileIcon(props as TreeNodeProps)\n : null,\n key: file,\n isLeaf: true,\n [inlinedResourcePathKey]: file,\n [basenameKey]: basename,\n });\n\n return t;\n },\n { key: '0', children: [] },\n ).children!;\n\n res.forEach((e) => {\n if (e.children) {\n e.children.forEach((item) =>\n flattenDirectory(\n item,\n e,\n internalSep,\n inlinedResourcePathKey,\n dirTitle,\n ),\n );\n }\n });\n\n return res;\n}\n\nexport function beautifyPath(path: string, cwd: string) {\n if (path.startsWith(cwd)) {\n return path.replace(cwd, '.');\n }\n\n return path;\n}\n\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: UploadFile,\n): Promise<T>;\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: Blob,\n): Promise<T>;\nexport function readJSONByFileReader<T extends Common.PlainObject>(\n file: unknown,\n): Promise<T> {\n return new Promise((resolve, reject) => {\n const reader = new FileReader();\n reader.onloadend = () => {\n const { result } = reader;\n try {\n const json = JSON.parse(result!.toString());\n resolve(json);\n } catch (err) {\n message.error('json parse error');\n reject(err);\n }\n };\n reader.onerror = () => {\n const msg = 'upload json file error, please try again.';\n message.error(msg);\n reject(new Error(msg));\n };\n reader.readAsText(((file as UploadFile).originFileObj || file) as Blob);\n });\n}\n\n/**\n * beautify module path, will replace cwd & last 'node_modules'\n */\nexport function beautifyModulePath(modulePath: string, cwd: string) {\n const res = beautifyPath(modulePath, cwd);\n\n const str = '/node_modules/';\n\n const idx = res.lastIndexOf(str);\n\n if (idx > -1) {\n return {\n alias: res.slice(idx + str.length),\n inNodeModules: true,\n };\n }\n\n return {\n alias: res,\n inNodeModules: false,\n };\n}\n\nexport function getFileIcon(props: TreeNodeProps, addRowIcon = true) {\n const { data } = props;\n const expanded = props.expanded;\n if (data?.children) {\n return (\n <Space>\n {addRowIcon ? (\n <RightOutlined\n className={`file-tree-switcher-arrow ${expanded ? 'file-tree-switcher-arrow-expand' : ''}`}\n />\n ) : (\n <></>\n )}\n {expanded ? <FolderOpenTwoTone /> : <FolderTwoTone />}\n </Space>\n );\n }\n if (props.eventKey && typeof props.eventKey === 'string') {\n return getFileCom(props.eventKey);\n }\n return <FileOutlined />;\n}\n\ntype TreeNode = {\n name: string;\n value?: number;\n children?: TreeNode[];\n path?: string;\n sourceSize?: number;\n bundledSize?: number;\n gzipSize?: number;\n id?: string | number;\n // Internal helper, not exported\n _map?: Map<string, TreeNode>;\n};\n\nexport function buildTreemapData(\n modules: SDK.ModuleData[],\n rootName = 'dist',\n): TreeNode {\n const root: TreeNode = { name: rootName, children: [], _map: new Map() };\n\n for (const mod of modules) {\n const parts = mod.path.split(/[\\\\/]/).filter(Boolean);\n let current = root;\n\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n if (i === parts.length - 1) {\n // File node\n if (!current.children) current.children = [];\n current.children.push({\n name: part,\n path: mod.path,\n sourceSize: mod.size?.sourceSize ?? 0,\n bundledSize: mod.size?.parsedSize ?? 0,\n gzipSize: mod.size?.gzipSize ?? 0,\n id: mod.id,\n });\n } else {\n // Directory node\n if (!current._map) current._map = new Map();\n let child = current._map.get(part);\n if (!child) {\n child = { name: part, children: [], _map: new Map() };\n current.children!.push(child);\n current._map.set(part, child);\n }\n current = child;\n }\n }\n }\n\n // Clean up _map property\n function clean(node: TreeNode) {\n delete node._map;\n if (node.children) node.children.forEach(clean);\n }\n clean(root);\n\n return root;\n}\n\nfunction flattenSingleChildDirs(node: TreeNode): TreeNode {\n // Return directly if leaf node\n if (!node.children || node.children.length === 0) return node;\n\n let current = node;\n // As long as children has only one child and it's not a leaf, merge\n while (\n current.children &&\n current.children.length === 1 &&\n !current.children[0].sourceSize // Not a leaf\n ) {\n current = {\n name: current.name + '/' + current.children[0].name,\n children: current.children[0].children,\n };\n }\n\n // Recursively process all child nodes\n if (current.children) {\n current.children = current.children.map(flattenSingleChildDirs);\n }\n return current;\n}\n\nfunction sumDirValue(node: TreeNode): {\n sourceSize: number;\n bundledSize: number;\n gzipSize: number;\n} {\n if (!node.children || node.children.length === 0) {\n // Leaf node, just return value\n return {\n sourceSize: node.sourceSize ?? 0,\n bundledSize: node.bundledSize ?? 0,\n gzipSize: node.gzipSize ?? 0,\n };\n }\n // Recursively sum all child nodes\n let sourceSum = 0;\n let bundledSum = 0;\n let gzipSum = 0;\n for (const child of node.children) {\n const { sourceSize, bundledSize, gzipSize } = sumDirValue(child);\n sourceSum += sourceSize;\n bundledSum += bundledSize;\n gzipSum += gzipSize;\n }\n node.sourceSize = sourceSum;\n node.bundledSize = bundledSum;\n node.gzipSize = gzipSum;\n return { sourceSize: sourceSum, bundledSize: bundledSum, gzipSize: gzipSum };\n}\n\nexport function flattenTreemapData(\n modules: SDK.ModuleData[],\n rootName = 'dist',\n): TreeNode {\n const rawTree = buildTreemapData(modules, rootName);\n const flattenedTree = flattenSingleChildDirs(rawTree);\n sumDirValue(flattenedTree); // Recursive sum\n return flattenedTree;\n}\n"],"names":["rootDirname","file","sep","idx","mapFileKey","arr","depth","filter","d","res","parent","e","t","basenameKey","flattenDirectory","n","inlinedResourcePathKey","dirTitle","_dir","defaultTitle","c","createFileStructures","files","fileTitle","_file","basename","page","normalizedFiles","internalSep","sepRegexp","RegExp","dir","exist","p","Boolean","props","getFileIcon","get","item","beautifyPath","path","cwd","readJSONByFileReader","Promise","resolve","reject","reader","FileReader","result","json","JSON","err","message","msg","Error","beautifyModulePath","modulePath","str","addRowIcon","data","expanded","Space","RightOutlined","FolderOpenTwoTone","FolderTwoTone","getFileCom","FileOutlined","buildTreemapData","modules","rootName","root","Map","mod","parts","current","i","part","child","clean","node","flattenSingleChildDirs","sumDirValue","sourceSum","bundledSum","gzipSum","sourceSize","bundledSize","gzipSize","flattenTreemapData","rawTree","flattenedTree"],"mappings":"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"}
@@ -25,6 +25,6 @@ export declare function useDuplicatePackagesByManifest(manifest: Manifest.Rsdoct
25
25
  export declare function useCompileAlertsByErrors(errors: Manifest.RsdoctorManifestData['errors']): Rule.RuleStoreDataItem[];
26
26
  export declare function useBundleAlertsByErrors(errors: Manifest.RsdoctorManifestData['errors']): Rule.RuleStoreDataItem[];
27
27
  export declare function useDuplicatePackagesByErrors(errors: Manifest.RsdoctorManifestData['errors']): Rule.PackageRelationDiffRuleStoreData[];
28
- export declare function useWebpackConfigurationByConfigs(configs?: SDK.ConfigData): SDK.WebpackConfigData | null | undefined;
28
+ export declare function useWebpackConfigurationByConfigs(configs?: SDK.ConfigData): SDK.BundlerConfigData | null | undefined;
29
29
  export declare function useDetectIfCloudIdeEnv(): boolean;
30
30
  export declare function useWindowWidth(): number;
@@ -77,14 +77,15 @@ async function fetchManifest(url = getManifestUrl()) {
77
77
  async function postServerAPI(...args) {
78
78
  const [api, body] = args;
79
79
  const timeout = 'development' === process.env.NODE_ENV ? 10000 : 60000;
80
- const res = await Fetch.fetchWithTimeout(resolveRequestUrl(`${api}?_t=${random()}`), {
80
+ const requestInit = {
81
81
  method: 'POST',
82
82
  headers: {
83
83
  'Content-Type': 'application/json'
84
84
  },
85
- body: void 0 === body ? void 0 : JSON.stringify(body),
86
85
  timeout
87
- });
86
+ };
87
+ if (null != body) requestInit.body = JSON.stringify(body);
88
+ const res = await Fetch.fetchWithTimeout(resolveRequestUrl(`${api}?_t=${random()}`), requestInit);
88
89
  return await res.json();
89
90
  }
90
91
  export { fetchJSONByUrl, fetchJSONByUrls, fetchManifest, fetchShardingFile, getManifestUrl, loadManifestByUrl, parseManifest, postServerAPI };
@@ -1 +1 @@
1
- {"version":3,"file":"utils/request.mjs","sources":["../../src/utils/request.ts"],"sourcesContent":["import { Manifest, SDK } from '@rsdoctor/types';\nimport { Fetch, Manifest as ManifestMethod, Url } from '@rsdoctor/utils/common';\nimport { APILoaderMode4Dev } from '../constants';\nimport { getManifestUrlFromUrlQuery } from './url';\nimport { getAPILoaderModeFromStorage } from './storage';\n\nfunction random() {\n return `${Date.now()}${Math.floor(Math.random() * 10000)}`;\n}\n\nfunction resolveRequestUrl(url: string): string {\n if (\n process.env.NODE_ENV === 'development' &&\n getAPILoaderModeFromStorage() === APILoaderMode4Dev.Local &&\n url.startsWith('/')\n ) {\n const nextUrl =\n url === manifestUrlForDev ? SDK.ServerAPI.API.Manifest : url;\n const currentUrl = new URL(location.href);\n currentUrl.port = String(process.env.LOCAL_CLI_PORT!);\n return `${currentUrl.origin}${nextUrl}`;\n }\n\n return url;\n}\n\nasync function requestText(url: string, timeout: number) {\n const res = await Fetch.fetchWithTimeout(resolveRequestUrl(url), { timeout });\n return res.text();\n}\n\nexport async function fetchShardingFile(url: string): Promise<string> {\n if (Url.isUrl(url)) {\n return requestText(url, 999999);\n }\n // json string\n return url;\n}\n\nexport async function loadManifestByUrl(url: string) {\n const json = await fetchJSONByUrl(url);\n\n const res = await parseManifest(json);\n return res;\n}\n\nexport async function fetchJSONByUrl(url: string) {\n let json: unknown = await requestText(url, 30000);\n\n if (typeof json === 'string') {\n const trimmed = json.trim();\n // If we got an HTML document (usually error page / SPA fallback), skip JSON.parse\n if (/^<!doctype html\\b/i.test(trimmed) || /^<html\\b/i.test(trimmed)) {\n json = {} as Manifest.RsdoctorManifestWithShardingFiles;\n } else {\n json = JSON.parse(json);\n }\n }\n\n return json as Manifest.RsdoctorManifestWithShardingFiles;\n}\n\nexport function fetchJSONByUrls(urls: string[]) {\n return Promise.all(urls.map((url) => fetchJSONByUrl(url)));\n}\n\nexport async function parseManifest(\n json: Manifest.RsdoctorManifestWithShardingFiles,\n) {\n let transformedData: Manifest.RsdoctorManifestData;\n\n try {\n // try to load cloud data first\n if (json.cloudData) {\n try {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.cloudData,\n fetchShardingFile,\n );\n } catch (error) {\n console.log('cloudData load error: ', error);\n }\n } else {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.data,\n fetchShardingFile,\n );\n }\n } catch {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.data,\n fetchShardingFile,\n );\n }\n\n return {\n ...json,\n data: transformedData!,\n };\n}\n\nconst manifestUrlForDev = '/manifest.json';\n\nexport function getManifestUrl(): string {\n let file: string | void;\n\n if (\n (window as { [key: string]: any })[\n Manifest.RsdoctorManifestClientConstant.WindowPropertyForManifestUrl\n ]\n ) {\n // load from window property\n file = (window as { [key: string]: any })[\n Manifest.RsdoctorManifestClientConstant.WindowPropertyForManifestUrl\n ];\n } else {\n // load from url query\n file = getManifestUrlFromUrlQuery();\n }\n\n if (!file) {\n file = SDK.ServerAPI.API.Manifest;\n }\n\n return file;\n}\n\nconst pool = new Map<\n string,\n Promise<Manifest.RsdoctorManifestWithShardingFiles>\n>();\n\nexport async function fetchManifest(url = getManifestUrl()) {\n if (!pool.has(url)) {\n pool.set(\n url,\n fetchJSONByUrl(url).catch((err) => {\n pool.delete(url);\n throw err;\n }),\n );\n }\n\n const res = await pool.get(url)!;\n\n return res;\n}\n\nexport async function postServerAPI<\n T extends SDK.ServerAPI.API,\n B extends SDK.ServerAPI.InferRequestBodyType<T> =\n SDK.ServerAPI.InferRequestBodyType<T>,\n R extends SDK.ServerAPI.InferResponseType<T> =\n SDK.ServerAPI.InferResponseType<T>,\n>(...args: B extends void ? [api: T] : [api: T, body: B]): Promise<R> {\n const [api, body] = args;\n const timeout = process.env.NODE_ENV === 'development' ? 10000 : 60000;\n const res = await Fetch.fetchWithTimeout(\n resolveRequestUrl(`${api}?_t=${random()}`),\n {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: body === undefined ? undefined : JSON.stringify(body),\n timeout,\n },\n );\n return (await res.json()) as R;\n}\n"],"names":["random","Date","Math","resolveRequestUrl","url","process","getAPILoaderModeFromStorage","APILoaderMode4Dev","nextUrl","manifestUrlForDev","SDK","currentUrl","URL","location","String","requestText","timeout","res","Fetch","fetchShardingFile","Url","loadManifestByUrl","json","fetchJSONByUrl","parseManifest","trimmed","JSON","fetchJSONByUrls","urls","Promise","transformedData","ManifestMethod","error","console","getManifestUrl","file","window","Manifest","getManifestUrlFromUrlQuery","pool","Map","fetchManifest","err","postServerAPI","args","api","body","undefined"],"mappings":"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"}
1
+ {"version":3,"file":"utils/request.mjs","sources":["../../src/utils/request.ts"],"sourcesContent":["import { Manifest, SDK } from '@rsdoctor/types';\nimport { Fetch, Manifest as ManifestMethod, Url } from '@rsdoctor/utils/common';\nimport { APILoaderMode4Dev } from '../constants';\nimport { getManifestUrlFromUrlQuery } from './url';\nimport { getAPILoaderModeFromStorage } from './storage';\n\nfunction random() {\n return `${Date.now()}${Math.floor(Math.random() * 10000)}`;\n}\n\nfunction resolveRequestUrl(url: string): string {\n if (\n process.env.NODE_ENV === 'development' &&\n getAPILoaderModeFromStorage() === APILoaderMode4Dev.Local &&\n url.startsWith('/')\n ) {\n const nextUrl =\n url === manifestUrlForDev ? SDK.ServerAPI.API.Manifest : url;\n const currentUrl = new URL(location.href);\n currentUrl.port = String(process.env.LOCAL_CLI_PORT!);\n return `${currentUrl.origin}${nextUrl}`;\n }\n\n return url;\n}\n\nasync function requestText(url: string, timeout: number) {\n const res = await Fetch.fetchWithTimeout(resolveRequestUrl(url), { timeout });\n return res.text();\n}\n\nexport async function fetchShardingFile(url: string): Promise<string> {\n if (Url.isUrl(url)) {\n return requestText(url, 999999);\n }\n // json string\n return url;\n}\n\nexport async function loadManifestByUrl(url: string) {\n const json = await fetchJSONByUrl(url);\n\n const res = await parseManifest(json);\n return res;\n}\n\nexport async function fetchJSONByUrl(url: string) {\n let json: unknown = await requestText(url, 30000);\n\n if (typeof json === 'string') {\n const trimmed = json.trim();\n // If we got an HTML document (usually error page / SPA fallback), skip JSON.parse\n if (/^<!doctype html\\b/i.test(trimmed) || /^<html\\b/i.test(trimmed)) {\n json = {} as Manifest.RsdoctorManifestWithShardingFiles;\n } else {\n json = JSON.parse(json);\n }\n }\n\n return json as Manifest.RsdoctorManifestWithShardingFiles;\n}\n\nexport function fetchJSONByUrls(urls: string[]) {\n return Promise.all(urls.map((url) => fetchJSONByUrl(url)));\n}\n\nexport async function parseManifest(\n json: Manifest.RsdoctorManifestWithShardingFiles,\n) {\n let transformedData: Manifest.RsdoctorManifestData;\n\n try {\n // try to load cloud data first\n if (json.cloudData) {\n try {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.cloudData,\n fetchShardingFile,\n );\n } catch (error) {\n console.log('cloudData load error: ', error);\n }\n } else {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.data,\n fetchShardingFile,\n );\n }\n } catch {\n transformedData = await ManifestMethod.fetchShardingFiles(\n json.data,\n fetchShardingFile,\n );\n }\n\n return {\n ...json,\n data: transformedData!,\n };\n}\n\nconst manifestUrlForDev = '/manifest.json';\n\nexport function getManifestUrl(): string {\n let file: string | void;\n\n if (\n (window as { [key: string]: any })[\n Manifest.RsdoctorManifestClientConstant.WindowPropertyForManifestUrl\n ]\n ) {\n // load from window property\n file = (window as { [key: string]: any })[\n Manifest.RsdoctorManifestClientConstant.WindowPropertyForManifestUrl\n ];\n } else {\n // load from url query\n file = getManifestUrlFromUrlQuery();\n }\n\n if (!file) {\n file = SDK.ServerAPI.API.Manifest;\n }\n\n return file;\n}\n\nconst pool = new Map<\n string,\n Promise<Manifest.RsdoctorManifestWithShardingFiles>\n>();\n\nexport async function fetchManifest(url = getManifestUrl()) {\n if (!pool.has(url)) {\n pool.set(\n url,\n fetchJSONByUrl(url).catch((err) => {\n pool.delete(url);\n throw err;\n }),\n );\n }\n\n const res = await pool.get(url)!;\n\n return res;\n}\n\nexport async function postServerAPI<\n T extends SDK.ServerAPI.API,\n B extends SDK.ServerAPI.InferRequestBodyType<T> =\n SDK.ServerAPI.InferRequestBodyType<T>,\n R extends SDK.ServerAPI.InferResponseType<T> =\n SDK.ServerAPI.InferResponseType<T>,\n>(...args: B extends void ? [api: T] : [api: T, body: B]): Promise<R> {\n const [api, body] = args;\n const timeout = process.env.NODE_ENV === 'development' ? 10000 : 60000;\n const requestInit: Fetch.FetchOptions = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n timeout,\n };\n\n if (body != null) {\n requestInit.body = JSON.stringify(body);\n }\n\n const res = await Fetch.fetchWithTimeout(\n resolveRequestUrl(`${api}?_t=${random()}`),\n requestInit,\n );\n return (await res.json()) as R;\n}\n"],"names":["random","Date","Math","resolveRequestUrl","url","process","getAPILoaderModeFromStorage","APILoaderMode4Dev","nextUrl","manifestUrlForDev","SDK","currentUrl","URL","location","String","requestText","timeout","res","Fetch","fetchShardingFile","Url","loadManifestByUrl","json","fetchJSONByUrl","parseManifest","trimmed","JSON","fetchJSONByUrls","urls","Promise","transformedData","ManifestMethod","error","console","getManifestUrl","file","window","Manifest","getManifestUrlFromUrlQuery","pool","Map","fetchManifest","err","postServerAPI","args","api","body","requestInit"],"mappings":"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"}
@@ -56,6 +56,29 @@ describe('request utils', ()=>{
56
56
  ok: true
57
57
  });
58
58
  });
59
+ it('postServerAPI() omits request body when body is null', async ()=>{
60
+ const fetchMock = rs.fn().mockResolvedValue({
61
+ ok: true,
62
+ json: async ()=>({
63
+ ok: true
64
+ })
65
+ });
66
+ globalThis.fetch = fetchMock;
67
+ process.env.NODE_ENV = 'production';
68
+ const result = await postServerAPI('/api/demo', null);
69
+ const [url, init] = fetchMock.mock.calls[0];
70
+ expect(url).toContain('/api/demo?_t=');
71
+ expect(init).toMatchObject({
72
+ method: 'POST',
73
+ headers: {
74
+ 'Content-Type': 'application/json'
75
+ }
76
+ });
77
+ expect(init).not.toHaveProperty('body');
78
+ expect(result).toStrictEqual({
79
+ ok: true
80
+ });
81
+ });
59
82
  });
60
83
 
61
84
  //# sourceMappingURL=request.test.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils/request.test.mjs","sources":["../../src/utils/request.test.ts"],"sourcesContent":["import { afterEach, describe, expect, it, rs } from '@rstest/core';\nimport { fetchJSONByUrl, postServerAPI } from './request';\n\ndescribe('request utils', () => {\n const originalFetch = globalThis.fetch;\n const originalNodeEnv = process.env.NODE_ENV;\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n process.env.NODE_ENV = originalNodeEnv;\n });\n\n it('fetchJSONByUrl() parses json text payload', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: true,\n text: async () => '{\"name\":\"rsdoctor\"}',\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n const data = await fetchJSONByUrl('https://example.com/manifest.json');\n\n expect(data).toStrictEqual({ name: 'rsdoctor' });\n expect(fetchMock).toBeCalledTimes(1);\n });\n\n it('fetchJSONByUrl() throws for non-2xx response', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: false,\n status: 500,\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n await expect(\n fetchJSONByUrl('https://example.com/manifest.json'),\n ).rejects.toThrow('Request failed with status 500');\n });\n\n it('postServerAPI() sends json body and parses response json', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: true,\n json: async () => ({ ok: true }),\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n const result = await (postServerAPI as any)('/api/demo', { id: 1 });\n const [url, init] = fetchMock.mock.calls[0];\n\n expect(url).toContain('/api/demo?_t=');\n expect(init).toMatchObject({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ id: 1 }),\n });\n expect(result).toStrictEqual({ ok: true });\n });\n});\n"],"names":["describe","originalFetch","globalThis","originalNodeEnv","process","afterEach","it","fetchMock","rs","data","fetchJSONByUrl","expect","result","postServerAPI","url","init","JSON"],"mappings":";;AAGAA,SAAS,iBAAiB;IACxB,MAAMC,gBAAgBC,WAAW,KAAK;IACtC,MAAMC,kBAAkBC,QAAQ,GAAG,CAAC,QAAQ;IAE5CC,UAAU;QACRH,WAAW,KAAK,GAAGD;QACnBG,QAAQ,GAAG,CAAC,QAAQ,GAAGD;IACzB;IAEAG,GAAG,6CAA6C;QAC9C,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,MAAM,UAAY;QACpB;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMK,OAAO,MAAMC,eAAe;QAElCC,OAAOF,MAAM,aAAa,CAAC;YAAE,MAAM;QAAW;QAC9CE,OAAOJ,WAAW,eAAe,CAAC;IACpC;IAEAD,GAAG,gDAAgD;QACjD,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,QAAQ;QACV;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMO,OACJD,eAAe,sCACf,OAAO,CAAC,OAAO,CAAC;IACpB;IAEAJ,GAAG,4DAA4D;QAC7D,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,MAAM,UAAa;oBAAE,IAAI;gBAAK;QAChC;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMQ,SAAS,MAAOC,cAAsB,aAAa;YAAE,IAAI;QAAE;QACjE,MAAM,CAACC,KAAKC,KAAK,GAAGR,UAAU,IAAI,CAAC,KAAK,CAAC,EAAE;QAE3CI,OAAOG,KAAK,SAAS,CAAC;QACtBH,OAAOI,MAAM,aAAa,CAAC;YACzB,QAAQ;YACR,SAAS;gBACP,gBAAgB;YAClB;YACA,MAAMC,KAAK,SAAS,CAAC;gBAAE,IAAI;YAAE;QAC/B;QACAL,OAAOC,QAAQ,aAAa,CAAC;YAAE,IAAI;QAAK;IAC1C;AACF"}
1
+ {"version":3,"file":"utils/request.test.mjs","sources":["../../src/utils/request.test.ts"],"sourcesContent":["import { afterEach, describe, expect, it, rs } from '@rstest/core';\nimport { fetchJSONByUrl, postServerAPI } from './request';\n\ndescribe('request utils', () => {\n const originalFetch = globalThis.fetch;\n const originalNodeEnv = process.env.NODE_ENV;\n\n afterEach(() => {\n globalThis.fetch = originalFetch;\n process.env.NODE_ENV = originalNodeEnv;\n });\n\n it('fetchJSONByUrl() parses json text payload', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: true,\n text: async () => '{\"name\":\"rsdoctor\"}',\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n const data = await fetchJSONByUrl('https://example.com/manifest.json');\n\n expect(data).toStrictEqual({ name: 'rsdoctor' });\n expect(fetchMock).toBeCalledTimes(1);\n });\n\n it('fetchJSONByUrl() throws for non-2xx response', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: false,\n status: 500,\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n await expect(\n fetchJSONByUrl('https://example.com/manifest.json'),\n ).rejects.toThrow('Request failed with status 500');\n });\n\n it('postServerAPI() sends json body and parses response json', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: true,\n json: async () => ({ ok: true }),\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n const result = await (postServerAPI as any)('/api/demo', { id: 1 });\n const [url, init] = fetchMock.mock.calls[0];\n\n expect(url).toContain('/api/demo?_t=');\n expect(init).toMatchObject({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ id: 1 }),\n });\n expect(result).toStrictEqual({ ok: true });\n });\n\n it('postServerAPI() omits request body when body is null', async () => {\n const fetchMock = rs.fn().mockResolvedValue({\n ok: true,\n json: async () => ({ ok: true }),\n });\n globalThis.fetch = fetchMock as typeof fetch;\n process.env.NODE_ENV = 'production';\n\n const result = await (postServerAPI as any)('/api/demo', null);\n const [url, init] = fetchMock.mock.calls[0];\n\n expect(url).toContain('/api/demo?_t=');\n expect(init).toMatchObject({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n expect(init).not.toHaveProperty('body');\n expect(result).toStrictEqual({ ok: true });\n });\n});\n"],"names":["describe","originalFetch","globalThis","originalNodeEnv","process","afterEach","it","fetchMock","rs","data","fetchJSONByUrl","expect","result","postServerAPI","url","init","JSON"],"mappings":";;AAGAA,SAAS,iBAAiB;IACxB,MAAMC,gBAAgBC,WAAW,KAAK;IACtC,MAAMC,kBAAkBC,QAAQ,GAAG,CAAC,QAAQ;IAE5CC,UAAU;QACRH,WAAW,KAAK,GAAGD;QACnBG,QAAQ,GAAG,CAAC,QAAQ,GAAGD;IACzB;IAEAG,GAAG,6CAA6C;QAC9C,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,MAAM,UAAY;QACpB;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMK,OAAO,MAAMC,eAAe;QAElCC,OAAOF,MAAM,aAAa,CAAC;YAAE,MAAM;QAAW;QAC9CE,OAAOJ,WAAW,eAAe,CAAC;IACpC;IAEAD,GAAG,gDAAgD;QACjD,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,QAAQ;QACV;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMO,OACJD,eAAe,sCACf,OAAO,CAAC,OAAO,CAAC;IACpB;IAEAJ,GAAG,4DAA4D;QAC7D,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,MAAM,UAAa;oBAAE,IAAI;gBAAK;QAChC;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMQ,SAAS,MAAOC,cAAsB,aAAa;YAAE,IAAI;QAAE;QACjE,MAAM,CAACC,KAAKC,KAAK,GAAGR,UAAU,IAAI,CAAC,KAAK,CAAC,EAAE;QAE3CI,OAAOG,KAAK,SAAS,CAAC;QACtBH,OAAOI,MAAM,aAAa,CAAC;YACzB,QAAQ;YACR,SAAS;gBACP,gBAAgB;YAClB;YACA,MAAMC,KAAK,SAAS,CAAC;gBAAE,IAAI;YAAE;QAC/B;QACAL,OAAOC,QAAQ,aAAa,CAAC;YAAE,IAAI;QAAK;IAC1C;IAEAN,GAAG,wDAAwD;QACzD,MAAMC,YAAYC,GAAG,EAAE,GAAG,iBAAiB,CAAC;YAC1C,IAAI;YACJ,MAAM,UAAa;oBAAE,IAAI;gBAAK;QAChC;QACAN,WAAW,KAAK,GAAGK;QACnBH,QAAQ,GAAG,CAAC,QAAQ,GAAG;QAEvB,MAAMQ,SAAS,MAAOC,cAAsB,aAAa;QACzD,MAAM,CAACC,KAAKC,KAAK,GAAGR,UAAU,IAAI,CAAC,KAAK,CAAC,EAAE;QAE3CI,OAAOG,KAAK,SAAS,CAAC;QACtBH,OAAOI,MAAM,aAAa,CAAC;YACzB,QAAQ;YACR,SAAS;gBACP,gBAAgB;YAClB;QACF;QACAJ,OAAOI,MAAM,GAAG,CAAC,cAAc,CAAC;QAChCJ,OAAOC,QAAQ,aAAa,CAAC;YAAE,IAAI;QAAK;IAC1C;AACF"}
@@ -1,6 +1,6 @@
1
1
  import { Manifest } from "@rsdoctor/types";
2
2
  function routes_hasCompile(routes) {
3
- const hasCompile = routes.includes(Manifest.RsdoctorManifestClientRoutes.WebpackLoaders) || routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleResolve) || routes.includes(Manifest.RsdoctorManifestClientRoutes.WebpackPlugins);
3
+ const hasCompile = routes.includes(Manifest.RsdoctorManifestClientRoutes.Loaders) || routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleResolve) || routes.includes(Manifest.RsdoctorManifestClientRoutes.Plugins);
4
4
  return hasCompile;
5
5
  }
6
6
  function routes_hasBundle(routes) {
@@ -1 +1 @@
1
- {"version":3,"file":"utils/routes.mjs","sources":["../../src/utils/routes.ts"],"sourcesContent":["import { Manifest } from '@rsdoctor/types';\n\nexport function hasCompile(routes: Manifest.RsdoctorManifestClientRoutes[]) {\n const hasCompile =\n routes.includes(Manifest.RsdoctorManifestClientRoutes.WebpackLoaders) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleResolve) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.WebpackPlugins);\n return hasCompile;\n}\n\nexport function hasBundle(routes: Manifest.RsdoctorManifestClientRoutes[]) {\n const hasBundle =\n routes.includes(Manifest.RsdoctorManifestClientRoutes.BundleSize) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleGraph) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.TreeShaking);\n return hasBundle;\n}\n"],"names":["hasCompile","routes","Manifest","hasBundle"],"mappings":";AAEO,SAASA,kBAAWC,MAA+C;IACxE,MAAMD,aACJC,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,cAAc,KACpED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,aAAa,KACnED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,cAAc;IACtE,OAAOF;AACT;AAEO,SAASG,iBAAUF,MAA+C;IACvE,MAAME,YACJF,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,UAAU,KAChED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,WAAW,KACjED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,WAAW;IACnE,OAAOC;AACT"}
1
+ {"version":3,"file":"utils/routes.mjs","sources":["../../src/utils/routes.ts"],"sourcesContent":["import { Manifest } from '@rsdoctor/types';\n\nexport function hasCompile(routes: Manifest.RsdoctorManifestClientRoutes[]) {\n const hasCompile =\n routes.includes(Manifest.RsdoctorManifestClientRoutes.Loaders) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleResolve) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.Plugins);\n return hasCompile;\n}\n\nexport function hasBundle(routes: Manifest.RsdoctorManifestClientRoutes[]) {\n const hasBundle =\n routes.includes(Manifest.RsdoctorManifestClientRoutes.BundleSize) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.ModuleGraph) ||\n routes.includes(Manifest.RsdoctorManifestClientRoutes.TreeShaking);\n return hasBundle;\n}\n"],"names":["hasCompile","routes","Manifest","hasBundle"],"mappings":";AAEO,SAASA,kBAAWC,MAA+C;IACxE,MAAMD,aACJC,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,OAAO,KAC7DD,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,aAAa,KACnED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,OAAO;IAC/D,OAAOF;AACT;AAEO,SAASG,iBAAUF,MAA+C;IACvE,MAAME,YACJF,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,UAAU,KAChED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,WAAW,KACjED,OAAO,QAAQ,CAACC,SAAS,4BAA4B,CAAC,WAAW;IACnE,OAAOC;AACT"}
@@ -1,7 +1,17 @@
1
- import { Socket } from 'socket.io-client';
2
- export declare function getSocket(socketPort?: string): Socket;
1
+ import type { SDK } from '@rsdoctor/types';
2
+ type SocketAPI = SDK.ServerAPI.API | SDK.ServerAPI.APIExtends;
3
+ export interface ServerSocketMessage<T extends SocketAPI = SocketAPI> {
4
+ api: T;
5
+ payload: SDK.ServerAPI.SocketResponseType<T>;
6
+ }
7
+ type SocketListener<T extends SocketAPI = SocketAPI> = (payload: SDK.ServerAPI.SocketResponseType<T>) => void;
8
+ export declare function requestServerAPI<T extends SDK.ServerAPI.API, B extends SDK.ServerAPI.InferRequestBodyType<T> = SDK.ServerAPI.InferRequestBodyType<T>, R extends SDK.ServerAPI.InferResponseType<T> = SDK.ServerAPI.InferResponseType<T>>(api: T, body: B | null | undefined, socketPort?: string): Promise<R>;
9
+ export declare function subscribeServerAPI<T extends SocketAPI>(api: T, body: SDK.ServerAPI.InferRequestBodyType<T, null> | null, listener: SocketListener<T>, socketPort?: string): () => void;
10
+ export declare function unsubscribeServerAPI<T extends SocketAPI>(api: T, body: SDK.ServerAPI.InferRequestBodyType<T, null> | null, listener: SocketListener<T>, socketPort?: string): void;
11
+ export declare function publishServerSocketMessage(message: ServerSocketMessage, socketUrl?: string): void;
3
12
  export declare function formatURL({ port, protocol, hostname, }: {
4
13
  port?: string;
5
14
  protocol: string;
6
15
  hostname: string;
7
16
  }): string;
17
+ export {};