@robot-admin/request-core 0.2.0 → 0.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +102 -0
  2. package/LICENSE +21 -0
  3. package/README.md +248 -357
  4. package/SECURITY.md +14 -0
  5. package/dist/axios.cjs +134 -809
  6. package/dist/axios.cjs.map +1 -1
  7. package/dist/axios.d.cts +55 -220
  8. package/dist/axios.d.ts +55 -220
  9. package/dist/axios.js +2 -790
  10. package/dist/axios.js.map +1 -1
  11. package/dist/chunk-2JXH7SIL.js +711 -0
  12. package/dist/chunk-2JXH7SIL.js.map +1 -0
  13. package/dist/chunk-56QOEWUS.js +8 -0
  14. package/dist/chunk-56QOEWUS.js.map +1 -0
  15. package/dist/chunk-DUP3Y4DN.js +320 -0
  16. package/dist/chunk-DUP3Y4DN.js.map +1 -0
  17. package/dist/chunk-JGFRUAZT.cjs +1007 -0
  18. package/dist/chunk-JGFRUAZT.cjs.map +1 -0
  19. package/dist/chunk-KHI6XQRN.cjs +717 -0
  20. package/dist/chunk-KHI6XQRN.cjs.map +1 -0
  21. package/dist/chunk-OAZ5BUBU.js +969 -0
  22. package/dist/chunk-OAZ5BUBU.js.map +1 -0
  23. package/dist/chunk-QSDNDTOZ.js +28 -0
  24. package/dist/chunk-QSDNDTOZ.js.map +1 -0
  25. package/dist/chunk-UHXBAFY6.cjs +323 -0
  26. package/dist/chunk-UHXBAFY6.cjs.map +1 -0
  27. package/dist/chunk-WUZ43MLM.cjs +30 -0
  28. package/dist/chunk-WUZ43MLM.cjs.map +1 -0
  29. package/dist/chunk-WXHQXPS4.cjs +10 -0
  30. package/dist/chunk-WXHQXPS4.cjs.map +1 -0
  31. package/dist/crud.cjs +12 -484
  32. package/dist/crud.cjs.map +1 -1
  33. package/dist/crud.d.cts +8 -269
  34. package/dist/crud.d.ts +8 -269
  35. package/dist/crud.js +4 -487
  36. package/dist/crud.js.map +1 -1
  37. package/dist/index.cjs +136 -1302
  38. package/dist/index.cjs.map +1 -1
  39. package/dist/index.d.cts +7 -165
  40. package/dist/index.d.ts +7 -165
  41. package/dist/index.js +5 -1283
  42. package/dist/index.js.map +1 -1
  43. package/dist/naive.cjs +14 -0
  44. package/dist/naive.cjs.map +1 -0
  45. package/dist/naive.d.cts +9 -0
  46. package/dist/naive.d.ts +9 -0
  47. package/dist/naive.js +5 -0
  48. package/dist/naive.js.map +1 -0
  49. package/dist/types-BRDRqYFs.d.cts +197 -0
  50. package/dist/types-BVJhlSuh.d.cts +310 -0
  51. package/dist/types-BVJhlSuh.d.ts +310 -0
  52. package/dist/types-CUyibJZX.d.ts +197 -0
  53. package/dist/vue.cjs +93 -0
  54. package/dist/vue.cjs.map +1 -0
  55. package/dist/vue.d.cts +38 -0
  56. package/dist/vue.d.ts +38 -0
  57. package/dist/vue.js +71 -0
  58. package/dist/vue.js.map +1 -0
  59. package/package.json +60 -16
