From 0509114aa87499fd275b33ed1091bfbdff36a5d7 Mon Sep 17 00:00:00 2001 From: Wenzhao Hu Date: Fri, 13 Dec 2024 17:08:02 +0800 Subject: [PATCH] feat(network): add network FacadeAPI (#4294) --- packages/network/package.json | 13 ++- packages/network/src/facade/f-network.ts | 95 +++++++++++++++++++ packages/network/src/facade/f-univer.ts | 37 ++++++++ packages/network/src/facade/index.ts | 20 ++++ .../network/src/services/http/http.service.ts | 27 +++--- 5 files changed, 177 insertions(+), 15 deletions(-) create mode 100644 packages/network/src/facade/f-network.ts create mode 100644 packages/network/src/facade/f-univer.ts create mode 100644 packages/network/src/facade/index.ts diff --git a/packages/network/package.json b/packages/network/package.json index bc30bb50541..3d47de452a0 100644 --- a/packages/network/package.json +++ b/packages/network/package.json @@ -21,7 +21,8 @@ ], "exports": { ".": "./src/index.ts", - "./*": "./src/*" + "./*": "./src/*", + "./facade": "./src/facade/index.ts" }, "main": "./src/index.ts", "types": "./lib/types/index.d.ts", @@ -40,6 +41,11 @@ "require": "./lib/cjs/*", "types": "./lib/types/index.d.ts" }, + "./facade": { + "import": "./lib/es/facade.js", + "require": "./lib/cjs/facade.js", + "types": "./lib/types/facade/index.d.ts" + }, "./lib/*": "./lib/*" } }, @@ -80,6 +86,11 @@ "require": "./lib/cjs/*", "types": "./lib/types/index.d.ts" }, + "./facade": { + "import": "./lib/es/facade.js", + "require": "./lib/cjs/facade.js", + "types": "./lib/types/facade/index.d.ts" + }, "./lib/*": "./lib/*" } } diff --git a/packages/network/src/facade/f-network.ts b/packages/network/src/facade/f-network.ts new file mode 100644 index 00000000000..10cb9fca847 --- /dev/null +++ b/packages/network/src/facade/f-network.ts @@ -0,0 +1,95 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import type { HTTPEvent, HTTPRequestMethod, HTTPResponse, IPostRequestParams, IRequestParams } from '@univerjs/network'; +import type { Observable } from 'rxjs'; +import { FBase, Inject, Injector } from '@univerjs/core'; +import { HTTPService } from '@univerjs/network'; + +export class FNetwork extends FBase { + constructor( + @Inject(Injector) protected readonly _injector: Injector, + @Inject(HTTPService) protected readonly _httpService: HTTPService + ) { + super(); + } + + /** + * Send GET request to the server. + * @param url The requested URL + * @param params Query parameters + * @returns Network response + */ + get(url: string, params?: IRequestParams): Promise> { + return this._httpService.get(url, params) as Promise>; ; + } + + /** + * Send POST request to the server. + * @param url The requested URL + * @param params Query parameters + * @returns Network response + */ + post(url: string, params?: IPostRequestParams): Promise> { + return this._httpService.post(url, params) as Promise>; ; + } + + /** + * Send PUT request to the server. + * @param url The requested URL + * @param params Query parameters + * @returns Network response + */ + put(url: string, params?: IPostRequestParams): Promise> { + return this._httpService.put(url, params) as Promise>; ; + } + + /** + * Send DELETE request to the server. + * @param url The requested URL + * @param params Query parameters + * @returns Network response + */ + delete(url: string, params?: IRequestParams): Promise> { + return this._httpService.delete(url, params) as Promise>; ; + } + + /** + * Send PATCH request to the server. + * @param url The requested URL + * @param params Query parameters + * @returns Network response + */ + patch(url: string, params?: IPostRequestParams): Promise> { + return this._httpService.patch(url, params) as Promise>; + } + + /** + * Request for a stream of server-sent events. Instead of a single response, the server sends a stream of responses, + * Univer wraps the stream in an [`Observable`](https://rxjs.dev/guide/observable) which you can call `subscribe` on. + * @param method HTTP request method + * @param url The requested URL + * @param params Query parameters + * @returns An observable that emits the network response + */ + getSSE( + method: HTTPRequestMethod, + url: string, + params?: IPostRequestParams + ): Observable> { + return this._httpService.getSSE(method, url, params); + } +} diff --git a/packages/network/src/facade/f-univer.ts b/packages/network/src/facade/f-univer.ts new file mode 100644 index 00000000000..156e4854119 --- /dev/null +++ b/packages/network/src/facade/f-univer.ts @@ -0,0 +1,37 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { FUniver } from '@univerjs/core'; +import { FNetwork } from './f-network'; + +interface IFUniverNetworkMixin { + /** + * Get the network API of Univer, with the help of which you can send HTTP requests. + */ + getNetwork(): FNetwork; +} + +export class FUniverNetworkMixin extends FUniver implements IFUniverNetworkMixin { + override getNetwork(): FNetwork { + return this._injector.createInstance(FNetwork); + } +} + +FUniver.extend(FUniverNetworkMixin); +declare module '@univerjs/core' { + // eslint-disable-next-line ts/naming-convention + interface FUniver extends IFUniverNetworkMixin { } +} diff --git a/packages/network/src/facade/index.ts b/packages/network/src/facade/index.ts new file mode 100644 index 00000000000..f1efd1a8cc6 --- /dev/null +++ b/packages/network/src/facade/index.ts @@ -0,0 +1,20 @@ +/** + * Copyright 2023-present DreamNum Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import './f-univer'; +import './f-network'; + +export type { FNetwork } from './f-network'; diff --git a/packages/network/src/services/http/http.service.ts b/packages/network/src/services/http/http.service.ts index 54ab1d63535..4672bfe91a1 100644 --- a/packages/network/src/services/http/http.service.ts +++ b/packages/network/src/services/http/http.service.ts @@ -15,19 +15,18 @@ */ import type { IDisposable, Nullable } from '@univerjs/core'; -import { Disposable, remove, toDisposable } from '@univerjs/core'; import type { Observable } from 'rxjs'; +import type { HTTPResponseType } from './http'; +import type { HTTPHandlerFn, HTTPInterceptorFn, RequestPipe } from './interceptor'; +import type { HTTPRequestMethod } from './request'; +import type { HTTPEvent } from './response'; +import { Disposable, remove, toDisposable } from '@univerjs/core'; import { firstValueFrom, of } from 'rxjs'; import { concatMap } from 'rxjs/operators'; - import { HTTPHeaders } from './headers'; -import type { HTTPResponseType } from './http'; import { IHTTPImplementation } from './implementations/implementation'; import { HTTPParams } from './params'; -import type { HTTPRequestMethod } from './request'; import { HTTPRequest } from './request'; -import type { HTTPEvent } from './response'; -import type { HTTPHandlerFn, HTTPInterceptorFn, RequestPipe } from './interceptor'; export interface IRequestParams { /** Query params. These params would be append to the url before the request is sent. */ @@ -117,27 +116,27 @@ export class HTTPService extends Disposable { return this._request('DELETE', url, params); } - patch(url: string, options?: IPostRequestParams): Promise> { - return this._request('PATCH', url, options); + patch(url: string, params?: IPostRequestParams): Promise> { + return this._request('PATCH', url, params); } getSSE( method: HTTPRequestMethod, url: string, - options?: IPostRequestParams + _params?: IPostRequestParams ): Observable> { // Things to do when sending a HTTP request: // 1. Generate HTTPRequest/HTTPHeader object // 2. Call interceptors and finally the HTTP implementation. - const headers = new HTTPHeaders(options?.headers); - const params = new HTTPParams(options?.params); + const headers = new HTTPHeaders(_params?.headers); + const params = new HTTPParams(_params?.params); const request = new HTTPRequest(method, url, { headers, params, - withCredentials: options?.withCredentials ?? false, + withCredentials: _params?.withCredentials ?? false, reportProgress: true, - responseType: options?.responseType ?? 'json', - body: (['GET', 'DELETE'].includes(method)) ? undefined : (options as IPostRequestParams)?.body, + responseType: _params?.responseType ?? 'json', + body: (['GET', 'DELETE'].includes(method)) ? undefined : (_params as IPostRequestParams)?.body, }); return of(request).pipe(concatMap((request) => this._runInterceptorsAndImplementation(request)));