@tacoreai/web-sdk 1.1.0 → 1.4.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.
|
@@ -33,8 +33,9 @@ class AppsTokenManager {
|
|
|
33
33
|
export class AppsAuthManager extends BaseAppsClient {
|
|
34
34
|
constructor(appId, config = {}) {
|
|
35
35
|
super(appId, config);
|
|
36
|
+
const isPreviewMode = isBackend && process.env.TACORE_APPSERVER_PREVIEW_MODE === "true";
|
|
36
37
|
|
|
37
|
-
if (isBackend && !this.config.tacoreServerInteropAppServerApiKey) {
|
|
38
|
+
if (isBackend && !isPreviewMode && !this.config.tacoreServerInteropAppServerApiKey) {
|
|
38
39
|
throw new Error("tacoreServerInteropAppServerApiKey is required for backend environment. Provide it in config or via TACORE_SERVER_INTEROP_APP_SERVER_API_KEY env var.");
|
|
39
40
|
}
|
|
40
41
|
|
|
@@ -333,4 +334,4 @@ export class AppsAuthManager extends BaseAppsClient {
|
|
|
333
334
|
clearAccessToken() {
|
|
334
335
|
AppsTokenManager.clearAccessToken();
|
|
335
336
|
}
|
|
336
|
-
}
|
|
337
|
+
}
|
|
@@ -2,6 +2,20 @@ import { env, isDevelopmentBrowser, isProductionBrowser, isBackend } from "../..
|
|
|
2
2
|
|
|
3
3
|
const appServerAPIMap = new Map();
|
|
4
4
|
|
|
5
|
+
const isBrowserPreviewRuntime = () => {
|
|
6
|
+
if (typeof window === "undefined") {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const explicitFlag = window.__TACORE_PREVIEW_MODE__;
|
|
11
|
+
if (explicitFlag === true || explicitFlag === "true") {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const pathname = typeof window.location?.pathname === "string" ? window.location.pathname : "";
|
|
16
|
+
return pathname.startsWith("/app-run/");
|
|
17
|
+
};
|
|
18
|
+
|
|
5
19
|
/**
|
|
6
20
|
* 注册一个 App Server API。
|
|
7
21
|
* - 在开发态浏览器中:有效,用于本地调用。
|
|
@@ -17,12 +31,54 @@ const registerAppServerAPI = (appServerAPIName, appServerAPIHandler) => {
|
|
|
17
31
|
// 在生产态浏览器中,这是一个空操作。
|
|
18
32
|
};
|
|
19
33
|
|
|
34
|
+
const invokeByPlatformProxy = async function(appServerAPIName, payload) {
|
|
35
|
+
const endpoint = `/apps/invokeAppServerAPI?appId=${encodeURIComponent(this.appId)}&apiName=${encodeURIComponent(appServerAPIName)}`;
|
|
36
|
+
const res = await this._post(endpoint, payload);
|
|
37
|
+
if (res.success) {
|
|
38
|
+
return res.data;
|
|
39
|
+
}
|
|
40
|
+
throw new Error(res.error || res.message || `AppServer invocation failed: ${res.code || "UNKNOWN_ERROR"}`);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const invokeByPreviewProxy = async function(appServerAPIName, payload) {
|
|
44
|
+
const endpoint = `/appserver-preview/invokeAppServerAPI?appId=${encodeURIComponent(this.appId)}&apiName=${encodeURIComponent(appServerAPIName)}`;
|
|
45
|
+
|
|
46
|
+
const response = await fetch(endpoint, {
|
|
47
|
+
method: "POST",
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json",
|
|
50
|
+
},
|
|
51
|
+
body: JSON.stringify(payload || {}),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const contentType = response.headers.get("content-type") || "";
|
|
55
|
+
const responseData = contentType.includes("application/json")
|
|
56
|
+
? await response.json()
|
|
57
|
+
: await response.text();
|
|
58
|
+
|
|
59
|
+
if (!response.ok) {
|
|
60
|
+
const errorMessage = typeof responseData === "object"
|
|
61
|
+
? (responseData?.error || responseData?.message || JSON.stringify(responseData))
|
|
62
|
+
: String(responseData || "");
|
|
63
|
+
throw new Error(`[AppServer-DevBridge] status: ${response.status}, message: ${errorMessage}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (responseData && typeof responseData === "object" && Object.prototype.hasOwnProperty.call(responseData, "success")) {
|
|
67
|
+
if (responseData.success) {
|
|
68
|
+
return responseData.data;
|
|
69
|
+
}
|
|
70
|
+
throw new Error(responseData.error || "AppServer invocation failed in dev bridge");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return responseData;
|
|
74
|
+
};
|
|
75
|
+
|
|
20
76
|
/**
|
|
21
77
|
* 调用一个 App Server API。
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
78
|
+
* - 在开发态浏览器中:预览页(/app-run/*)走本地预览代理,其余开发页直接走平台转发。
|
|
79
|
+
* - 在生产态浏览器中:统一走平台转发(/apps/invokeAppServerAPI)。
|
|
24
80
|
* - 在后端云函数中:本地执行 (由云函数入口调用)。
|
|
25
|
-
* -
|
|
81
|
+
* - 跨应用调用:仅后端场景可直连目标 AppServer(需 appServerBaseUrl + appServerApiKey)。
|
|
26
82
|
* @param {string} appServerAPIName - 要调用的服务名称。
|
|
27
83
|
* @param {Object} payload - 传递给服务的负载数据。
|
|
28
84
|
* @returns {Promise<any>} 服务处理后的结果。
|
|
@@ -30,7 +86,7 @@ const registerAppServerAPI = (appServerAPIName, appServerAPIHandler) => {
|
|
|
30
86
|
const invokeAppServerAPI = async function(appServerAPIName, payload) {
|
|
31
87
|
console.log(`[AppServer][${this.appId}] Invoking "${appServerAPIName}" with payload:`, payload);
|
|
32
88
|
// 场景零:跨应用调用,在源应用的 appserver 云函数调用目标应用的 appserver 云函数
|
|
33
|
-
if (this.config.appServerBaseUrl && this.config.appServerApiKey) {
|
|
89
|
+
if (isBackend && this.config.appServerBaseUrl && this.config.appServerApiKey) {
|
|
34
90
|
const endpoint = `${this.config.appServerBaseUrl}/invokeAppServerAPI?apiName=${appServerAPIName}`;
|
|
35
91
|
try {
|
|
36
92
|
const response = await fetch(endpoint, {
|
|
@@ -61,24 +117,25 @@ const invokeAppServerAPI = async function(appServerAPIName, payload) {
|
|
|
61
117
|
}
|
|
62
118
|
}
|
|
63
119
|
|
|
64
|
-
//
|
|
65
|
-
if (
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
120
|
+
// 场景一:开发环境浏览器
|
|
121
|
+
if (isDevelopmentBrowser) {
|
|
122
|
+
if (isBrowserPreviewRuntime()) {
|
|
123
|
+
return await invokeByPreviewProxy.call(this, appServerAPIName, payload);
|
|
124
|
+
}
|
|
125
|
+
return await invokeByPlatformProxy.call(this, appServerAPIName, payload);
|
|
126
|
+
}
|
|
69
127
|
|
|
128
|
+
// 场景二:生产环境的浏览器,统一走平台转发
|
|
129
|
+
if (isProductionBrowser) {
|
|
70
130
|
try {
|
|
71
|
-
|
|
72
|
-
if (res.success) {
|
|
73
|
-
return res.data;
|
|
74
|
-
}
|
|
131
|
+
return await invokeByPlatformProxy.call(this, appServerAPIName, payload);
|
|
75
132
|
} catch (error) {
|
|
76
133
|
console.error(`[AppServer-Prod] Failed to invoke "${appServerAPIName}" via appsClient:`, error);
|
|
77
134
|
throw error;
|
|
78
135
|
}
|
|
79
136
|
}
|
|
80
137
|
|
|
81
|
-
//
|
|
138
|
+
// 场景三:后端云函数环境,从本地 Map 执行
|
|
82
139
|
const appServerAPIHandler = appServerAPIMap.get(appServerAPIName);
|
|
83
140
|
if (!appServerAPIHandler) {
|
|
84
141
|
throw new Error(`[AppServer-${env}] AppServer "${appServerAPIName}" not found or not registered.`);
|
|
@@ -89,4 +146,4 @@ const invokeAppServerAPI = async function(appServerAPIName, payload) {
|
|
|
89
146
|
export const appsClientAppServerMethods = {
|
|
90
147
|
registerAppServerAPI,
|
|
91
148
|
invokeAppServerAPI,
|
|
92
|
-
};
|
|
149
|
+
};
|
|
@@ -38,8 +38,9 @@ class AppsClient extends BaseAppsClient {
|
|
|
38
38
|
|
|
39
39
|
constructor(appId, config = {}) {
|
|
40
40
|
super(appId, config);
|
|
41
|
+
const isPreviewMode = isBackend && process.env.TACORE_APPSERVER_PREVIEW_MODE === "true";
|
|
41
42
|
|
|
42
|
-
if (isBackend && !this.config.tacoreServerInteropAppServerApiKey) {
|
|
43
|
+
if (isBackend && !isPreviewMode && !this.config.tacoreServerInteropAppServerApiKey) {
|
|
43
44
|
throw new Error(
|
|
44
45
|
"tacoreServerInteropAppServerApiKey is required for backend environment. Provide it in config or via TACORE_SERVER_INTEROP_APP_SERVER_API_KEY env var."
|
|
45
46
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getAppsApiBaseUrl, isBrowser, isBackend,
|
|
1
|
+
import { getAppsApiBaseUrl, isBrowser, isBackend, getGlobalOptions } from "../../../utils/index.js";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Apps SDK 基类
|
|
@@ -13,7 +13,8 @@ export class BaseAppsClient {
|
|
|
13
13
|
|
|
14
14
|
const globalOptions = getGlobalOptions();
|
|
15
15
|
const defaultConfig = {
|
|
16
|
-
|
|
16
|
+
// 默认统一走平台接口;如需特殊链路可显式传入 apiBaseUrl 覆盖。
|
|
17
|
+
apiBaseUrl: getAppsApiBaseUrl(),
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
this.config = {
|
|
@@ -212,4 +213,4 @@ export class BaseAppsClient {
|
|
|
212
213
|
getConfig() {
|
|
213
214
|
return { ...this.config };
|
|
214
215
|
}
|
|
215
|
-
}
|
|
216
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tacoreai/web-sdk",
|
|
3
3
|
"description": "This file is for app server package, not the real npm package",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.4.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
7
8
|
"registry": "https://registry.npmjs.com"
|
|
8
9
|
},
|
|
9
10
|
"exports": {
|
|
@@ -11,6 +12,6 @@
|
|
|
11
12
|
"./utils": "./utils/index.js"
|
|
12
13
|
},
|
|
13
14
|
"scripts": {
|
|
14
|
-
"release": "npm version minor && git commit -am \"web-sdk update version\" &&
|
|
15
|
+
"release": "npm version minor && git commit -am \"web-sdk update version\" && npm publish"
|
|
15
16
|
}
|
|
16
17
|
}
|