@@ -0,0 +1,197 @@
1
+ import { Ref, ShallowRef, ComputedRef } from 'vue';
2
+ import { f as RequestClient, j as RequestError } from './types-BVJhlSuh.js';
3
+
4
+ type DataRecord = object;
5
+ interface TableColumn<T = object> {
6
+ title?: string;
7
+ key?: string;
8
+ render?: (row: T, index: number) => unknown;
9
+ width?: number | string;
10
+ minWidth?: number | string;
11
+ maxWidth?: number | string;
12
+ fixed?: "left" | "right";
13
+ align?: "left" | "center" | "right";
14
+ ellipsis?: boolean | object;
15
+ sorter?: boolean | ((a: T, b: T) => number) | string;
16
+ filter?: boolean | ((value: string, row: T) => boolean);
17
+ [key: string]: unknown;
18
+ }
19
+ interface ApiEndpoints {
20
+ list: string;
21
+ get?: string;
22
+ create?: string;
23
+ update?: string;
24
+ remove?: string;
25
+ batchRemove?: string;
26
+ }
27
+ interface CrudMessageApi {
28
+ success(message: string): unknown;
29
+ error(message: string): unknown;
30
+ warning(message: string): unknown;
31
+ info?(message: string): unknown;
32
+ }
33
+ interface CrudDialogApi {
34
+ warning(options: unknown): unknown;
35
+ error(options: unknown): unknown;
36
+ success(options: unknown): unknown;
37
+ info(options: unknown): unknown;
38
+ }
39
+ interface CrudUiAdapter {
40
+ message: CrudMessageApi;
41
+ dialog?: CrudDialogApi;
42
+ }
43
+ interface TablePageState {
44
+ current: number;
45
+ size: number;
46
+ }
47
+ interface TableQueryContext<Filters, Sort> {
48
+ page: number;
49
+ pageSize: number;
50
+ paginationEnabled: boolean;
51
+ filters: Readonly<Filters>;
52
+ sort: Readonly<Sort> | null;
53
+ signal: AbortSignal;
54
+ }
55
+ interface TableQueryResult<T> {
56
+ items: T[];
57
+ total: number;
58
+ }
59
+ interface TableMutationContext {
60
+ signal: AbortSignal;
61
+ }
62
+ interface CrudMutations<T> {
63
+ create?: (row: T, context: TableMutationContext) => Promise<unknown>;
64
+ update?: (row: T, context: TableMutationContext) => Promise<unknown>;
65
+ remove?: (row: T, context: TableMutationContext) => Promise<unknown>;
66
+ batchRemove?: (rows: T[], context: TableMutationContext) => Promise<unknown>;
67
+ get?: (row: T, context: TableMutationContext) => Promise<T>;
68
+ }
69
+ interface ActionContext<T> {
70
+ data: T[];
71
+ index: number;
72
+ page: TablePageState;
73
+ paginationEnabled: boolean;
74
+ message: CrudMessageApi;
75
+ dialog: CrudDialogApi;
76
+ refresh: () => Promise<void>;
77
+ }
78
+ interface CustomAction<T> {
79
+ key: string;
80
+ label: string;
81
+ icon: string;
82
+ type?: "default" | "primary" | "info" | "success" | "warning" | "error";
83
+ handler: (row: T, context: ActionContext<T>) => void | Promise<void>;
84
+ }
85
+ interface DetailItem {
86
+ label: string;
87
+ key: string;
88
+ type?: string;
89
+ span?: number;
90
+ formatter?: (value: unknown) => string;
91
+ tagType?: string;
92
+ [key: string]: unknown;
93
+ }
94
+ interface DetailSection {
95
+ title: string;
96
+ columns: number;
97
+ items: DetailItem[];
98
+ }
99
+ interface DetailConfig {
100
+ sections: DetailSection[];
101
+ }
102
+ interface UseTableCrudConfig<T extends DataRecord, Filters extends object = Record<string, unknown>, Sort extends object = Record<string, unknown>> {
103
+ /** Legacy string endpoints. Prefer query/mutations for typed applications. */
104
+ api?: ApiEndpoints;
105
+ query?: (context: TableQueryContext<Filters, Sort>) => Promise<TableQueryResult<T> | unknown>;
106
+ mutations?: CrudMutations<T>;
107
+ client?: RequestClient;
108
+ columns?: TableColumn<T>[];
109
+ customActions?: CustomAction<T>[];
110
+ detail?: DetailConfig;
111
+ idKey?: keyof T;
112
+ defaultPageSize?: number;
113
+ defaultPaginationEnabled?: boolean;
114
+ initialFilters?: Filters;
115
+ initialSort?: Sort | null;
116
+ createNewRow?: () => T;
117
+ extractListData?: (response: unknown) => TableQueryResult<T>;
118
+ /** true keeps the historical immediate behavior; "mounted" is SSR-safe. */
119
+ autoLoad?: boolean | "mounted";
120
+ refreshAfterMutation?: boolean;
121
+ batchConcurrency?: number;
122
+ ui?: CrudUiAdapter;
123
+ detailTitle?: (row: T) => string;
124
+ onError?: (error: RequestError, operation: string) => void | Promise<void>;
125
+ }
126
+ interface DetailModal<T> {
127
+ visible: Ref<boolean>;
128
+ data: Ref<T | null>;
129
+ title: Ref<string>;
130
+ show: (row: T) => void;
131
+ close: () => void;
132
+ }
133
+ interface TableActionResult<T = unknown> {
134
+ data: T | null;
135
+ error: RequestError | null;
136
+ }
137
+ interface TableActions<T> {
138
+ edit?: (row: T) => Promise<TableActionResult<T>>;
139
+ delete?: (row: T) => Promise<TableActionResult<{
140
+ success: true;
141
+ }>>;
142
+ detail?: (row: T) => Promise<TableActionResult<T | null>>;
143
+ custom?: Array<{
144
+ key: string;
145
+ label: string;
146
+ icon: string;
147
+ type: CustomAction<T>["type"];
148
+ onClick: (row: T, index: number) => void | Promise<void>;
149
+ }>;
150
+ }
151
+ interface UseTableCrudReturn<T extends DataRecord, Filters extends object = Record<string, unknown>, Sort extends object = Record<string, unknown>> {
152
+ data: ShallowRef<T[]>;
153
+ /** Preferred semantic alias of data. */
154
+ rows: ShallowRef<T[]>;
155
+ loading: ComputedRef<boolean>;
156
+ isInitialLoading: ComputedRef<boolean>;
157
+ isRefreshing: ComputedRef<boolean>;
158
+ creating: ComputedRef<boolean>;
159
+ updating: ComputedRef<boolean>;
160
+ removing: ComputedRef<boolean>;
161
+ total: Ref<number>;
162
+ error: ShallowRef<RequestError | null>;
163
+ lastUpdated: Ref<number | null>;
164
+ columns: ComputedRef<TableColumn<T>[]>;
165
+ actions: ComputedRef<TableActions<T>>;
166
+ tableRef: Ref<unknown>;
167
+ page: TablePageState;
168
+ filters: Ref<Filters>;
169
+ sort: Ref<Sort | null>;
170
+ paginationEnabled: Ref<boolean>;
171
+ pagination: ComputedRef<false | {
172
+ enabled: true;
173
+ page: number;
174
+ pageSize: number;
175
+ itemCount: number;
176
+ }>;
177
+ refresh: () => Promise<void>;
178
+ reload: () => Promise<void>;
179
+ search: (next?: Partial<Filters>) => Promise<void>;
180
+ resetSearch: () => Promise<void>;
181
+ setSort: (next: Sort | null) => Promise<void>;
182
+ create: (row: T) => Promise<void>;
183
+ save: (row: T) => Promise<void>;
184
+ remove: (row: T) => Promise<void>;
185
+ batchRemove: (rows: T[]) => Promise<void>;
186
+ getDetail: (row: T) => Promise<T | null>;
187
+ createDraft: () => T;
188
+ cancel: () => void;
189
+ dispose: () => void;
190
+ handleCancel: () => Promise<void>;
191
+ handlePaginationChange: (page: number, pageSize: number) => void;
192
+ handleRowDelete: (row: T, index?: number) => void;
193
+ detail: DetailModal<T>;
194
+ detailConfig?: DetailConfig;
195
+ }
196
+
197
+ export type { ActionContext as A, CustomAction as C, DataRecord as D, TableColumn as T, UseTableCrudConfig as U, ApiEndpoints as a, DetailConfig as b, DetailItem as c, DetailModal as d, DetailSection as e, UseTableCrudReturn as f, CrudDialogApi as g, CrudMessageApi as h, CrudMutations as i, CrudUiAdapter as j, TableQueryContext as k, TableQueryResult as l };
package/dist/vue.cjs ADDED
@@ -0,0 +1,93 @@
1
+ 'use strict';
2
+
3
+ var chunkKHI6XQRN_cjs = require('./chunk-KHI6XQRN.cjs');
4
+ var chunkJGFRUAZT_cjs = require('./chunk-JGFRUAZT.cjs');
5
+ var vue = require('vue');
6
+
7
+ function useRequest(executor, options = {}) {
8
+ const data = vue.shallowRef(options.initialData);
9
+ const error = vue.shallowRef(null);
10
+ const pending = vue.shallowRef(0);
11
+ const loading = vue.computed(() => pending.value > 0);
12
+ let active = null;
13
+ const controllers = /* @__PURE__ */ new Set();
14
+ let sequence = 0;
15
+ const cancel = (reason) => {
16
+ sequence += 1;
17
+ for (const controller of controllers) controller.abort(reason);
18
+ controllers.clear();
19
+ active = null;
20
+ };
21
+ const run = async (...args) => {
22
+ const concurrency = options.concurrency ?? "takeLatest";
23
+ if (active && concurrency === "takeFirst") return active.promise;
24
+ if (active && concurrency === "takeLatest") active.controller.abort();
25
+ const id = ++sequence;
26
+ const controller = new AbortController();
27
+ controllers.add(controller);
28
+ if (!options.keepPreviousData) data.value = void 0;
29
+ error.value = null;
30
+ pending.value += 1;
31
+ const promise = executor({ signal: controller.signal }, ...args);
32
+ active = { controller, promise, id };
33
+ try {
34
+ const result = await promise;
35
+ if (id === sequence || concurrency === "takeFirst") {
36
+ data.value = result;
37
+ try {
38
+ await options.onSuccess?.(result);
39
+ } catch {
40
+ }
41
+ }
42
+ return result;
43
+ } catch (cause) {
44
+ const normalized = chunkJGFRUAZT_cjs.normalizeRequestError(cause);
45
+ if (!chunkJGFRUAZT_cjs.isCanceledError(normalized) && id === sequence) {
46
+ error.value = normalized;
47
+ try {
48
+ await options.onError?.(normalized);
49
+ } catch {
50
+ }
51
+ }
52
+ throw normalized;
53
+ } finally {
54
+ pending.value = Math.max(0, pending.value - 1);
55
+ controllers.delete(controller);
56
+ if (active?.id === id) active = null;
57
+ }
58
+ };
59
+ const reset = () => {
60
+ cancel();
61
+ data.value = options.initialData;
62
+ error.value = null;
63
+ };
64
+ if (vue.getCurrentScope()) vue.onScopeDispose(() => cancel());
65
+ if (options.immediate) {
66
+ void run(...options.immediateArgs ?? []).catch(() => void 0);
67
+ }
68
+ return { data, error, loading, run, cancel, reset };
69
+ }
70
+
71
+ Object.defineProperty(exports, "REQUEST_CLIENT_KEY", {
72
+ enumerable: true,
73
+ get: function () { return chunkKHI6XQRN_cjs.REQUEST_CLIENT_KEY; }
74
+ });
75
+ Object.defineProperty(exports, "createRequestPlugin", {
76
+ enumerable: true,
77
+ get: function () { return chunkKHI6XQRN_cjs.createRequestPlugin; }
78
+ });
79
+ Object.defineProperty(exports, "provideRequestClient", {
80
+ enumerable: true,
81
+ get: function () { return chunkKHI6XQRN_cjs.provideRequestClient; }
82
+ });
83
+ Object.defineProperty(exports, "useRequestClient", {
84
+ enumerable: true,
85
+ get: function () { return chunkKHI6XQRN_cjs.useRequestClient; }
86
+ });
87
+ Object.defineProperty(exports, "useTableCrud", {
88
+ enumerable: true,
89
+ get: function () { return chunkKHI6XQRN_cjs.useTableCrud; }
90
+ });
91
+ exports.useRequest = useRequest;
92
+ //# sourceMappingURL=vue.cjs.map
93
+ //# sourceMappingURL=vue.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vue/useRequest.ts"],"names":["shallowRef","computed","normalizeRequestError","isCanceledError","getCurrentScope","onScopeDispose"],"mappings":"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","file":"vue.cjs","sourcesContent":["import {\n computed,\n getCurrentScope,\n onScopeDispose,\n shallowRef,\n type ComputedRef,\n type ShallowRef,\n} from \"vue\";\nimport type { ConcurrencyPolicy } from \"../axios/types\";\nimport {\n isCanceledError,\n normalizeRequestError,\n type RequestError,\n} from \"../client/errors\";\n\nexport interface UseRequestContext {\n signal: AbortSignal;\n}\n\nexport interface UseRequestOptions<T, Args extends unknown[]> {\n initialData?: T;\n immediate?: boolean;\n immediateArgs?: Args;\n concurrency?: Extract<ConcurrencyPolicy, \"allow\" | \"takeLatest\" | \"takeFirst\">;\n keepPreviousData?: boolean;\n onSuccess?: (data: T) => void | Promise<void>;\n onError?: (error: RequestError) => void | Promise<void>;\n}\n\nexport interface UseRequestReturn<T, Args extends unknown[]> {\n data: ShallowRef<T | undefined>;\n error: ShallowRef<RequestError | null>;\n loading: ComputedRef<boolean>;\n run: (...args: Args) => Promise<T>;\n cancel: (reason?: unknown) => void;\n reset: () => void;\n}\n\nexport function useRequest<T, Args extends unknown[] = []>(\n executor: (context: UseRequestContext, ...args: Args) => Promise<T>,\n options: UseRequestOptions<T, Args> = {},\n): UseRequestReturn<T, Args> {\n const data = shallowRef<T | undefined>(options.initialData);\n const error = shallowRef<RequestError | null>(null);\n const pending = shallowRef(0);\n const loading = computed(() => pending.value > 0);\n let active: { controller: AbortController; promise: Promise<T>; id: number } | null =\n null;\n const controllers = new Set<AbortController>();\n let sequence = 0;\n\n const cancel = (reason?: unknown): void => {\n sequence += 1;\n for (const controller of controllers) controller.abort(reason);\n controllers.clear();\n active = null;\n };\n\n const run = async (...args: Args): Promise<T> => {\n const concurrency = options.concurrency ?? \"takeLatest\";\n if (active && concurrency === \"takeFirst\") return active.promise;\n if (active && concurrency === \"takeLatest\") active.controller.abort();\n\n const id = ++sequence;\n const controller = new AbortController();\n controllers.add(controller);\n if (!options.keepPreviousData) data.value = undefined;\n error.value = null;\n pending.value += 1;\n\n const promise = executor({ signal: controller.signal }, ...args);\n active = { controller, promise, id };\n try {\n const result = await promise;\n if (id === sequence || concurrency === \"takeFirst\") {\n data.value = result;\n try {\n await options.onSuccess?.(result);\n } catch {\n // Lifecycle callbacks must not turn a successful request into a failure.\n }\n }\n return result;\n } catch (cause) {\n const normalized = normalizeRequestError(cause);\n if (!isCanceledError(normalized) && id === sequence) {\n error.value = normalized;\n try {\n await options.onError?.(normalized);\n } catch {\n // Preserve the original request error if an observer fails.\n }\n }\n throw normalized;\n } finally {\n pending.value = Math.max(0, pending.value - 1);\n controllers.delete(controller);\n if (active?.id === id) active = null;\n }\n };\n\n const reset = (): void => {\n cancel();\n data.value = options.initialData;\n error.value = null;\n };\n\n if (getCurrentScope()) onScopeDispose(() => cancel());\n if (options.immediate) {\n void run(...(options.immediateArgs ?? ([] as unknown as Args))).catch(() => undefined);\n }\n\n return { data, error, loading, run, cancel, reset };\n}\n"]}
package/dist/vue.d.cts ADDED
@@ -0,0 +1,38 @@
1
+ import { InjectionKey, App, ShallowRef, ComputedRef } from 'vue';
2
+ import { f as RequestClient, d as ConcurrencyPolicy, j as RequestError } from './types-BVJhlSuh.cjs';
3
+ import { D as DataRecord, U as UseTableCrudConfig, f as UseTableCrudReturn } from './types-BRDRqYFs.cjs';
4
+ export { A as ActionContext, a as ApiEndpoints, g as CrudDialogApi, h as CrudMessageApi, i as CrudMutations, j as CrudUiAdapter, C as CustomAction, b as DetailConfig, c as DetailItem, d as DetailModal, e as DetailSection, T as TableColumn, k as TableQueryContext, l as TableQueryResult } from './types-BRDRqYFs.cjs';
5
+ import 'axios';
6
+
7
+ declare const REQUEST_CLIENT_KEY: InjectionKey<RequestClient>;
8
+ declare function createRequestPlugin(client: RequestClient): {
9
+ install(app: App): void;
10
+ };
11
+ declare function provideRequestClient(client: RequestClient): RequestClient;
12
+ declare function useRequestClient(optional?: boolean): RequestClient | undefined;
13
+
14
+ interface UseRequestContext {
15
+ signal: AbortSignal;
16
+ }
17
+ interface UseRequestOptions<T, Args extends unknown[]> {
18
+ initialData?: T;
19
+ immediate?: boolean;
20
+ immediateArgs?: Args;
21
+ concurrency?: Extract<ConcurrencyPolicy, "allow" | "takeLatest" | "takeFirst">;
22
+ keepPreviousData?: boolean;
23
+ onSuccess?: (data: T) => void | Promise<void>;
24
+ onError?: (error: RequestError) => void | Promise<void>;
25
+ }
26
+ interface UseRequestReturn<T, Args extends unknown[]> {
27
+ data: ShallowRef<T | undefined>;
28
+ error: ShallowRef<RequestError | null>;
29
+ loading: ComputedRef<boolean>;
30
+ run: (...args: Args) => Promise<T>;
31
+ cancel: (reason?: unknown) => void;
32
+ reset: () => void;
33
+ }
34
+ declare function useRequest<T, Args extends unknown[] = []>(executor: (context: UseRequestContext, ...args: Args) => Promise<T>, options?: UseRequestOptions<T, Args>): UseRequestReturn<T, Args>;
35
+
36
+ declare function useTableCrud<T extends DataRecord, Filters extends object = Record<string, unknown>, Sort extends object = Record<string, unknown>>(config: UseTableCrudConfig<T, Filters, Sort>): UseTableCrudReturn<T, Filters, Sort>;
37
+
38
+ export { DataRecord, REQUEST_CLIENT_KEY, type UseRequestContext, type UseRequestOptions, type UseRequestReturn, UseTableCrudConfig, UseTableCrudReturn, createRequestPlugin, provideRequestClient, useRequest, useRequestClient, useTableCrud };
package/dist/vue.d.ts ADDED
@@ -0,0 +1,38 @@
1
+ import { InjectionKey, App, ShallowRef, ComputedRef } from 'vue';
2
+ import { f as RequestClient, d as ConcurrencyPolicy, j as RequestError } from './types-BVJhlSuh.js';
3
+ import { D as DataRecord, U as UseTableCrudConfig, f as UseTableCrudReturn } from './types-CUyibJZX.js';
4
+ export { A as ActionContext, a as ApiEndpoints, g as CrudDialogApi, h as CrudMessageApi, i as CrudMutations, j as CrudUiAdapter, C as CustomAction, b as DetailConfig, c as DetailItem, d as DetailModal, e as DetailSection, T as TableColumn, k as TableQueryContext, l as TableQueryResult } from './types-CUyibJZX.js';
5
+ import 'axios';
6
+
7
+ declare const REQUEST_CLIENT_KEY: InjectionKey<RequestClient>;
8
+ declare function createRequestPlugin(client: RequestClient): {
9
+ install(app: App): void;
10
+ };
11
+ declare function provideRequestClient(client: RequestClient): RequestClient;
12
+ declare function useRequestClient(optional?: boolean): RequestClient | undefined;
13
+
14
+ interface UseRequestContext {
15
+ signal: AbortSignal;
16
+ }
17
+ interface UseRequestOptions<T, Args extends unknown[]> {
18
+ initialData?: T;
19
+ immediate?: boolean;
20
+ immediateArgs?: Args;
21
+ concurrency?: Extract<ConcurrencyPolicy, "allow" | "takeLatest" | "takeFirst">;
22
+ keepPreviousData?: boolean;
23
+ onSuccess?: (data: T) => void | Promise<void>;
24
+ onError?: (error: RequestError) => void | Promise<void>;
25
+ }
26
+ interface UseRequestReturn<T, Args extends unknown[]> {
27
+ data: ShallowRef<T | undefined>;
28
+ error: ShallowRef<RequestError | null>;
29
+ loading: ComputedRef<boolean>;
30
+ run: (...args: Args) => Promise<T>;
31
+ cancel: (reason?: unknown) => void;
32
+ reset: () => void;
33
+ }
34
+ declare function useRequest<T, Args extends unknown[] = []>(executor: (context: UseRequestContext, ...args: Args) => Promise<T>, options?: UseRequestOptions<T, Args>): UseRequestReturn<T, Args>;
35
+
36
+ declare function useTableCrud<T extends DataRecord, Filters extends object = Record<string, unknown>, Sort extends object = Record<string, unknown>>(config: UseTableCrudConfig<T, Filters, Sort>): UseTableCrudReturn<T, Filters, Sort>;
37
+
38
+ export { DataRecord, REQUEST_CLIENT_KEY, type UseRequestContext, type UseRequestOptions, type UseRequestReturn, UseTableCrudConfig, UseTableCrudReturn, createRequestPlugin, provideRequestClient, useRequest, useRequestClient, useTableCrud };
package/dist/vue.js ADDED
@@ -0,0 +1,71 @@
1
+ export { REQUEST_CLIENT_KEY, createRequestPlugin, provideRequestClient, useRequestClient, useTableCrud } from './chunk-2JXH7SIL.js';
2
+ import { normalizeRequestError, isCanceledError } from './chunk-OAZ5BUBU.js';
3
+ import { shallowRef, computed, getCurrentScope, onScopeDispose } from 'vue';
4
+
5
+ function useRequest(executor, options = {}) {
6
+ const data = shallowRef(options.initialData);
7
+ const error = shallowRef(null);
8
+ const pending = shallowRef(0);
9
+ const loading = computed(() => pending.value > 0);
10
+ let active = null;
11
+ const controllers = /* @__PURE__ */ new Set();
12
+ let sequence = 0;
13
+ const cancel = (reason) => {
14
+ sequence += 1;
15
+ for (const controller of controllers) controller.abort(reason);
16
+ controllers.clear();
17
+ active = null;
18
+ };
19
+ const run = async (...args) => {
20
+ const concurrency = options.concurrency ?? "takeLatest";
21
+ if (active && concurrency === "takeFirst") return active.promise;
22
+ if (active && concurrency === "takeLatest") active.controller.abort();
23
+ const id = ++sequence;
24
+ const controller = new AbortController();
25
+ controllers.add(controller);
26
+ if (!options.keepPreviousData) data.value = void 0;
27
+ error.value = null;
28
+ pending.value += 1;
29
+ const promise = executor({ signal: controller.signal }, ...args);
30
+ active = { controller, promise, id };
31
+ try {
32
+ const result = await promise;
33
+ if (id === sequence || concurrency === "takeFirst") {
34
+ data.value = result;
35
+ try {
36
+ await options.onSuccess?.(result);
37
+ } catch {
38
+ }
39
+ }
40
+ return result;
41
+ } catch (cause) {
42
+ const normalized = normalizeRequestError(cause);
43
+ if (!isCanceledError(normalized) && id === sequence) {
44
+ error.value = normalized;
45
+ try {
46
+ await options.onError?.(normalized);
47
+ } catch {
48
+ }
49
+ }
50
+ throw normalized;
51
+ } finally {
52
+ pending.value = Math.max(0, pending.value - 1);
53
+ controllers.delete(controller);
54
+ if (active?.id === id) active = null;
55
+ }
56
+ };
57
+ const reset = () => {
58
+ cancel();
59
+ data.value = options.initialData;
60
+ error.value = null;
61
+ };
62
+ if (getCurrentScope()) onScopeDispose(() => cancel());
63
+ if (options.immediate) {
64
+ void run(...options.immediateArgs ?? []).catch(() => void 0);
65
+ }
66
+ return { data, error, loading, run, cancel, reset };
67
+ }
68
+
69
+ export { useRequest };
70
+ //# sourceMappingURL=vue.js.map
71
+ //# sourceMappingURL=vue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vue/useRequest.ts"],"names":[],"mappings":"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","file":"vue.js","sourcesContent":["import {\n computed,\n getCurrentScope,\n onScopeDispose,\n shallowRef,\n type ComputedRef,\n type ShallowRef,\n} from \"vue\";\nimport type { ConcurrencyPolicy } from \"../axios/types\";\nimport {\n isCanceledError,\n normalizeRequestError,\n type RequestError,\n} from \"../client/errors\";\n\nexport interface UseRequestContext {\n signal: AbortSignal;\n}\n\nexport interface UseRequestOptions<T, Args extends unknown[]> {\n initialData?: T;\n immediate?: boolean;\n immediateArgs?: Args;\n concurrency?: Extract<ConcurrencyPolicy, \"allow\" | \"takeLatest\" | \"takeFirst\">;\n keepPreviousData?: boolean;\n onSuccess?: (data: T) => void | Promise<void>;\n onError?: (error: RequestError) => void | Promise<void>;\n}\n\nexport interface UseRequestReturn<T, Args extends unknown[]> {\n data: ShallowRef<T | undefined>;\n error: ShallowRef<RequestError | null>;\n loading: ComputedRef<boolean>;\n run: (...args: Args) => Promise<T>;\n cancel: (reason?: unknown) => void;\n reset: () => void;\n}\n\nexport function useRequest<T, Args extends unknown[] = []>(\n executor: (context: UseRequestContext, ...args: Args) => Promise<T>,\n options: UseRequestOptions<T, Args> = {},\n): UseRequestReturn<T, Args> {\n const data = shallowRef<T | undefined>(options.initialData);\n const error = shallowRef<RequestError | null>(null);\n const pending = shallowRef(0);\n const loading = computed(() => pending.value > 0);\n let active: { controller: AbortController; promise: Promise<T>; id: number } | null =\n null;\n const controllers = new Set<AbortController>();\n let sequence = 0;\n\n const cancel = (reason?: unknown): void => {\n sequence += 1;\n for (const controller of controllers) controller.abort(reason);\n controllers.clear();\n active = null;\n };\n\n const run = async (...args: Args): Promise<T> => {\n const concurrency = options.concurrency ?? \"takeLatest\";\n if (active && concurrency === \"takeFirst\") return active.promise;\n if (active && concurrency === \"takeLatest\") active.controller.abort();\n\n const id = ++sequence;\n const controller = new AbortController();\n controllers.add(controller);\n if (!options.keepPreviousData) data.value = undefined;\n error.value = null;\n pending.value += 1;\n\n const promise = executor({ signal: controller.signal }, ...args);\n active = { controller, promise, id };\n try {\n const result = await promise;\n if (id === sequence || concurrency === \"takeFirst\") {\n data.value = result;\n try {\n await options.onSuccess?.(result);\n } catch {\n // Lifecycle callbacks must not turn a successful request into a failure.\n }\n }\n return result;\n } catch (cause) {\n const normalized = normalizeRequestError(cause);\n if (!isCanceledError(normalized) && id === sequence) {\n error.value = normalized;\n try {\n await options.onError?.(normalized);\n } catch {\n // Preserve the original request error if an observer fails.\n }\n }\n throw normalized;\n } finally {\n pending.value = Math.max(0, pending.value - 1);\n controllers.delete(controller);\n if (active?.id === id) active = null;\n }\n };\n\n const reset = (): void => {\n cancel();\n data.value = options.initialData;\n error.value = null;\n };\n\n if (getCurrentScope()) onScopeDispose(() => cancel());\n if (options.immediate) {\n void run(...(options.immediateArgs ?? ([] as unknown as Args))).catch(() => undefined);\n }\n\n return { data, error, loading, run, cancel, reset };\n}\n"]}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@robot-admin/request-core",
3
- "version": "0.2.0",
4
- "description": "Axios request orchestration + CRUD composables for Vue 3",
3
+ "version": "0.4.0",
4
+ "description": "Instance-scoped Axios orchestration and headless CRUD composables for Vue 3",
5
5
  "type": "module",
