openxiangda 1.0.122 → 1.0.124
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/openxiangda-skills/references/notifications.md +21 -0
- package/package.json +1 -1
- package/packages/sdk/dist/runtime/index.cjs +128 -10
- package/packages/sdk/dist/runtime/index.cjs.map +1 -1
- package/packages/sdk/dist/runtime/index.d.mts +1 -1
- package/packages/sdk/dist/runtime/index.d.ts +1 -1
- package/packages/sdk/dist/runtime/index.mjs +176 -58
- package/packages/sdk/dist/runtime/index.mjs.map +1 -1
- package/packages/sdk/dist/runtime/react.cjs +130 -12
- package/packages/sdk/dist/runtime/react.cjs.map +1 -1
- package/packages/sdk/dist/runtime/react.d.mts +64 -4
- package/packages/sdk/dist/runtime/react.d.ts +64 -4
- package/packages/sdk/dist/runtime/react.mjs +131 -13
- package/packages/sdk/dist/runtime/react.mjs.map +1 -1
|
@@ -61,6 +61,27 @@ await sdk.notification.sendByType({
|
|
|
61
61
|
});
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
User-facing in-app message centers should read the platform inbox instead of
|
|
65
|
+
creating app-specific message/log forms:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
const inbox = await sdk.notification.listInbox({
|
|
69
|
+
page: 1,
|
|
70
|
+
limit: 20,
|
|
71
|
+
readStatus: "unread",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
await sdk.notification.markRead(messageId);
|
|
75
|
+
await sdk.notification.markAllRead();
|
|
76
|
+
|
|
77
|
+
const unread = await sdk.notification.getUnreadCount();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Inbox APIs are app-scoped and only return the current logged-in user's `inapp`
|
|
81
|
+
messages. Use `keyword`, `templateCode`, and `readStatus` for server-side
|
|
82
|
+
filtering. Do not expose `/api/message/history` to normal users; it is an
|
|
83
|
+
administrative send-history surface.
|
|
84
|
+
|
|
64
85
|
CLI smoke tests:
|
|
65
86
|
|
|
66
87
|
```bash
|
package/package.json
CHANGED
|
@@ -2445,6 +2445,45 @@ var createPageSdk = (context) => {
|
|
|
2445
2445
|
...params,
|
|
2446
2446
|
appType: resolveAppType(context, params.appType)
|
|
2447
2447
|
}
|
|
2448
|
+
}),
|
|
2449
|
+
listInbox: (params = {}) => request({
|
|
2450
|
+
path: buildOpenXiangdaAppPath(
|
|
2451
|
+
context,
|
|
2452
|
+
params.appType,
|
|
2453
|
+
"/notifications/inbox"
|
|
2454
|
+
),
|
|
2455
|
+
method: "get",
|
|
2456
|
+
query: {
|
|
2457
|
+
page: params.page,
|
|
2458
|
+
limit: params.limit,
|
|
2459
|
+
readStatus: params.readStatus,
|
|
2460
|
+
keyword: params.keyword,
|
|
2461
|
+
templateCode: params.templateCode
|
|
2462
|
+
}
|
|
2463
|
+
}),
|
|
2464
|
+
getUnreadCount: (params = {}) => request({
|
|
2465
|
+
path: buildOpenXiangdaAppPath(
|
|
2466
|
+
context,
|
|
2467
|
+
params.appType,
|
|
2468
|
+
"/notifications/inbox/unread-count"
|
|
2469
|
+
),
|
|
2470
|
+
method: "get"
|
|
2471
|
+
}),
|
|
2472
|
+
markRead: (messageId, params = {}) => request({
|
|
2473
|
+
path: buildOpenXiangdaAppPath(
|
|
2474
|
+
context,
|
|
2475
|
+
params.appType,
|
|
2476
|
+
`/notifications/inbox/${encodePathSegment(messageId)}/read`
|
|
2477
|
+
),
|
|
2478
|
+
method: "post"
|
|
2479
|
+
}),
|
|
2480
|
+
markAllRead: (params = {}) => request({
|
|
2481
|
+
path: buildOpenXiangdaAppPath(
|
|
2482
|
+
context,
|
|
2483
|
+
params.appType,
|
|
2484
|
+
"/notifications/inbox/read-all"
|
|
2485
|
+
),
|
|
2486
|
+
method: "post"
|
|
2448
2487
|
})
|
|
2449
2488
|
};
|
|
2450
2489
|
const sdk = {
|
|
@@ -35317,10 +35356,18 @@ var OpenXiangdaProvider = ({
|
|
|
35317
35356
|
const [accessToken, setAccessTokenState] = (0, import_react216.useState)(null);
|
|
35318
35357
|
const accessTokenRef = (0, import_react216.useRef)(null);
|
|
35319
35358
|
const setAccessToken = (0, import_react216.useCallback)(
|
|
35320
|
-
(nextAccessToken) => {
|
|
35359
|
+
(nextAccessToken, options = {}) => {
|
|
35360
|
+
if (!nextAccessToken && options.clearIfToken && accessTokenRef.current?.token !== options.clearIfToken) {
|
|
35361
|
+
return;
|
|
35362
|
+
}
|
|
35321
35363
|
const normalizedAccessToken = nextAccessToken || null;
|
|
35322
|
-
|
|
35323
|
-
|
|
35364
|
+
const nextState = normalizedAccessToken ? {
|
|
35365
|
+
token: normalizedAccessToken,
|
|
35366
|
+
scope: options.scope || "default",
|
|
35367
|
+
path: options.path || null
|
|
35368
|
+
} : null;
|
|
35369
|
+
accessTokenRef.current = nextState;
|
|
35370
|
+
setAccessTokenState(nextState);
|
|
35324
35371
|
},
|
|
35325
35372
|
[]
|
|
35326
35373
|
);
|
|
@@ -35346,7 +35393,13 @@ var OpenXiangdaProvider = ({
|
|
|
35346
35393
|
return;
|
|
35347
35394
|
}
|
|
35348
35395
|
setState((prev) => ({ ...prev, loading: true, error: null }));
|
|
35349
|
-
const requestFetch = options.accessToken !== void 0 ? createAuthorizedFetch(
|
|
35396
|
+
const requestFetch = options.accessToken !== void 0 ? createAuthorizedFetch(
|
|
35397
|
+
resolvedFetch,
|
|
35398
|
+
createAccessTokenState(
|
|
35399
|
+
options.accessToken || null,
|
|
35400
|
+
options.accessTokenOptions
|
|
35401
|
+
)
|
|
35402
|
+
) : createAuthorizedFetch(resolvedFetch, accessTokenRef.current);
|
|
35350
35403
|
try {
|
|
35351
35404
|
const response = await requestFetch(
|
|
35352
35405
|
buildServiceUrl3(
|
|
@@ -35756,9 +35809,11 @@ var buildServiceUrl3 = (servicePrefix, path) => {
|
|
|
35756
35809
|
var createAuthorizedFetch = (baseFetch, accessToken) => {
|
|
35757
35810
|
if (!accessToken) return baseFetch;
|
|
35758
35811
|
return ((input, init = {}) => {
|
|
35812
|
+
const token = resolveAccessTokenForCurrentRoute(accessToken);
|
|
35813
|
+
if (!token) return baseFetch(input, init);
|
|
35759
35814
|
const headers = new Headers(init.headers || {});
|
|
35760
35815
|
if (!headers.has("authorization")) {
|
|
35761
|
-
headers.set("authorization", `Bearer ${
|
|
35816
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
35762
35817
|
}
|
|
35763
35818
|
return baseFetch(input, {
|
|
35764
35819
|
...init,
|
|
@@ -35766,6 +35821,34 @@ var createAuthorizedFetch = (baseFetch, accessToken) => {
|
|
|
35766
35821
|
});
|
|
35767
35822
|
});
|
|
35768
35823
|
};
|
|
35824
|
+
var createAccessTokenState = (accessToken, options = {}) => accessToken ? {
|
|
35825
|
+
token: accessToken,
|
|
35826
|
+
scope: options.scope || "default",
|
|
35827
|
+
path: options.path || null
|
|
35828
|
+
} : null;
|
|
35829
|
+
var resolveAccessTokenForCurrentRoute = (accessToken) => {
|
|
35830
|
+
if (accessToken.scope !== "public") return accessToken.token;
|
|
35831
|
+
const scopedPath = normalizeRoutePath(accessToken.path);
|
|
35832
|
+
const currentPath = normalizeRoutePath(getCurrentPathname2());
|
|
35833
|
+
if (!scopedPath) {
|
|
35834
|
+
return isPublicRoutePath(currentPath) ? accessToken.token : null;
|
|
35835
|
+
}
|
|
35836
|
+
if (currentPath === scopedPath || isPublicRoutePath(currentPath) && currentPath.startsWith(`${scopedPath}/`)) {
|
|
35837
|
+
return accessToken.token;
|
|
35838
|
+
}
|
|
35839
|
+
return null;
|
|
35840
|
+
};
|
|
35841
|
+
var normalizeRoutePath = (path) => {
|
|
35842
|
+
const text = String(path || "").trim();
|
|
35843
|
+
if (!text) return "";
|
|
35844
|
+
try {
|
|
35845
|
+
const base = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
35846
|
+
return new URL(text, base).pathname.replace(/\/+$/, "") || "/";
|
|
35847
|
+
} catch {
|
|
35848
|
+
return text.split(/[?#]/, 1)[0].replace(/\/+$/, "") || "/";
|
|
35849
|
+
}
|
|
35850
|
+
};
|
|
35851
|
+
var isPublicRoutePath = (path) => /\/public(?:\/|$)/.test(path);
|
|
35769
35852
|
var readJsonPayload = async (response) => {
|
|
35770
35853
|
try {
|
|
35771
35854
|
return await response.json();
|
|
@@ -35866,6 +35949,7 @@ var attachCallback = (loginUrl, callback) => {
|
|
|
35866
35949
|
}
|
|
35867
35950
|
};
|
|
35868
35951
|
var getCurrentHref4 = () => typeof window === "undefined" ? "" : window.location.href;
|
|
35952
|
+
var getCurrentPathname2 = () => typeof window === "undefined" ? "" : window.location.pathname;
|
|
35869
35953
|
var getCurrentHostname2 = () => typeof window === "undefined" ? "" : window.location.hostname;
|
|
35870
35954
|
var getRuntimeEnv = (key) => {
|
|
35871
35955
|
const env = typeof process !== "undefined" ? process.env : void 0;
|
|
@@ -35958,6 +36042,8 @@ var usePublicAccess = (options = {}) => {
|
|
|
35958
36042
|
const [session, setSession] = (0, import_react217.useState)(null);
|
|
35959
36043
|
const [error, setError] = (0, import_react217.useState)(null);
|
|
35960
36044
|
const [loading, setLoading] = (0, import_react217.useState)(Boolean(autoStart));
|
|
36045
|
+
const activeSessionRef = (0, import_react217.useRef)(null);
|
|
36046
|
+
const mountedRef = (0, import_react217.useRef)(true);
|
|
35961
36047
|
const sessionInputKey = JSON.stringify(sessionInput);
|
|
35962
36048
|
const stableSessionInput = (0, import_react217.useMemo)(() => sessionInput, [sessionInputKey]);
|
|
35963
36049
|
const client = (0, import_react217.useMemo)(
|
|
@@ -35973,15 +36059,31 @@ var usePublicAccess = (options = {}) => {
|
|
|
35973
36059
|
setLoading(true);
|
|
35974
36060
|
setError(null);
|
|
35975
36061
|
try {
|
|
36062
|
+
const resolvedPath = input.path || stableSessionInput.path || readPathFromLocation();
|
|
35976
36063
|
const data = await client.startSession({
|
|
35977
36064
|
...stableSessionInput,
|
|
35978
36065
|
...input,
|
|
35979
36066
|
ticket: input.ticket || stableSessionInput.ticket || readTicketFromLocation(),
|
|
35980
|
-
path:
|
|
36067
|
+
path: resolvedPath
|
|
35981
36068
|
});
|
|
36069
|
+
if (!mountedRef.current) return data;
|
|
36070
|
+
activeSessionRef.current = {
|
|
36071
|
+
accessToken: data.accessToken,
|
|
36072
|
+
path: resolvedPath
|
|
36073
|
+
};
|
|
35982
36074
|
setSession(data);
|
|
35983
|
-
setAccessToken(data.accessToken
|
|
35984
|
-
|
|
36075
|
+
setAccessToken(data.accessToken, {
|
|
36076
|
+
scope: "public",
|
|
36077
|
+
path: resolvedPath
|
|
36078
|
+
});
|
|
36079
|
+
await reloadRuntime({
|
|
36080
|
+
accessToken: data.accessToken,
|
|
36081
|
+
accessTokenOptions: {
|
|
36082
|
+
scope: "public",
|
|
36083
|
+
path: resolvedPath
|
|
36084
|
+
}
|
|
36085
|
+
});
|
|
36086
|
+
if (!mountedRef.current) return data;
|
|
35985
36087
|
setLoading(false);
|
|
35986
36088
|
return data;
|
|
35987
36089
|
} catch (caught) {
|
|
@@ -35989,8 +36091,10 @@ var usePublicAccess = (options = {}) => {
|
|
|
35989
36091
|
caught instanceof Error ? caught.message : "\u516C\u5F00\u8BBF\u95EE\u4F1A\u8BDD\u521B\u5EFA\u5931\u8D25",
|
|
35990
36092
|
{ payload: caught }
|
|
35991
36093
|
);
|
|
35992
|
-
|
|
35993
|
-
|
|
36094
|
+
if (mountedRef.current) {
|
|
36095
|
+
setError(nextError);
|
|
36096
|
+
setLoading(false);
|
|
36097
|
+
}
|
|
35994
36098
|
throw nextError;
|
|
35995
36099
|
}
|
|
35996
36100
|
},
|
|
@@ -36000,6 +36104,20 @@ var usePublicAccess = (options = {}) => {
|
|
|
36000
36104
|
if (!autoStart) return;
|
|
36001
36105
|
void startSession().catch(() => void 0);
|
|
36002
36106
|
}, [autoStart, startSession]);
|
|
36107
|
+
(0, import_react217.useEffect)(
|
|
36108
|
+
() => {
|
|
36109
|
+
mountedRef.current = true;
|
|
36110
|
+
return () => {
|
|
36111
|
+
mountedRef.current = false;
|
|
36112
|
+
const activeSession = activeSessionRef.current;
|
|
36113
|
+
if (!activeSession) return;
|
|
36114
|
+
activeSessionRef.current = null;
|
|
36115
|
+
setAccessToken(null, { clearIfToken: activeSession.accessToken });
|
|
36116
|
+
void reloadRuntime({ accessToken: null });
|
|
36117
|
+
};
|
|
36118
|
+
},
|
|
36119
|
+
[reloadRuntime, setAccessToken]
|
|
36120
|
+
);
|
|
36003
36121
|
return {
|
|
36004
36122
|
loading,
|
|
36005
36123
|
error,
|