befly-shared 2.22.0 → 2.23.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "befly-shared",
3
- "version": "2.22.0",
3
+ "version": "2.23.0",
4
4
  "gitHead": "70c48ac058875255ac8b54c5f4b5987b997c3bfd",
5
5
  "private": false,
6
6
  "description": "Befly Shared - 通用工具函数库",
@@ -1,18 +0,0 @@
1
- export function getVsCode() {
2
- const cacheKey = "__YICODE_VSCODE_API";
3
- const cached = globalThis[cacheKey];
4
- if (cached) {
5
- return cached;
6
- }
7
- const acquire = globalThis.acquireVsCodeApi;
8
- if (typeof acquire !== "function") {
9
- return null;
10
- }
11
- try {
12
- const api = acquire();
13
- globalThis[cacheKey] = api;
14
- return api;
15
- } catch {
16
- return globalThis[cacheKey] ?? null;
17
- }
18
- }
@@ -1,91 +0,0 @@
1
- import { createHttp } from "../createHttp.js";
2
-
3
- const reportRequest = createHttp({
4
- apiPath: "https://api.yicode.tech/api",
5
- getToken: () => ""
6
- });
7
-
8
- const ERROR_REPORT_DEDUP_GAP = 3000;
9
-
10
- function normalizeDetail(detail) {
11
- if (detail === null || typeof detail === "undefined") return "";
12
- if (typeof detail === "string") {
13
- return detail;
14
- }
15
- if (detail instanceof Error) {
16
- return detail.stack || detail.message || String(detail);
17
- }
18
- try {
19
- return JSON.stringify(detail);
20
- } catch {
21
- return String(detail);
22
- }
23
- }
24
-
25
- function createBasePayload(options = {}) {
26
- return {
27
- source: options.source || "vscode",
28
- productName: options.productName,
29
- productCode: options.productCode,
30
- productVersion: options.productVersion,
31
- pagePath: options.pagePath,
32
- pageName: options.pageName
33
- };
34
- }
35
-
36
- function mergePagePayload(basePayload, page = {}) {
37
- return {
38
- ...basePayload,
39
- pagePath: page.pagePath ?? basePayload.pagePath,
40
- pageName: page.pageName ?? basePayload.pageName
41
- };
42
- }
43
-
44
- async function postReport(path, payload) {
45
- try {
46
- await reportRequest(path, payload, ["", null, undefined]);
47
- return true;
48
- } catch {
49
- return false;
50
- }
51
- }
52
-
53
- export function createReporter(options = {}) {
54
- const basePayload = createBasePayload(options);
55
- if (!basePayload.productCode) {
56
- return null;
57
- }
58
-
59
- const requestPost = options.requestPost || postReport;
60
- const fixedErrorType = basePayload.productCode || "extension";
61
- let lastErrorKey = "";
62
- let lastErrorTime = 0;
63
-
64
- return {
65
- reportInfo: function (page = {}) {
66
- return requestPost("/core/tongJi/infoReport", mergePagePayload(basePayload, page));
67
- },
68
- reportError: function (input = {}, page = {}) {
69
- const message = input.message || "未知错误";
70
- const detail = normalizeDetail(input.detail);
71
- const errorKey = `${fixedErrorType}|${message}|${detail}`;
72
- const now = Date.now();
73
- if (errorKey === lastErrorKey && now - lastErrorTime < ERROR_REPORT_DEDUP_GAP) {
74
- return Promise.resolve(false);
75
- }
76
- lastErrorKey = errorKey;
77
- lastErrorTime = now;
78
- return requestPost("/core/tongJi/errorReport", {
79
- ...mergePagePayload(basePayload, page),
80
- errorType: input.errorType || fixedErrorType,
81
- message: message,
82
- detail: detail
83
- });
84
- },
85
- reportOnline: function (clientId, page = {}) {
86
- const payload = mergePagePayload(basePayload, page);
87
- payload.clientId = clientId || "";
88
- return requestPost("/core/tongJi/onlineReport", payload);
89
- }
90
- };
91
- }
@@ -1,146 +0,0 @@
1
- /* eslint-env node */
2
-
3
- import { createReporter } from "./report.js";
4
-
5
- function getPackageMeta(context) {
6
- const packageJson = context.extension.packageJSON;
7
- const productCode = packageJson.name;
8
- if (!productCode) {
9
- return null;
10
- }
11
- return {
12
- productName: packageJson.displayName || packageJson.name,
13
- productCode: productCode,
14
- productVersion: packageJson.version
15
- };
16
- }
17
-
18
- export function createExtensionReporter(context, options = {}) {
19
- const packageMeta = getPackageMeta(context);
20
- if (!packageMeta) {
21
- return null;
22
- }
23
- const productCode = options.productCode || packageMeta.productCode;
24
- const pageName = productCode;
25
- return createReporter({
26
- ...options,
27
- source: options.source || "vscode",
28
- productName: options.productName || packageMeta.productName,
29
- productCode: productCode,
30
- productVersion: options.productVersion || packageMeta.productVersion,
31
- pagePath: `/${pageName}`,
32
- pageName: pageName
33
- });
34
- }
35
-
36
- const ONLINE_REPORT_HEARTBEAT_INTERVAL = 60 * 1000;
37
- const ONLINE_REPORT_CLIENT_ID_KEY = "befly-vscode-online-client-id";
38
-
39
- function generateClientId() {
40
- return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
41
- }
42
-
43
- function readClientId(context) {
44
- try {
45
- const stored = context.globalState.get(ONLINE_REPORT_CLIENT_ID_KEY);
46
- if (stored) {
47
- return String(stored);
48
- }
49
- } catch {
50
- // ignore
51
- }
52
- return "";
53
- }
54
-
55
- function writeClientId(context, clientId) {
56
- try {
57
- context.globalState.update(ONLINE_REPORT_CLIENT_ID_KEY, clientId);
58
- } catch {
59
- // ignore
60
- }
61
- }
62
-
63
- function getClientId(context) {
64
- const stored = readClientId(context);
65
- if (stored) {
66
- return stored;
67
- }
68
- const clientId = generateClientId();
69
- writeClientId(context, clientId);
70
- return clientId;
71
- }
72
-
73
- export function startReportHeartbeat(reporter, context) {
74
- if (!reporter || !reporter.reportOnline) {
75
- return () => {};
76
- }
77
- const clientId = getClientId(context);
78
-
79
- const timer = setInterval(() => {
80
- void reporter.reportOnline(clientId);
81
- }, ONLINE_REPORT_HEARTBEAT_INTERVAL);
82
-
83
- void reporter.reportOnline(clientId);
84
-
85
- return () => {
86
- clearInterval(timer);
87
- };
88
- }
89
-
90
- export function setupWebviewMessageReporter(panel, reporter) {
91
- if (!panel || !reporter) {
92
- return () => {};
93
- }
94
- const disposable = panel.webview.onDidReceiveMessage((message) => {
95
- if (!message || typeof message !== "object") {
96
- return;
97
- }
98
- if (message.command === "reportPageView") {
99
- void reporter.reportInfo({
100
- pagePath: message.pagePath,
101
- pageName: message.pageName
102
- });
103
- } else if (message.command === "reportError") {
104
- void reporter.reportError(
105
- {
106
- message: message.message,
107
- detail: message.detail,
108
- errorType: message.errorType
109
- },
110
- {
111
- pagePath: message.pagePath,
112
- pageName: message.pageName
113
- }
114
- );
115
- }
116
- });
117
- return () => {
118
- disposable.dispose();
119
- };
120
- }
121
-
122
- export function setupExtensionErrorHandlers(reporter) {
123
- if (!reporter) {
124
- return () => {};
125
- }
126
- const handleError = (error) => {
127
- void reporter.reportError({
128
- message: error?.message || "扩展未捕获异常",
129
- detail: error?.stack || String(error),
130
- errorType: "extension"
131
- });
132
- };
133
- const handleRejection = (reason) => {
134
- void reporter.reportError({
135
- message: reason?.message || "扩展未处理 Promise 拒绝",
136
- detail: reason?.stack || String(reason),
137
- errorType: "extension"
138
- });
139
- };
140
- process.on("uncaughtException", handleError);
141
- process.on("unhandledRejection", handleRejection);
142
- return () => {
143
- process.off("uncaughtException", handleError);
144
- process.off("unhandledRejection", handleRejection);
145
- };
146
- }
@@ -1,173 +0,0 @@
1
- /* eslint-env node */
2
-
3
- import * as fs from "node:fs";
4
-
5
- import * as vscode from "vscode";
6
-
7
- const DEV_SERVER_ORIGIN = "http://localhost:5200";
8
- const DEV_SERVER_WS_ORIGIN = "ws://localhost:5200";
9
-
10
- export function createBootstrapJs(args) {
11
- const devServerOrigin = args.isDev ? args.httpOrigin : "";
12
- const bootstrapValues = {
13
- __YICODE_IS_DEV: args.isDev === true,
14
- __YICODE_MODE: args.mode || "",
15
- __YICODE_PAGE_NAME: args.pageName || "main",
16
- __YICODE_PAGE_PATH: args.pagePath || "/main",
17
- __YICODE_DEV_SERVER_ORIGIN: devServerOrigin,
18
- __YICODE_PRODUCT_NAME: args.productName || "",
19
- __YICODE_PRODUCT_CODE: args.productCode || "",
20
- __YICODE_PRODUCT_VERSION: args.productVersion || ""
21
- };
22
- return Object.entries(bootstrapValues)
23
- .map(([key, value]) => `globalThis.${key}=${JSON.stringify(value)};`)
24
- .join("");
25
- }
26
-
27
- function getPackageMeta(context) {
28
- const packageJson = context.extension.packageJSON;
29
- return {
30
- productName: packageJson.displayName || packageJson.name || "",
31
- productCode: packageJson.name || "",
32
- productVersion: packageJson.version || ""
33
- };
34
- }
35
-
36
- export function isEnvEnabled(name) {
37
- const raw = process.env[name];
38
- if (!raw) return false;
39
- const v = raw.toLowerCase();
40
- return v === "1" || v === "true" || v === "yes";
41
- }
42
- export function createNonce() {
43
- const timestamp = Date.now();
44
- const random6 = Math.floor(Math.random() * 1000000)
45
- .toString()
46
- .padStart(6, "0");
47
- return `${timestamp}${random6}`;
48
- }
49
- export function createCsp(mode, args) {
50
- const common = {
51
- defaultSrc: "default-src 'none'",
52
- imgSrc: `img-src ${args.cspSource} https: http: data: blob:`,
53
- styleSrc: `style-src ${args.cspSource} 'unsafe-inline'`,
54
- fontSrc: `font-src ${args.cspSource} data:`
55
- };
56
- if (mode === "dev") {
57
- return [
58
- common.defaultSrc,
59
- `script-src 'nonce-${args.nonce}' 'unsafe-eval' ${args.httpOrigin}`,
60
- `${common.imgSrc} ${args.httpOrigin}`,
61
- `${common.styleSrc} ${args.httpOrigin}`,
62
- `${common.fontSrc} ${args.httpOrigin}`,
63
- `connect-src ${args.httpOrigin} ${args.wsOrigin} https://api.yicode.tech http://127.0.0.1:3020 http://localhost:3020`
64
- ].join("; ");
65
- }
66
- return [common.defaultSrc, common.imgSrc, `script-src 'nonce-${args.nonce}'`, common.styleSrc, common.fontSrc, `connect-src ${args.cspSource} https://api.yicode.tech`].join("; ");
67
- }
68
- export function createDevHtml(args) {
69
- const bootstrap = args.bootstrapJs ? `<script nonce="${args.nonce}">${args.bootstrapJs}</script>` : "";
70
- return `<!doctype html>
71
- <html lang="zh-CN">
72
- <head>
73
- <meta charset="UTF-8" />
74
- <meta http-equiv="Content-Security-Policy" content="${args.csp}" />
75
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
76
- <title>WebView(开发)</title>
77
- ${bootstrap}
78
- </head>
79
- <body style="padding: 0">
80
- <div id="app"></div>
81
- <script type="module" nonce="${args.nonce}" src="${args.httpOrigin}/@vite/client"></script>
82
- <script type="module" nonce="${args.nonce}" src="${args.httpOrigin}/main.js"></script>
83
- </body>
84
- </html>`;
85
- }
86
- export function createBuildHtml(args) {
87
- let out = args.html.replace(/(src|href)="\.\/([^"]+)"/g, (_match, attr, relPath) => {
88
- const resourceUri = args.mapAssetUri(relPath);
89
- return `${attr}="${resourceUri}"`;
90
- });
91
- const baseTag = `<base href="${args.baseHref}">`;
92
- out = out.replace(
93
- /<head(\s[^>]*)?>/i,
94
- (m) => `${m}
95
- ${baseTag}`
96
- );
97
- if (args.csp) {
98
- const cspTag = `<meta http-equiv="Content-Security-Policy" content="${args.csp}" />`;
99
- out = out.replace(
100
- /<head(\s[^>]*)?>/i,
101
- (m) => `${m}
102
- ${cspTag}`
103
- );
104
- }
105
- const bootstrapTag = `<script nonce="${args.nonce}">${args.bootstrapJs}</script>`;
106
- out = out.replace(
107
- /<head(\s[^>]*)?>/i,
108
- (m) => `${m}
109
- ${bootstrapTag}`
110
- );
111
- out = out.replace(/<script(?!\b[^>]*\bnonce=)/g, `<script nonce="${args.nonce}"`);
112
- return out;
113
- }
114
-
115
- export async function getWebviewHtml(context, webview, options = {}) {
116
- const nonce = createNonce();
117
- const modeName = options.mode || "main";
118
- const packageMeta = getPackageMeta(context);
119
- const pageName = packageMeta.productCode || "main";
120
- const pagePath = `/${pageName}`;
121
- const mode = modeName === "main" ? `${context.extension.id}` : `${context.extension.id}.${modeName}`;
122
-
123
- if (isEnvEnabled("WEBVIEW_DEV_SERVER") && context.extensionMode === vscode.ExtensionMode.Development) {
124
- const httpOrigin = DEV_SERVER_ORIGIN;
125
- const wsOrigin = DEV_SERVER_WS_ORIGIN;
126
- const bootstrapJs = createBootstrapJs({
127
- isDev: true,
128
- mode: mode,
129
- httpOrigin: httpOrigin,
130
- pageName: pageName,
131
- pagePath: pagePath,
132
- productName: packageMeta.productName,
133
- productCode: packageMeta.productCode,
134
- productVersion: packageMeta.productVersion
135
- });
136
- const csp = createCsp("dev", {
137
- cspSource: webview.cspSource,
138
- nonce: nonce,
139
- httpOrigin: httpOrigin,
140
- wsOrigin: wsOrigin
141
- });
142
- return createDevHtml({
143
- nonce: nonce,
144
- csp: csp,
145
- httpOrigin: httpOrigin,
146
- bootstrapJs: bootstrapJs
147
- });
148
- }
149
- const htmlPath = vscode.Uri.joinPath(context.extensionUri, "dist", "index.html");
150
- const htmlContent = fs.readFileSync(htmlPath.fsPath, "utf8");
151
- const distBaseUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri, "dist"));
152
- const baseHref = `${distBaseUri}`.endsWith("/") ? `${distBaseUri}` : `${distBaseUri}/`;
153
- const bootstrapJs = createBootstrapJs({
154
- isDev: false,
155
- mode: mode,
156
- httpOrigin: "",
157
- pageName: pageName,
158
- pagePath: pagePath,
159
- productName: packageMeta.productName,
160
- productCode: packageMeta.productCode,
161
- productVersion: packageMeta.productVersion
162
- });
163
- return createBuildHtml({
164
- html: htmlContent,
165
- nonce: nonce,
166
- baseHref: baseHref,
167
- bootstrapJs: bootstrapJs,
168
- mapAssetUri: (relPath) => {
169
- const resourceUri = webview.asWebviewUri(vscode.Uri.joinPath(context.extensionUri, "dist", relPath));
170
- return `${resourceUri}`;
171
- }
172
- });
173
- }