6
6
  "keywords": [
7
7
  "vue",
@@ -12,9 +12,12 @@
12
12
  ],
13
13
  "author": "ChenYu <ycyplus@gmail.com>",
14
14
  "license": "MIT",
15
+ "engines": {
16
+ "node": ">=18.18.0"
17
+ },
15
18
  "repository": {
16
19
  "type": "git",
17
- "url": "https://github.com/ChenyCHENYU/robot-admin-packages",
20
+ "url": "git+https://github.com/ChenyCHENYU/robot-admin-packages.git",
18
21
  "directory": "packages/request-core"
19
22
  },
20
23
  "main": "./dist/index.cjs",
@@ -22,24 +25,62 @@
22
25
  "types": "./dist/index.d.ts",
23
26
  "exports": {
24
27
  ".": {
25
- "types": "./dist/index.d.ts",
26
- "import": "./dist/index.js",
27
- "require": "./dist/index.cjs"
28
+ "import": {
29
+ "types": "./dist/index.d.ts",
30
+ "default": "./dist/index.js"
31
+ },
32
+ "require": {
33
+ "types": "./dist/index.d.cts",
34
+ "default": "./dist/index.cjs"
35
+ }
28
36
  },
29
37
  "./axios": {
30
- "types": "./dist/axios.d.ts",
31
- "import": "./dist/axios.js",
32
- "require": "./dist/axios.cjs"
38
+ "import": {
39
+ "types": "./dist/axios.d.ts",
40
+ "default": "./dist/axios.js"
41
+ },
42
+ "require": {
43
+ "types": "./dist/axios.d.cts",
44
+ "default": "./dist/axios.cjs"
45
+ }
33
46
  },
34
47
  "./crud": {
35
- "types": "./dist/crud.d.ts",
36
- "import": "./dist/crud.js",
37
- "require": "./dist/crud.cjs"
48
+ "import": {
49
+ "types": "./dist/crud.d.ts",
50
+ "default": "./dist/crud.js"
51
+ },
52
+ "require": {
53
+ "types": "./dist/crud.d.cts",
54
+ "default": "./dist/crud.cjs"
55
+ }
56
+ },
57
+ "./vue": {
58
+ "import": {
59
+ "types": "./dist/vue.d.ts",
60
+ "default": "./dist/vue.js"
61
+ },
62
+ "require": {
63
+ "types": "./dist/vue.d.cts",
64
+ "default": "./dist/vue.cjs"
65
+ }
66
+ },
67
+ "./naive": {
68
+ "import": {
69
+ "types": "./dist/naive.d.ts",
70
+ "default": "./dist/naive.js"
71
+ },
72
+ "require": {
73
+ "types": "./dist/naive.d.cts",
74
+ "default": "./dist/naive.cjs"
75
+ }
38
76
  }
39
77
  },
