@fudanda/client 1.20261015.1-beta.1 → 2.20261024.1-beta.1

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- # MIT License
2
-
3
- Copyright (c) 2026 iwangbowen
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ # MIT License
2
+
3
+ Copyright (c) 2026 iwangbowen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,71 +1,47 @@
1
- # @fudanda/client
2
-
3
- 单组织 Go 基础版的独立 TypeScript API 客户端。运行时只依赖 `@fudanda/shared`,不依赖 React、Semi UI、TanStack Query、Web 源码或浏览器存储。支持 workspace 开发和根目录 `pack:packages` 的编译后 tarball 交付,可在仓库外安装,并由普通 Node 直接导入 ESM。
4
-
5
- ```ts
6
- import { Client, call, operationURL } from '@fudanda/client';
7
- import { goAuthContract, positionContract } from '@fudanda/shared/identity';
8
-
9
- const client = new Client({
10
- onUnauthorized: () => { /* 由宿主更新登录状态 */ },
11
- });
12
-
13
- // 浏览器发送 HttpOnly Cookie;刷新页面后重新获取 CSRF。
14
- const session = await call(client, goAuthContract.me);
15
- client.setCsrfToken(session.csrfToken);
16
-
17
- const page = await call(client, positionContract.list, {
18
- query: { page: 1, pageSize: 10, keyword: '工程' },
19
- });
20
-
21
- const csv = await client.readBlob(operationURL(positionContract.exportCsv, { query: {} }));
22
- ```
23
-
24
- ## 职责
25
-
26
- - `Client`:JSON、原始响应、multipart 上传、XHR 上传进度、取消和二进制下载;统一 Cookie/CSRF、请求头、链路 ID 和错误处理。
27
- - `call` / `callRaw`:从 shared 契约派生 `/api/v1` 路径、参数和响应;执行响应校验及单组织设置投影,保留更新时省略的字段。`call` 解包数据并抛业务错误,`callRaw` 返回 `{ code, message, data }`。
28
- - `operationURL`:为上传、预览和下载生成契约路径。未开放操作会在发送请求前被拒绝。
29
- - `ClientError`:无会话、网络故障、响应格式或下载错误,含 `status`、`reason` 和可用的 `requestId`;取消保留 `AbortError`。`ApiError` 表示非零业务响应码。
30
-
31
- 登录可通过 `call(client, goAuthContract.login, { body: ... })` 发起;登录成功后由宿主用响应中的 `csrfToken` 更新客户端。退出、改密后由宿主清除 CSRF 和用户状态。认证请求返回 401 时客户端清除 CSRF 并调用 `onUnauthorized`,503 不清除会话。登录失败不触发宿主强退事件。
32
-
33
- ```ts
34
- import { fileContract } from '@fudanda/shared/platform';
35
-
36
- const form = new FormData();
37
- form.append('file', file);
38
- await client.postForm(operationURL(fileContract.uploadOne), form, {
39
- signal: controller.signal,
40
- onProgress: percent => { /* 由宿主显示进度 */ },
41
- });
42
- ```
43
-
44
- 实际应用应通过 `operationURL(fileContract.uploadOne)` 获取上传路径,复用 shared 契约。文件下载返回 Blob;保存文件、Toast、重定向、用户信息和查询缓存由宿主负责。普通上传与进度上传使用相同的最新 CSRF,浏览器自行生成 multipart boundary。
45
-
46
- 默认同源,`baseURL` 可显式设置为 HTTP origin;客户端不会接受请求路径中的外部 URL。`transport` 可注入 fetch,`xhrFactory` 可注入上传实现。Node 调用需要注入维护 Cookie 的 transport;Node 的原生 fetch 不会自动保存服务端会话 Cookie。
47
-
48
- 宿主业务使用 `new Client({ operations: [hostContract.list] })` 明确注册 `/api/v1/extensions/` 契约,随后通过 `call` 调用;注册彼此隔离,不影响其他 Client 的首版限制。详见 [宿主接入说明](../../docs/guide/go-host-integration.md)。
49
-
50
- ## 验证
51
-
52
- ```sh
53
- npm run check:types
54
- npm run check:boundaries
55
- npm run test:client
56
- npm run lint -w @fudanda/client
57
- ```
58
-
59
- Web 的 `go-transport`、`go-api-client` 和文件请求仅保留宿主适配;React Query hooks、会话 Provider、下载保存和提示仍位于 `packages/web`,原页面沿用原来的调用入口。
60
-
61
- ## 脚本密钥与订阅
62
-
63
- `new Client({ baseURL, apiKey })` 使用受限 Bearer API Key,默认 `credentials: 'omit'`,不要求 CSRF;客户端不保存密钥到浏览器存储。Cookie 模式行为保持不变。服务端同时检查密钥范围、用户当前权限及数据范围;密钥不能管理密钥、授权或安全设置。
64
-
65
- `subscribe(client, { onChange, onUnauthorized, onError })` 提供 fetch SSE,兼容 Cookie 与 Key。变更只提示重新查询,支持内存游标、断线重连及认证失效终止。返回 `{ close, done }`;宿主卸载时调用 `close()` 并等待 `done`,查询缓存由宿主管理。
66
-
67
- 完整示例、接口、S3 和只读 MCP 说明见 [集成扩展](../../docs/guide/go-integrations.md)。
68
-
69
- `subscribeOperation(client, operation, {params, parse, onEvent, onConnection, onError, onUnauthorized})` 订阅该 Client 已注册的 GET SSE 契约。提供 `{close, done}`、UTF-8 分片解析和重连;业务缓存与 token 合并由宿主负责。自动化订阅收到 `ready` / `done` 后重新查询持久结果,不将临时预览作为最终输出,见[流式运行](../../docs/guide/workflow-stream-performance.md)。
70
-
71
- Casdoor 登录和目录管理通过 `goAuthContract` / `identityDirectoryContract` 调用,完整流程见 [身份接入指南](../../docs/guide/go-identity.md)。只有本地登录、外部登录开始/完成及会话冲突确认允许匿名 POST,目录写入仍要求 Cookie/CSRF。
1
+ # @fudanda/client
2
+
3
+ 原生 Goa TypeScript 客户端,运行时只依赖 `@fudanda/shared`。支持浏览器 Cookie/CSRF、脚本 API Key、严格请求/响应校验、multipart、上传进度、下载和 SSE,不依赖 React、UI 或查询缓存。
4
+
5
+ ```ts
6
+ import { GoaClient } from '@fudanda/client';
7
+ import { authMe } from '@fudanda/shared/api/identity';
8
+ import { positionsList } from '@fudanda/shared/api/positions';
9
+
10
+ const client = new GoaClient();
11
+ const session = await client.call(authMe);
12
+ client.setCSRFToken(session.csrfToken);
13
+ const page = await client.call(positionsList, {
14
+ query: { page: 1, pageSize: 10, keyword: '工程' },
15
+ });
16
+ ```
17
+
18
+ Goa DSL 生成路径、方法、参数、Result、错误及协议描述。`call` 直接返回原生 Result,204 返回 `undefined`;`callWithResponse` 另外返回状态和响应头。旧 `Client`、`callRaw` 和响应包装接口已退出公共包。
19
+
20
+ ## 会话与错误
21
+
22
+ 浏览器默认同源并发送 HttpOnly Cookie;刷新页面后读取 `authMe` 恢复 CSRF。登录成功后调用 `setCSRFToken`,退出或身份改变时调用 `clearSession`。`subscribeUnauthorized` 和 `onUnauthorized` 供宿主更新登录状态。受保护请求的 401 清除当前会话,503 不清除;迟到的旧会话结果以 `AbortError` 结束,不能覆盖新会话。
23
+
24
+ `GoaError` 提供 `status`、`reason`、`errorId`、`requestId`、`temporary`、`timeout` 和 `fault`;网络与取消错误保留原语义。请求的 `signal` 支持取消。PATCH 省略字段保持原值,清空使用设计允许的 `clearFields`,集合 PUT 允许 `[]`。客户端不自动重放写入。
25
+
26
+ `baseURL` 只能是 HTTP origin;Node 原生 fetch 不维护 Cookie,Cookie 模式须注入维护 Cookie 的 `transport`。`new GoaClient({ baseURL, apiKey })` 使用受限 Bearer Key,默认不携带 Cookie,不保存 Key 到浏览器存储。服务端继续校验实时账号权限、Key scope 和数据范围。
27
+
28
+ ## 文件与 SSE
29
+
30
+ `upload(operation, input, { signal, onProgress })` 接收生成的 multipart 输入;普通上传使用 fetch,需要进度时使用 XHR。二者使用最新 CSRF,浏览器自行生成 multipart boundary,宿主不能覆盖认证头。Blob、Blob 数组或 FormData 仍按生成操作校验。
31
+
32
+ `download(operation, input, options)` 返回未缓冲的 `Response`,调用者须消费或取消 body。宿主负责保存文件、Toast 和界面状态。
33
+
34
+ `stream(operation, input, { onEvent, onConnection, onError, signal })` 返回 `{ close, done }`。事件以生成 schema 校验,支持 UTF-8 分片、多行 data、Last-Event-ID 和有界重连;权限或会话失效终止观察。卸载时调用 `close()` 并等待 `done`,不会取消服务端业务运行。缓存重查由宿主负责。
35
+
36
+ 独立业务模块直接将自身 Goa 生成的描述符传给同一个客户端。TypeScript 生成器公开为 `create-arcbase/goa-contracts`,不能自行维护第二份请求 schema。
37
+
38
+ ## 验证
39
+
40
+ ```sh
41
+ npm run check:types -w @fudanda/client
42
+ npm run test:client
43
+ npm run lint -w @fudanda/client
44
+ npm run check:boundaries
45
+ ```
46
+
47
+ 两套管理台通过 `@fudanda/react-core` 共享会话、Query、缓存失效和文件适配。完整协议与权限说明见 [集成扩展](../../docs/guide/go-integrations.md)。
@@ -0,0 +1,12 @@
1
+ export interface SSEFrame {
2
+ event: string;
3
+ data?: string;
4
+ id?: string;
5
+ retry?: number;
6
+ }
7
+ export declare class SSEProtocolError extends Error {
8
+ }
9
+ /** Incremental SSE framing. Bound each frame before retaining its text. */
10
+ export declare function readSSE(body: ReadableStream<Uint8Array>, signal: AbortSignal): AsyncGenerator<SSEFrame>;
11
+ export declare function waitForReconnect(milliseconds: number, signal: AbortSignal): Promise<void>;
12
+ //# sourceMappingURL=goa-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goa-stream.d.ts","sourceRoot":"","sources":["../src/goa-stream.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IAAG,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE;AAEvF,qBAAa,gBAAiB,SAAQ,KAAK;CAAG;AAE9C,2EAA2E;AAC3E,wBAAuB,OAAO,CAAC,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,WAAW,GAAG,cAAc,CAAC,QAAQ,CAAC,CAiE9G;AAED,wBAAgB,gBAAgB,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAOzF"}
@@ -0,0 +1,117 @@
1
+ export class SSEProtocolError extends Error {
2
+ }
3
+ /** Incremental SSE framing. Bound each frame before retaining its text. */
4
+ export async function* readSSE(body, signal) {
5
+ const reader = body.getReader();
6
+ const decoder = new TextDecoder('utf-8', { fatal: true });
7
+ const encoder = new TextEncoder();
8
+ let line = '', event = '', data = [], id, retry;
9
+ let frameBytes = 0, afterCR = false, finished = false, cancelled = false;
10
+ const cancel = async () => {
11
+ if (finished || cancelled)
12
+ return;
13
+ cancelled = true;
14
+ try {
15
+ await reader.cancel();
16
+ }
17
+ catch { /* The original read failure is reported by the caller. */ }
18
+ };
19
+ const abort = () => { void cancel(); };
20
+ const append = (fragment) => {
21
+ frameBytes += encoder.encode(fragment).byteLength;
22
+ if (frameBytes > 512 * 1024)
23
+ throw new SSEProtocolError('SSE frame exceeds 512 KiB');
24
+ line += fragment;
25
+ };
26
+ const consume = () => {
27
+ const current = line;
28
+ line = '';
29
+ if (!current) {
30
+ const frame = data.length || id !== undefined || retry !== undefined ? { event: event || 'message', data: data.length ? data.join('\n') : undefined, id, retry } : undefined;
31
+ event = '';
32
+ data = [];
33
+ id = undefined;
34
+ retry = undefined;
35
+ frameBytes = 0;
36
+ return frame;
37
+ }
38
+ if (current.startsWith(':')) {
39
+ frameBytes -= encoder.encode(current).byteLength;
40
+ return;
41
+ }
42
+ const colon = current.indexOf(':');
43
+ const field = colon === -1 ? current : current.slice(0, colon);
44
+ let value = colon === -1 ? '' : current.slice(colon + 1);
45
+ if (value.startsWith(' '))
46
+ value = value.slice(1);
47
+ if (field === 'event')
48
+ event = value;
49
+ else if (field === 'data')
50
+ data.push(value);
51
+ else if (field === 'id' && !value.includes('\0'))
52
+ id = value;
53
+ else if (field === 'retry' && /^\d+$/.test(value) && Number.isSafeInteger(Number(value)))
54
+ retry = Number(value);
55
+ };
56
+ signal.addEventListener('abort', abort, { once: true });
57
+ try {
58
+ signal.throwIfAborted();
59
+ while (true) {
60
+ const part = await reader.read();
61
+ signal.throwIfAborted();
62
+ if (part.done) {
63
+ finished = true;
64
+ break;
65
+ }
66
+ let text;
67
+ try {
68
+ text = decoder.decode(part.value, { stream: true });
69
+ }
70
+ catch {
71
+ throw new SSEProtocolError('SSE contains invalid UTF-8');
72
+ }
73
+ let start = 0;
74
+ for (let index = 0; index < text.length; index++) {
75
+ const char = text[index];
76
+ if (afterCR) {
77
+ afterCR = false;
78
+ if (char === '\n') {
79
+ start = index + 1;
80
+ continue;
81
+ }
82
+ }
83
+ if (char !== '\r' && char !== '\n')
84
+ continue;
85
+ append(text.slice(start, index));
86
+ const frame = consume();
87
+ if (frame)
88
+ yield frame;
89
+ afterCR = char === '\r';
90
+ start = index + 1;
91
+ }
92
+ append(text.slice(start));
93
+ }
94
+ try {
95
+ decoder.decode();
96
+ }
97
+ catch {
98
+ throw new SSEProtocolError('SSE contains incomplete UTF-8');
99
+ }
100
+ // The SSE protocol discards a final event without its empty-line delimiter.
101
+ }
102
+ finally {
103
+ signal.removeEventListener('abort', abort);
104
+ await cancel();
105
+ reader.releaseLock();
106
+ }
107
+ }
108
+ export function waitForReconnect(milliseconds, signal) {
109
+ return new Promise(resolve => {
110
+ const finish = () => { clearTimeout(timer); signal.removeEventListener('abort', finish); resolve(); };
111
+ const timer = setTimeout(finish, milliseconds);
112
+ signal.addEventListener('abort', finish, { once: true });
113
+ if (signal.aborted)
114
+ finish();
115
+ });
116
+ }
117
+ //# sourceMappingURL=goa-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goa-stream.js","sourceRoot":"","sources":["../src/goa-stream.ts"],"names":[],"mappings":"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"}
package/dist/goa.d.ts ADDED
@@ -0,0 +1,81 @@
1
+ import type { GoaInputOf, GoaOperation, GoaOutputOf } from '@fudanda/shared/core';
2
+ export interface GoaClientOptions {
3
+ baseURL?: string;
4
+ credentials?: RequestCredentials;
5
+ transport?: typeof fetch;
6
+ xhrFactory?: () => XMLHttpRequest;
7
+ apiKey?: string;
8
+ csrfToken?: string;
9
+ onUnauthorized?: () => void;
10
+ }
11
+ export interface GoaRequestOptions {
12
+ signal?: AbortSignal | null;
13
+ headers?: HeadersInit;
14
+ }
15
+ export interface GoaUploadOptions extends GoaRequestOptions {
16
+ onProgress?: (percent: number) => void;
17
+ }
18
+ export type GoaConnectionState = 'connecting' | 'connected' | 'reconnecting' | 'closed';
19
+ export interface GoaStreamOptions<Data> extends GoaRequestOptions {
20
+ onEvent: (event: Data) => void;
21
+ onConnection?: (state: GoaConnectionState) => void;
22
+ onError?: (error: Error) => void;
23
+ reconnectDelay?: number;
24
+ }
25
+ export interface GoaSubscription {
26
+ close(): void;
27
+ done: Promise<void>;
28
+ }
29
+ export declare class GoaError extends Error {
30
+ readonly status: number;
31
+ readonly reason: string;
32
+ readonly name = "GoaError";
33
+ errorId?: string;
34
+ requestId?: string;
35
+ temporary: boolean;
36
+ timeout: boolean;
37
+ fault: boolean;
38
+ details?: unknown;
39
+ constructor(status: number, reason: string, message: string);
40
+ }
41
+ type Arguments<Operation extends GoaOperation> = undefined extends GoaInputOf<Operation> ? [input?: GoaInputOf<Operation>, options?: GoaRequestOptions] : [input: GoaInputOf<Operation>, options?: GoaRequestOptions];
42
+ type UploadArguments<Operation extends GoaOperation> = [input: GoaInputOf<Operation>, options?: GoaUploadOptions];
43
+ export interface GoaResponse<Data> {
44
+ data: Data;
45
+ status: number;
46
+ headers: Headers;
47
+ }
48
+ /** Native Goa HTTP client. Generated schemas own request and response shapes. */
49
+ export declare class GoaClient {
50
+ private readonly options;
51
+ private csrfToken;
52
+ private sessionRevision;
53
+ private readonly responseSessions;
54
+ private readonly unauthorizedListeners;
55
+ constructor(options?: GoaClientOptions);
56
+ setCSRFToken(token: string): void;
57
+ clearSession(): void;
58
+ sessionHeaders(): Record<string, string>;
59
+ subscribeUnauthorized(listener: () => void): () => void;
60
+ expireSession(): void;
61
+ call<Operation extends GoaOperation>(operation: Operation, ...args: Arguments<Operation>): Promise<GoaOutputOf<Operation>>;
62
+ callWithResponse<Operation extends GoaOperation>(operation: Operation, ...args: Arguments<Operation>): Promise<GoaResponse<GoaOutputOf<Operation>>>;
63
+ upload<Operation extends GoaOperation & {
64
+ readonly kind: 'multipart';
65
+ }>(operation: Operation, ...args: UploadArguments<Operation>): Promise<GoaOutputOf<Operation>>;
66
+ /** Observe a generated GET stream; closing it never cancels domain execution. */
67
+ stream<Operation extends GoaOperation & {
68
+ readonly kind: 'sse';
69
+ }>(operation: Operation, input: GoaInputOf<Operation>, options: GoaStreamOptions<GoaOutputOf<Operation>>): GoaSubscription;
70
+ /** The caller consumes or cancels the returned body; the transport never buffers files. */
71
+ download<Operation extends GoaOperation & {
72
+ readonly kind: 'file' | 'csv';
73
+ }>(operation: Operation, ...args: Arguments<Operation>): Promise<Response>;
74
+ private execute;
75
+ private requireCurrentSession;
76
+ private fetch;
77
+ private sendUpload;
78
+ private error;
79
+ }
80
+ export {};
81
+ //# sourceMappingURL=goa.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goa.d.ts","sourceRoot":"","sources":["../src/goa.ts"],"names":[],"mappings":"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"}