create-secra 0.1.0 → 0.1.2

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.
Files changed (38) hide show
  1. package/README.md +3 -5
  2. package/bin/index.mjs +15 -11
  3. package/package.json +4 -6
  4. package/template/apps/core/index.html +13 -0
  5. package/template/apps/core/package.json +18 -0
  6. package/template/apps/core/public/favicon.ico +1 -0
  7. package/template/apps/core/public/favicon.svg +1 -0
  8. package/template/apps/core/public/logo.svg +1 -0
  9. package/template/apps/core/src/assets/react.svg +1 -0
  10. package/template/apps/core/src/main.tsx +21 -0
  11. package/template/apps/core/src/pages/index.tsx +4 -0
  12. package/template/apps/core/src/router.ts +15 -0
  13. package/template/apps/core/src/types/auto-imports.d.ts +130 -0
  14. package/template/apps/core/tsconfig.app.json +7 -0
  15. package/template/apps/core/tsconfig.json +7 -0
  16. package/template/apps/core/tsconfig.node.json +7 -0
  17. package/template/apps/core/vite.config.ts +86 -0
  18. package/template/eslint.config.js +23 -0
  19. package/template/package.json +60 -0
  20. package/template/packages/sdk/.swcrc +18 -0
  21. package/template/packages/sdk/package-lock.json +1621 -0
  22. package/template/packages/sdk/package.json +32 -0
  23. package/template/packages/sdk/src/build/index.ts +33 -0
  24. package/template/packages/sdk/src/build/plugins/auto-import.ts +47 -0
  25. package/template/packages/sdk/src/build/plugins/bundle-analyzer.ts +35 -0
  26. package/template/packages/sdk/src/build/plugins/remove-console.ts +21 -0
  27. package/template/packages/sdk/src/build/plugins/unocss.ts +110 -0
  28. package/template/packages/sdk/src/build/plugins/unplugin-icon.ts +43 -0
  29. package/template/packages/sdk/src/index.ts +1 -0
  30. package/template/packages/sdk/src/request/index.ts +341 -0
  31. package/template/packages/sdk/src/styles/reset.css +111 -0
  32. package/template/packages/sdk/tsconfig.json +16 -0
  33. package/template/pnpm-lock.yaml +8055 -0
  34. package/template/pnpm-workspace.yaml +3 -0
  35. package/template/tsconfig.app.json +29 -0
  36. package/template/tsconfig.json +7 -0
  37. package/template/tsconfig.node.json +27 -0
  38. package/template/turbo.json +17 -0
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@vlian/sdk",
3
+ "version": "1.0.2",
4
+ "description": "",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "types": "dist/types/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/types/index.d.ts",
11
+ "import": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./request": {
15
+ "types": "./dist/types/request/index.d.ts",
16
+ "import": "./dist/request/index.js",
17
+ "default": "./dist/request/index.js"
18
+ },
19
+ "./reset.css": "./dist/styles/reset.css"
20
+ },
21
+ "scripts": {
22
+ "build": "pnpm run build:js && pnpm run build:types && pnpm run build:assets",
23
+ "build:js": "swc src -d dist --config-file .swcrc --source-maps --strip-leading-paths",
24
+ "build:types": "tsc -p tsconfig.json --emitDeclarationOnly --declaration --declarationMap --outDir dist/types",
25
+ "build:assets": "mkdir -p dist/styles && cp src/styles/reset.css dist/styles/reset.css"
26
+ },
27
+ "devDependencies": {
28
+ "@swc/cli": "^0.7.3",
29
+ "@swc/core": "^1.13.5"
30
+ },
31
+ "private": true
32
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * @react-plugins/build
3
+ * 构建工具和配置共享包
4
+ *
5
+ * 提供统一的 Vite 插件配置,供 Monorepo 中所有应用使用
6
+ */
7
+
8
+ // 导出版本
9
+ export const version = '0.0.1';
10
+
11
+ // 插件导出
12
+ export { setupAutoImport } from './plugins/auto-import.js';
13
+ export { setupUnocss } from './plugins/unocss.js';
14
+ export { setupUnPluginIcon } from './plugins/unplugin-icon.js';
15
+ export { setupRemoveConsole } from './plugins/remove-console.js';
16
+ export { setupBundleAnalyzer } from './plugins/bundle-analyzer.js';
17
+
18
+ // 工具导出
19
+ export { default as Inspect } from 'vite-plugin-inspect';
20
+ export { default as removeConsole } from 'vite-plugin-remove-console';
21
+
22
+ // 依赖优化列表(用于 optimizeDeps.include)
23
+ export const include = [
24
+ 'ahooks',
25
+ 'i18next',
26
+ 'lodash',
27
+ 'immer',
28
+ 'react-i18next',
29
+ ] as const;
30
+
31
+ // 类型导出
32
+ export type { Plugin } from 'vite';
33
+ export type { UserConfig } from '@unocss/core';
@@ -0,0 +1,47 @@
1
+ import AutoImport from 'unplugin-auto-import/vite';
2
+ import IconsResolver from 'unplugin-icons/resolver';
3
+ import type { Plugin } from 'vite';
4
+
5
+ /**
6
+ * 自动导入配置
7
+ *
8
+ * 功能:
9
+ * - 自动导入 React、React Router、ahooks 等常用库
10
+ * - 自动导入图标组件
11
+ * - 自动导入自定义 hooks 和组件
12
+ */
13
+ export function setupAutoImport(): Plugin | Plugin[] {
14
+ return AutoImport({
15
+ // 扫描目录,自动导入 hooks 和组件
16
+ dirs: ['src/hooks/**', 'src/components/**'],
17
+
18
+ // 自动导入类型声明文件
19
+ dts: 'src/types/auto-imports.d.ts',
20
+
21
+ // 自动导入的库
22
+ imports: [
23
+ 'react',
24
+ 'react-router-dom',
25
+ 'react-i18next',
26
+ 'ahooks',
27
+ // React 类型导入
28
+ { from: 'react', imports: ['FC', 'ReactNode', 'ComponentType'], type: true },
29
+ ],
30
+
31
+ // 匹配的文件
32
+ include: [/\.[tj]sx?$/],
33
+
34
+ // 排除的文件(排除文档文件和其他非代码文件)
35
+ exclude: [/\.md$/, /\.d\.ts$/, /\.test\.(ts|tsx)$/, /\.spec\.(ts|tsx)$/],
36
+
37
+ // 解析器
38
+ resolvers: [
39
+ // 图标解析器
40
+ IconsResolver({
41
+ customCollections: ['local'],
42
+ extension: 'tsx',
43
+ prefix: 'icon',
44
+ }),
45
+ ],
46
+ });
47
+ }
@@ -0,0 +1,35 @@
1
+ import { visualizer } from 'rollup-plugin-visualizer';
2
+ import type { Plugin } from 'vite';
3
+
4
+ /**
5
+ * 打包分析插件
6
+ *
7
+ * 功能:
8
+ * - 生成打包分析报告
9
+ * - 可视化 bundle 大小
10
+ * - 帮助优化打包体积
11
+ *
12
+ * @param options - 配置选项
13
+ * @returns Vite 插件
14
+ */
15
+ export function setupBundleAnalyzer(options?: {
16
+ /** 输出文件名(默认: stats.html) */
17
+ filename?: string;
18
+ /** 是否自动打开浏览器 */
19
+ open?: boolean;
20
+ /** 输出格式(默认: html) */
21
+ template?: 'treemap' | 'sunburst' | 'network';
22
+ /** 是否 gzip 压缩 */
23
+ gzipSize?: boolean;
24
+ /** 是否 brotli 压缩 */
25
+ brotliSize?: boolean;
26
+ }): Plugin | Plugin[] {
27
+ return visualizer({
28
+ filename: options?.filename || 'dist/stats.html',
29
+ open: options?.open ?? true,
30
+ template: options?.template || 'treemap',
31
+ gzipSize: options?.gzipSize ?? true,
32
+ brotliSize: options?.brotliSize ?? true,
33
+ }) as Plugin;
34
+ }
35
+
@@ -0,0 +1,21 @@
1
+ import removeConsole from 'vite-plugin-remove-console';
2
+ import type { Plugin } from 'vite';
3
+
4
+ /**
5
+ * 移除 console 插件
6
+ *
7
+ * 功能:
8
+ * - 生产环境自动移除 console 语句
9
+ * - 提升生产环境性能
10
+ *
11
+ * @param options - 配置选项
12
+ * @returns Vite 插件
13
+ */
14
+ export function setupRemoveConsole(options?: {
15
+ /** 需要移除的 console 方法 */
16
+ include?: string[];
17
+ }): Plugin | Plugin[] {
18
+ return removeConsole({
19
+ external: options?.include || ['log', 'info', 'debug', 'warn'],
20
+ }) as Plugin | Plugin[];
21
+ }
@@ -0,0 +1,110 @@
1
+ import { FileSystemIconLoader } from '@iconify/utils/lib/loader/node-loaders';
2
+ import presetAttributify from '@unocss/preset-attributify';
3
+ import presetIcons from '@unocss/preset-icons';
4
+ import presetUno from '@unocss/preset-uno';
5
+ import transformerDirectives from '@unocss/transformer-directives';
6
+ import transformerVariantGroup from '@unocss/transformer-variant-group';
7
+ import unocss from '@unocss/vite';
8
+ import type { UserConfig } from '@unocss/core';
9
+
10
+ /**
11
+ * UnoCSS 配置
12
+ *
13
+ * 功能:
14
+ * - 集成 UnoCSS
15
+ * - 支持本地 SVG 图标
16
+ * - 包含完整的预设和转换器
17
+ * - 支持属性化模式(Attributify)
18
+ *
19
+ * @param localIconPath - 本地图标路径
20
+ * @param unocssConfig - UnoCSS 配置(可选,用于合并其他配置)
21
+ */
22
+ export function setupUnocss(
23
+ localIconPath: string,
24
+ unocssConfig?: Partial<UserConfig>
25
+ ): ReturnType<typeof unocss> {
26
+ return unocss({
27
+ presets: [
28
+ // 基础预设 - 包含 Tailwind CSS 兼容的工具类
29
+ presetUno(),
30
+ // 属性化模式 - 支持 <div bg="blue-400" /> 语法
31
+ presetAttributify(),
32
+ // 图标预设 - 支持本地 SVG 图标
33
+ presetIcons({
34
+ collections: {
35
+ // 本地图标集合
36
+ local: FileSystemIconLoader(localIconPath, (svg) =>
37
+ svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
38
+ ),
39
+ },
40
+ extraProperties: {
41
+ display: 'inline-block',
42
+ },
43
+ prefix: 'icon-',
44
+ scale: 1,
45
+ warn: true,
46
+ }),
47
+ ],
48
+ // 转换器
49
+ transformers: [
50
+ transformerDirectives(), // 支持 @apply、@screen 等指令
51
+ transformerVariantGroup(), // 支持 variant groups (hover:bg-gray-400 hover:text-white)
52
+ ],
53
+ // 主题配置
54
+ theme: {
55
+ colors: {},
56
+ breakpoints: {
57
+ xs: '320px',
58
+ sm: '640px',
59
+ md: '768px',
60
+ lg: '1024px',
61
+ xl: '1280px',
62
+ '2xl': '1536px',
63
+ },
64
+ },
65
+ // 快捷方式 - 组合多个工具类
66
+ shortcuts: {
67
+ // 按钮样式
68
+ 'btn': 'px-4 py-2 rounded font-semibold transition-colors duration-200',
69
+ 'btn-primary': 'btn bg-primary-500 text-white hover:bg-primary-600 active:bg-primary-700',
70
+ 'btn-secondary': 'btn bg-gray-500 text-white hover:bg-gray-600 active:bg-gray-700',
71
+ 'btn-success': 'btn bg-success-500 text-white hover:bg-success-600 active:bg-success-700',
72
+ 'btn-warning': 'btn bg-warning-500 text-white hover:bg-warning-600 active:bg-warning-700',
73
+ 'btn-error': 'btn bg-error-500 text-white hover:bg-error-600 active:bg-error-700',
74
+ 'btn-outline': 'btn border-2 bg-transparent hover:bg-gray-100',
75
+ 'btn-ghost': 'btn bg-transparent hover:bg-gray-100',
76
+ // 容器样式
77
+ 'container': 'mx-auto px-4 sm:px-6 lg:px-8',
78
+ 'container-sm': 'mx-auto px-4 sm:px-6 max-w-screen-sm',
79
+ 'container-md': 'mx-auto px-4 sm:px-6 max-w-screen-md',
80
+ 'container-lg': 'mx-auto px-4 sm:px-6 max-w-screen-lg',
81
+ 'container-xl': 'mx-auto px-4 sm:px-6 max-w-screen-xl',
82
+ // 卡片样式
83
+ 'card': 'bg-white rounded-lg shadow-sm border border-gray-200',
84
+ 'card-header': 'px-6 py-4 border-b border-gray-200',
85
+ 'card-body': 'px-6 py-4',
86
+ 'card-footer': 'px-6 py-4 border-t border-gray-200',
87
+ // 输入框样式
88
+ 'input': 'px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary-500 focus:border-transparent',
89
+ 'input-error': 'input border-error-500 focus:ring-error-500',
90
+ // 布局样式
91
+ 'flex-center': 'flex items-center justify-center',
92
+ 'flex-between': 'flex items-center justify-between',
93
+ 'flex-start': 'flex items-center justify-start',
94
+ 'flex-end': 'flex items-center justify-end',
95
+ },
96
+ // 自定义规则
97
+ rules: [
98
+ // 可以在这里添加项目特定的工具类
99
+ // 示例:['custom-rule', { color: 'red' }],
100
+ ],
101
+ // 安全列表 - 确保这些类名始终被生成(即使没有被扫描到)
102
+ safelist: [
103
+ // 可以添加动态生成的类名
104
+ // 例如:'bg-red-500', 'bg-blue-500',
105
+ // 或者使用正则:/^bg-(red|blue|green)-\d+$/,
106
+ ],
107
+ // 合并用户自定义配置(会覆盖上面的默认配置)
108
+ ...unocssConfig,
109
+ });
110
+ }
@@ -0,0 +1,43 @@
1
+ import { FileSystemIconLoader } from 'unplugin-icons/loaders';
2
+ import Icons from 'unplugin-icons/vite';
3
+ import { createSvgIconsPlugin } from 'vite-plugin-svg-icons';
4
+
5
+ /**
6
+ * 图标插件配置
7
+ *
8
+ * 功能:
9
+ * - SVG 图标支持(vite-plugin-svg-icons)
10
+ * - 图标组件自动导入(unplugin-icons)
11
+ * - 支持本地 SVG 图标
12
+ *
13
+ * @param localIconPath - 本地图标路径
14
+ * @param customDomId - 自定义 DOM ID(默认: __SVG_ICON_LOCAL__)
15
+ * @returns 插件数组
16
+ */
17
+ export function setupUnPluginIcon(
18
+ localIconPath: string,
19
+ customDomId = '__SVG_ICON_LOCAL__'
20
+ ): Array<ReturnType<typeof createSvgIconsPlugin> | ReturnType<typeof Icons>> {
21
+ return [
22
+ // SVG 图标插件 - 用于 <svg><use xlink:href="#icon-local-xxx" /></svg> 方式
23
+ createSvgIconsPlugin({
24
+ customDomId,
25
+ iconDirs: [localIconPath],
26
+ inject: 'body-last',
27
+ symbolId: 'icon-local-[dir]-[name]',
28
+ }),
29
+
30
+ // 图标组件插件 - 用于 <IconLocalXxx /> 组件方式
31
+ Icons({
32
+ compiler: 'jsx',
33
+ customCollections: {
34
+ local: FileSystemIconLoader(localIconPath, (svg) =>
35
+ svg.replace(/^<svg\s/, '<svg width="1em" height="1em" ')
36
+ ),
37
+ },
38
+ defaultClass: 'inline-block',
39
+ jsx: 'react',
40
+ scale: 1,
41
+ }),
42
+ ];
43
+ }
@@ -0,0 +1 @@
1
+ export * from "./build/index.js";
@@ -0,0 +1,341 @@
1
+ import {
2
+ RequestClient,
3
+ RequestError,
4
+ RequestErrorCode,
5
+ RequestErrorType,
6
+ type RequestBody,
7
+ type RequestHeaders,
8
+ type RequestOptions,
9
+ type RequestQuery,
10
+ type Response,
11
+ kyAdapter,
12
+ axiosAdapter,
13
+ PluginPriority,
14
+ type RequestPlugin,
15
+ type RequestClientConfig,
16
+ } from "@vlian/framework/request";
17
+
18
+ export interface ApiResponse<T = unknown> {
19
+ data: T;
20
+ code: number;
21
+ message: string;
22
+ }
23
+
24
+ export interface SdkRequestMeta extends Record<string, unknown> {
25
+ /** Disable default error message prompt. */
26
+ silent?: boolean;
27
+ /** Explicitly control error message prompt. */
28
+ showErrorMessage?: boolean;
29
+ }
30
+
31
+ export interface SdkRequestOptions<TResponse = unknown>
32
+ extends Omit<RequestOptions<TResponse>, "body" | "query" | "_responseType"> {
33
+ data?: RequestBody;
34
+ params?: RequestQuery;
35
+ meta?: SdkRequestMeta;
36
+ body?: RequestBody;
37
+ query?: RequestQuery;
38
+ _responseType?: SdkResponse<TResponse>;
39
+ }
40
+
41
+ export interface SdkResponse<T = unknown> {
42
+ data: T | undefined;
43
+ code: number;
44
+ message: string;
45
+ headers: RequestHeaders;
46
+ raw: unknown;
47
+ status: number;
48
+ error: boolean;
49
+ version: string;
50
+ }
51
+
52
+ const DEFAULT_MESSAGE = "消息提示";
53
+ const RESPONSE_VERSION = "1.0.0";
54
+ export const SDK_REQUEST_VERSION = RESPONSE_VERSION;
55
+
56
+ const getMessageHandler = (): ((message: string) => void) | null => {
57
+ if (typeof window === "undefined") {
58
+ return null;
59
+ }
60
+ const message = (window as unknown as { $message?: { error?: (msg: string) => void } })
61
+ .$message;
62
+ if (message && typeof message.error === "function") {
63
+ return message.error.bind(message);
64
+ }
65
+ return null;
66
+ };
67
+
68
+ const extractMessage = (payload: unknown): string | undefined => {
69
+ if (!payload || typeof payload !== "object") {
70
+ return undefined;
71
+ }
72
+ if ("error" in payload) {
73
+ const errorPayload = (payload as { error?: unknown }).error;
74
+ const errorMessage = extractMessage(errorPayload);
75
+ if (errorMessage) {
76
+ return errorMessage;
77
+ }
78
+ }
79
+ if ("message" in payload && typeof (payload as { message?: unknown }).message === "string") {
80
+ return (payload as { message: string }).message;
81
+ }
82
+ return undefined;
83
+ };
84
+
85
+ const extractErrorPayload = (error: RequestError): unknown => {
86
+ if (error.response?.data) {
87
+ return error.response.data;
88
+ }
89
+ const cause = error.cause as { response?: { data?: unknown } } | undefined;
90
+ if (cause?.response?.data) {
91
+ return cause.response.data;
92
+ }
93
+ return undefined;
94
+ };
95
+
96
+ const normalizeResponse = <T>(payload: unknown, status: number): ApiResponse<T> => {
97
+ const objectPayload = payload && typeof payload === "object" ? (payload as Record<string, unknown>) : undefined;
98
+ const hasEnvelope =
99
+ !!objectPayload && ("code" in objectPayload || "message" in objectPayload || "data" in objectPayload);
100
+ const data =
101
+ objectPayload && "data" in objectPayload
102
+ ? (objectPayload.data as T)
103
+ : (hasEnvelope ? (undefined as T) : (payload as T));
104
+ const codeValue = objectPayload && "code" in objectPayload ? objectPayload.code : status === 200 ? 0 : status;
105
+ const code = typeof codeValue === "number" ? codeValue : Number(codeValue || 0);
106
+ const message =
107
+ (objectPayload && typeof objectPayload.message === "string" && objectPayload.message) ||
108
+ DEFAULT_MESSAGE;
109
+ return {
110
+ data,
111
+ code,
112
+ message,
113
+ };
114
+ };
115
+
116
+ const createDefaultResponsePlugin = (): RequestPlugin => ({
117
+ name: "sdk-default-response",
118
+ priority: PluginPriority.HIGH,
119
+ onAfterRequest(context) {
120
+ const response = context.response as Response<unknown> | undefined;
121
+ if (!response) {
122
+ return;
123
+ }
124
+ const normalized = normalizeResponse(response.data, response.status);
125
+ const isSuccess = response.status === 200 && normalized.code === 0;
126
+ const transformed: SdkResponse<unknown> = {
127
+ data: normalized.data as unknown,
128
+ code: normalized.code,
129
+ message: normalized.message,
130
+ raw: response.raw,
131
+ headers: response.headers || {},
132
+ status: response.status,
133
+ error: !isSuccess,
134
+ version: RESPONSE_VERSION,
135
+ };
136
+ const mergedResponse = {
137
+ ...response,
138
+ data: transformed,
139
+ } as Response<SdkResponse<unknown>>;
140
+
141
+ if (isSuccess) {
142
+ return mergedResponse;
143
+ }
144
+
145
+ throw new RequestError(
146
+ normalized.message || `HTTP ${response.status} 错误`,
147
+ response.status === 200 ? RequestErrorType.UNKNOWN_ERROR : RequestErrorType.HTTP_ERROR,
148
+ response.status >= 500 ? RequestErrorCode.SERVER_ERROR : RequestErrorCode.CLIENT_ERROR,
149
+ {
150
+ status: response.status,
151
+ response: mergedResponse,
152
+ },
153
+ );
154
+ },
155
+ onError(context) {
156
+ const { error, request } = context;
157
+ if (!error || !request) {
158
+ return;
159
+ }
160
+ const meta = (request.meta || {}) as SdkRequestMeta;
161
+ if (meta.silent === true || meta.showErrorMessage === false) {
162
+ return;
163
+ }
164
+ if (error.type === RequestErrorType.ABORT_ERROR) {
165
+ return;
166
+ }
167
+ let message = error.message || "请求失败";
168
+ if (error.type === RequestErrorType.NETWORK_ERROR) {
169
+ message = "网络连接失败,请检查网络";
170
+ } else if (error.type === RequestErrorType.TIMEOUT_ERROR) {
171
+ message = "请求超时,请稍后重试";
172
+ } else {
173
+ const payload = extractErrorPayload(error);
174
+ if (payload) {
175
+ message = extractMessage(payload) || message;
176
+ }
177
+ }
178
+
179
+ const handler = getMessageHandler();
180
+ if (handler) {
181
+ handler(message);
182
+ } else if (typeof console !== "undefined") {
183
+ console.error(message);
184
+ }
185
+ },
186
+ });
187
+
188
+ const mapRequestOptions = <T>(options: SdkRequestOptions<T>): RequestOptions<SdkResponse<T>> => ({
189
+ ...options,
190
+ body: options.body ?? options.data,
191
+ query: options.query ?? options.params,
192
+ meta: options.meta as Record<string, unknown> | undefined,
193
+ });
194
+
195
+ class SdkRequestClient {
196
+ private client: RequestClient;
197
+ private initPromise?: Promise<void>;
198
+
199
+ constructor(config: RequestClientConfig) {
200
+ this.client = new RequestClient(config);
201
+ }
202
+
203
+ private async ensureInitialized() {
204
+ if (!this.initPromise) {
205
+ this.initPromise = this.client.initialize();
206
+ }
207
+ await this.initPromise;
208
+ }
209
+
210
+ async request<TResponse = unknown>(
211
+ options: SdkRequestOptions<TResponse>,
212
+ ): Promise<SdkResponse<TResponse>> {
213
+ await this.ensureInitialized();
214
+ const response = await this.client.request<unknown>(mapRequestOptions(options));
215
+ const payload = response.data as SdkResponse<TResponse> | Record<string, unknown> | null | undefined;
216
+ if (payload && typeof payload === "object" && "version" in payload) {
217
+ return payload as SdkResponse<TResponse>;
218
+ }
219
+ const normalized = normalizeResponse<TResponse>(response.data, response.status);
220
+ const isSuccess = response.status === 200 && normalized.code === 0;
221
+ return {
222
+ data: normalized.data as TResponse,
223
+ code: normalized.code,
224
+ message: normalized.message,
225
+ headers: response.headers || {},
226
+ raw: response.raw,
227
+ status: response.status,
228
+ error: !isSuccess,
229
+ version: RESPONSE_VERSION,
230
+ };
231
+ }
232
+
233
+ async get<TResponse = unknown>(
234
+ urlOrOptions: string | SdkRequestOptions<TResponse>,
235
+ options?: SdkRequestOptions<TResponse>,
236
+ ): Promise<SdkResponse<TResponse>> {
237
+ if (typeof urlOrOptions === "string") {
238
+ return this.request({
239
+ ...(options || {}),
240
+ url: urlOrOptions,
241
+ method: "GET",
242
+ });
243
+ }
244
+ return this.request({
245
+ ...urlOrOptions,
246
+ method: "GET",
247
+ });
248
+ }
249
+
250
+ async post<TResponse = unknown>(
251
+ urlOrOptions: string | SdkRequestOptions<TResponse>,
252
+ data?: RequestBody,
253
+ options?: SdkRequestOptions<TResponse>,
254
+ ): Promise<SdkResponse<TResponse>> {
255
+ if (typeof urlOrOptions === "string") {
256
+ return this.request({
257
+ ...(options || {}),
258
+ url: urlOrOptions,
259
+ method: "POST",
260
+ data,
261
+ });
262
+ }
263
+ return this.request({
264
+ ...urlOrOptions,
265
+ method: "POST",
266
+ });
267
+ }
268
+
269
+ async put<TResponse = unknown>(
270
+ urlOrOptions: string | SdkRequestOptions<TResponse>,
271
+ data?: RequestBody,
272
+ options?: SdkRequestOptions<TResponse>,
273
+ ): Promise<SdkResponse<TResponse>> {
274
+ if (typeof urlOrOptions === "string") {
275
+ return this.request({
276
+ ...(options || {}),
277
+ url: urlOrOptions,
278
+ method: "PUT",
279
+ data,
280
+ });
281
+ }
282
+ return this.request({
283
+ ...urlOrOptions,
284
+ method: "PUT",
285
+ });
286
+ }
287
+
288
+ async patch<TResponse = unknown>(
289
+ urlOrOptions: string | SdkRequestOptions<TResponse>,
290
+ data?: RequestBody,
291
+ options?: SdkRequestOptions<TResponse>,
292
+ ): Promise<SdkResponse<TResponse>> {
293
+ if (typeof urlOrOptions === "string") {
294
+ return this.request({
295
+ ...(options || {}),
296
+ url: urlOrOptions,
297
+ method: "PATCH",
298
+ data,
299
+ });
300
+ }
301
+ return this.request({
302
+ ...urlOrOptions,
303
+ method: "PATCH",
304
+ });
305
+ }
306
+
307
+ async delete<TResponse = unknown>(
308
+ urlOrOptions: string | SdkRequestOptions<TResponse>,
309
+ options?: SdkRequestOptions<TResponse>,
310
+ ): Promise<SdkResponse<TResponse>> {
311
+ if (typeof urlOrOptions === "string") {
312
+ return this.request({
313
+ ...(options || {}),
314
+ url: urlOrOptions,
315
+ method: "DELETE",
316
+ });
317
+ }
318
+ return this.request({
319
+ ...urlOrOptions,
320
+ method: "DELETE",
321
+ });
322
+ }
323
+
324
+ async setAdapter(adapter: string | (() => Promise<unknown>)) {
325
+ await this.ensureInitialized();
326
+ // @ts-expect-error - adapter type is ensured by request client
327
+ await this.client.setAdapter(adapter);
328
+ }
329
+ }
330
+
331
+ export const platformRequestClient = new SdkRequestClient({
332
+ defaultAdapter: kyAdapter,
333
+ plugins: [createDefaultResponsePlugin()],
334
+ });
335
+
336
+ export const uploadRequestClient = new SdkRequestClient({
337
+ defaultAdapter: axiosAdapter,
338
+ plugins: [createDefaultResponsePlugin()],
339
+ });
340
+
341
+ export const createSdkRequestPlugin = createDefaultResponsePlugin;