40
78
  "files": [
41
79
  "dist",
42
- "README.md"
80
+ "README.md",
81
+ "CHANGELOG.md",
82
+ "LICENSE",
83
+ "SECURITY.md"
43
84
  ],
44
85
  "sideEffects": false,
45
86
  "publishConfig": {
@@ -51,8 +92,10 @@
51
92
  "build": "tsup",
52
93
  "clean": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\"",
53
94
  "test": "vitest run tests",
54
- "type-check": "tsc --noEmit",
55
- "prepublishOnly": "bun run build"
95
+ "type-check": "tsc --noEmit && tsc --noEmit -p tsconfig.test.json",
96
+ "check:package": "node ./node_modules/publint/src/cli.js && node ./scripts/verify-package.mjs",
97
+ "verify": "bun run type-check && bun run test && bun run build && bun run check:package",
98
+ "prepublishOnly": "bun run verify"
56
99
  },
57
100
  "peerDependencies": {
58
101
  "vue": "^3.4.0",
@@ -73,6 +116,7 @@
73
116
  "tsup": "^8.1.0",
74
117
  "vue": "^3.4.0",
75
118
  "naive-ui": "^2.38.0",
76
- "axios": "^1.7.0"
119
+ "axios": "^1.7.0",
120
+ "publint": "0.3.24"
77
121
  }
78
122
  }