@classytic/arc-next 0.1.2 → 0.2.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.
- package/README.md +593 -51
- package/dist/api.d.ts +10 -6
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +24 -11
- package/dist/api.js.map +1 -1
- package/dist/hooks.d.ts +43 -5
- package/dist/hooks.d.ts.map +1 -1
- package/dist/hooks.js +134 -13
- package/dist/hooks.js.map +1 -1
- package/dist/mutation.d.ts +22 -16
- package/dist/mutation.d.ts.map +1 -1
- package/dist/mutation.js +9 -5
- package/dist/mutation.js.map +1 -1
- package/dist/query.d.ts +12 -4
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +26 -23
- package/dist/query.js.map +1 -1
- package/package.json +1 -1
package/dist/api.d.ts
CHANGED
|
@@ -46,11 +46,11 @@ interface AggregatePaginationResponse<T = unknown> {
|
|
|
46
46
|
type PaginatedResponse<T = unknown> = OffsetPaginationResponse<T> | KeysetPaginationResponse<T> | AggregatePaginationResponse<T>;
|
|
47
47
|
interface DeleteResponse {
|
|
48
48
|
success: boolean;
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
data?: {
|
|
50
|
+
message?: string;
|
|
51
|
+
id?: string;
|
|
52
|
+
soft?: boolean;
|
|
53
|
+
};
|
|
54
54
|
}
|
|
55
55
|
type SortDirection = 1 | -1 | 'asc' | 'desc';
|
|
56
56
|
type SortSpec = Record<string, SortDirection> | string;
|
|
@@ -94,6 +94,8 @@ declare class BaseApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, T
|
|
|
94
94
|
readonly baseUrl: string;
|
|
95
95
|
private readonly requestFn;
|
|
96
96
|
constructor(entity: string, config?: BaseApiConfig);
|
|
97
|
+
/** Merge per-instance headers into request options */
|
|
98
|
+
private withHeaders;
|
|
97
99
|
createQueryString(params?: Record<string, unknown>): string;
|
|
98
100
|
prepareParams(params?: QueryParams): Record<string, unknown>;
|
|
99
101
|
getAll({
|
|
@@ -162,12 +164,14 @@ declare class BaseApi<TDoc = Record<string, unknown>, TCreate = Partial<TDoc>, T
|
|
|
162
164
|
token,
|
|
163
165
|
organizationId,
|
|
164
166
|
data,
|
|
167
|
+
id,
|
|
165
168
|
path,
|
|
166
169
|
options
|
|
167
170
|
}: {
|
|
168
171
|
token?: string | null;
|
|
169
172
|
organizationId?: string | null;
|
|
170
|
-
data: FormData;
|
|
173
|
+
data: FormData; /** Resource ID — shorthand for path, appended as `baseUrl/{id}/upload` */
|
|
174
|
+
id?: string; /** Custom sub-path appended as `baseUrl/{path}`. Takes precedence over `id`. */
|
|
171
175
|
path?: string;
|
|
172
176
|
options?: Omit<RequestOptions, 'token' | 'organizationId'>;
|
|
173
177
|
}): Promise<ApiResponse<TDoc>>;
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","names":[],"sources":["../src/api.ts"],"mappings":";;;UAOiB,cAAA;EACf,IAAA;EACA,MAAA;EACA,KAAA,GAAQ,MAAA;AAAA;AAAA,UAOO,WAAA;EACf,OAAA;EACA,IAAA,GAAO,CAAA;EACP,OAAA;AAAA;AAAA,UAGe,wBAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,IAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,UAGe,wBAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,KAAA;EACA,OAAA;EACA,IAAA;AAAA;AAAA,UAGe,2BAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,IAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,KAGU,iBAAA,gBACR,wBAAA,CAAyB,CAAA,IACzB,wBAAA,CAAyB,CAAA,IACzB,2BAAA,CAA4B,CAAA;AAAA,UAEf,cAAA;EACf,OAAA;EACA,OAAA;
|
|
1
|
+
{"version":3,"file":"api.d.ts","names":[],"sources":["../src/api.ts"],"mappings":";;;UAOiB,cAAA;EACf,IAAA;EACA,MAAA;EACA,KAAA,GAAQ,MAAA;AAAA;AAAA,UAOO,WAAA;EACf,OAAA;EACA,IAAA,GAAO,CAAA;EACP,OAAA;AAAA;AAAA,UAGe,wBAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,IAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,UAGe,wBAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,KAAA;EACA,OAAA;EACA,IAAA;AAAA;AAAA,UAGe,2BAAA;EACf,OAAA;EACA,MAAA;EACA,IAAA,EAAM,CAAA;EACN,IAAA;EACA,KAAA;EACA,KAAA;EACA,KAAA;EACA,OAAA;EACA,OAAA;EACA,OAAA;AAAA;AAAA,KAGU,iBAAA,gBACR,wBAAA,CAAyB,CAAA,IACzB,wBAAA,CAAyB,CAAA,IACzB,2BAAA,CAA4B,CAAA;AAAA,UAEf,cAAA;EACf,OAAA;EACA,IAAA;IACE,OAAA;IACA,EAAA;IACA,IAAA;EAAA;AAAA;AAAA,KAQQ,aAAA;AAAA,KACA,QAAA,GAAW,MAAA,SAAe,aAAA;AAAA,KAE1B,cAAA;AAAA,UAKK,WAAA;EACf,IAAA;EACA,KAAA;EACA,KAAA;EACA,MAAA;EACA,IAAA;EACA,MAAA;EACA,QAAA;EACA,eAAA,GAAkB,cAAA;EAClB,IAAA;EAAA,CACC,GAAA;AAAA;AAAA,UAGc,cAAA;EACf,KAAA;EACA,cAAA;EACA,KAAA,GAAQ,YAAA;EACR,UAAA;EACA,IAAA;EACA,aAAA,GAAgB,MAAA;EAChB,YAAA;EACA,MAAA,GAAS,WAAA;AAAA;AAAA,UAGM,aAAA;EACf,QAAA;EACA,aAAA;IACE,KAAA;IACA,IAAA;IAAA,CACC,GAAA;EAAA;EAEH,KAAA,GAAQ,YAAA;EACR,OAAA,GAAU,MAAA;EACV,MAAA,GAAS,SAAA;AAAA;AAAA,cAiBE,OAAA,QACJ,MAAA,6BACG,OAAA,CAAQ,IAAA,aACR,OAAA,CAAQ,IAAA;EAAA,SAET,MAAA;EAAA,SACA,MAAA,EAAQ,QAAA,CAAS,IAAA,CAAK,aAAA;EAAA,SACtB,OAAA;EAAA,iBACQ,SAAA;cAEL,MAAA,UAAgB,MAAA,GAAQ,aAAA;EAjFrB;EAAA,QAqGP,WAAA;EASR,iBAAA,CAAkB,MAAA,GAAQ,MAAA;EAI1B,aAAA,CAAc,MAAA,GAAQ,WAAA,GAAmB,MAAA;EAmCnC,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,MAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,MAAA,GAAS,WAAA;IACT,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACR,OAAA,CAAQ,iBAAA,CAAkB,IAAA;EAe7B,OAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,EAAA;IACA,MAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,EAAA;IACA,MAAA;MAAW,MAAA;MAAiB,QAAA;IAAA;IAC5B,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,WAAA,CAAY,IAAA;EAiBlB,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,IAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,IAAA,EAAM,OAAA;IACN,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,WAAA,CAAY,IAAA;EAYlB,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,EAAA;IACA,IAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,EAAA;IACA,IAAA,EAAM,OAAA;IACN,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,WAAA,CAAY,IAAA;EAclB,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,EAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,EAAA;IACA,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,cAAA;EAWN,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,IAAA;IACA,EAAA;IACA,IAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,IAAA,EAAM,QAAA,EAxPO;IA0Pb,EAAA,WA1P2B;IA4P3B,IAAA;IACA,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,WAAA,CAAY,IAAA;EAelB,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,YAAA;IACA,MAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,YAAA,GAAe,MAAA;IACf,MAAA,GAAS,WAAA;IACT,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACR,OAAA,CAAQ,iBAAA,CAAkB,IAAA;EAgB7B,MAAA,CAAA;IACJ,KAAA;IACA,cAAA;IACA,KAAA;IACA,KAAA;IACA,QAAA;IACA,MAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,KAAA;IACA,KAAA;IACA,QAAA,GAAW,cAAA;IACX,MAAA,GAAS,WAAA;IACT,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IACb,OAAA,CAAQ,iBAAA,CAAkB,IAAA;EA2BxB,OAAA,qBAAA,CACJ,MAAA,+CACA,QAAA;IAEE,KAAA;IACA,cAAA;IACA,IAAA;IACA,MAAA;IACA;EAAA;IAEA,KAAA;IACA,cAAA;IACA,IAAA;IACA,MAAA,GAAS,WAAA;IACT,OAAA,GAAU,IAAA,CAAK,cAAA;EAAA,IAEhB,OAAA,CAAQ,SAAA;AAAA;AAAA,iBA0BG,aAAA,QACP,MAAA,6BACG,OAAA,CAAQ,IAAA,aACR,OAAA,CAAQ,IAAA,EAAA,CAClB,MAAA,UAAgB,MAAA,GAAQ,aAAA,GAAqB,OAAA,CAAQ,IAAA,EAAM,OAAA,EAAS,OAAA;AAAA,KAQ1D,UAAA,MAAgB,CAAA,SAAU,iBAAA,YAA6B,CAAA;AAAA,iBAEnD,kBAAA,GAAA,CACd,QAAA,EAAU,iBAAA,CAAkB,CAAA,IAC3B,QAAA,IAAY,wBAAA,CAAyB,CAAA;AAAA,iBAIxB,kBAAA,GAAA,CACd,QAAA,EAAU,iBAAA,CAAkB,CAAA,IAC3B,QAAA,IAAY,wBAAA,CAAyB,CAAA;AAAA,iBAIxB,qBAAA,GAAA,CACd,QAAA,EAAU,iBAAA,CAAkB,CAAA,IAC3B,QAAA,IAAY,2BAAA,CAA4B,CAAA"}
|
package/dist/api.js
CHANGED
|
@@ -21,6 +21,18 @@ var BaseApi = class {
|
|
|
21
21
|
};
|
|
22
22
|
this.baseUrl = `${this.config.basePath}/${this.entity}`;
|
|
23
23
|
}
|
|
24
|
+
/** Merge per-instance headers into request options */
|
|
25
|
+
withHeaders(options) {
|
|
26
|
+
const instanceHeaders = this.config.headers;
|
|
27
|
+
if (!instanceHeaders || Object.keys(instanceHeaders).length === 0) return options;
|
|
28
|
+
return {
|
|
29
|
+
...options,
|
|
30
|
+
headerOptions: {
|
|
31
|
+
...instanceHeaders,
|
|
32
|
+
...options.headerOptions ?? {}
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
}
|
|
24
36
|
createQueryString(params = {}) {
|
|
25
37
|
return createQueryString(params);
|
|
26
38
|
}
|
|
@@ -53,7 +65,7 @@ var BaseApi = class {
|
|
|
53
65
|
};
|
|
54
66
|
if (token) requestOptions.token = token;
|
|
55
67
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
56
|
-
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, requestOptions);
|
|
68
|
+
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));
|
|
57
69
|
}
|
|
58
70
|
async getById({ token = null, organizationId = null, id, params = {}, options = {} }) {
|
|
59
71
|
if (!id) throw new Error("ID is required");
|
|
@@ -65,7 +77,7 @@ var BaseApi = class {
|
|
|
65
77
|
};
|
|
66
78
|
if (token) requestOptions.token = token;
|
|
67
79
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
68
|
-
return this.requestFn("GET", url, requestOptions);
|
|
80
|
+
return this.requestFn("GET", url, this.withHeaders(requestOptions));
|
|
69
81
|
}
|
|
70
82
|
async create({ token, organizationId = null, data, options = {} }) {
|
|
71
83
|
const requestOptions = {
|
|
@@ -74,7 +86,7 @@ var BaseApi = class {
|
|
|
74
86
|
};
|
|
75
87
|
if (token) requestOptions.token = token;
|
|
76
88
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
77
|
-
return this.requestFn("POST", this.baseUrl, requestOptions);
|
|
89
|
+
return this.requestFn("POST", this.baseUrl, this.withHeaders(requestOptions));
|
|
78
90
|
}
|
|
79
91
|
async update({ token, organizationId = null, id, data, options = {} }) {
|
|
80
92
|
if (!id) throw new Error("ID is required");
|
|
@@ -84,24 +96,25 @@ var BaseApi = class {
|
|
|
84
96
|
};
|
|
85
97
|
if (token) requestOptions.token = token;
|
|
86
98
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
87
|
-
return this.requestFn("PATCH", `${this.baseUrl}/${id}`, requestOptions);
|
|
99
|
+
return this.requestFn("PATCH", `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));
|
|
88
100
|
}
|
|
89
101
|
async delete({ token, organizationId = null, id, options = {} }) {
|
|
90
102
|
if (!id) throw new Error("ID is required");
|
|
91
103
|
const requestOptions = { ...options };
|
|
92
104
|
if (token) requestOptions.token = token;
|
|
93
105
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
94
|
-
return this.requestFn("DELETE", `${this.baseUrl}/${id}`, requestOptions);
|
|
106
|
+
return this.requestFn("DELETE", `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));
|
|
95
107
|
}
|
|
96
|
-
async upload({ token, organizationId = null, data, path, options = {} }) {
|
|
97
|
-
const
|
|
108
|
+
async upload({ token, organizationId = null, data, id, path, options = {} }) {
|
|
109
|
+
const suffix = path ?? (id ? `${id}/upload` : void 0);
|
|
110
|
+
const url = suffix ? `${this.baseUrl}/${suffix}` : this.baseUrl;
|
|
98
111
|
const requestOptions = {
|
|
99
112
|
body: data,
|
|
100
113
|
...options
|
|
101
114
|
};
|
|
102
115
|
if (token) requestOptions.token = token;
|
|
103
116
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
104
|
-
return this.requestFn("POST", url, requestOptions);
|
|
117
|
+
return this.requestFn("POST", url, this.withHeaders(requestOptions));
|
|
105
118
|
}
|
|
106
119
|
async search({ token = null, organizationId = null, searchParams = {}, params = {}, options = {} } = {}) {
|
|
107
120
|
const queryParams = {
|
|
@@ -116,7 +129,7 @@ var BaseApi = class {
|
|
|
116
129
|
};
|
|
117
130
|
if (token) requestOptions.token = token;
|
|
118
131
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
119
|
-
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, requestOptions);
|
|
132
|
+
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));
|
|
120
133
|
}
|
|
121
134
|
async findBy({ token = null, organizationId = null, field, value, operator, params = {}, options = {} }) {
|
|
122
135
|
if (!field || value === void 0) throw new Error("Field and value are required");
|
|
@@ -131,7 +144,7 @@ var BaseApi = class {
|
|
|
131
144
|
};
|
|
132
145
|
if (token) requestOptions.token = token;
|
|
133
146
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
134
|
-
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, requestOptions);
|
|
147
|
+
return this.requestFn("GET", `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));
|
|
135
148
|
}
|
|
136
149
|
async request(method, endpoint, { token, organizationId = null, data, params, options = {} } = {}) {
|
|
137
150
|
let url = endpoint;
|
|
@@ -146,7 +159,7 @@ var BaseApi = class {
|
|
|
146
159
|
};
|
|
147
160
|
if (token) requestOptions.token = token;
|
|
148
161
|
if (organizationId) requestOptions.organizationId = organizationId;
|
|
149
|
-
return this.requestFn(method, url, requestOptions);
|
|
162
|
+
return this.requestFn(method, url, this.withHeaders(requestOptions));
|
|
150
163
|
}
|
|
151
164
|
};
|
|
152
165
|
function createCrudApi(entity, config = {}) {
|
package/dist/api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","names":[],"sources":["../src/api.ts"],"sourcesContent":["import { handleApiRequest, createQueryString } from './client.js';\nimport type { ApiRequestOptions, ArcClient } from './client.js';\n\n// ============================================================================\n// Populate Types\n// ============================================================================\n\nexport interface PopulateOption {\n path: string;\n select?: string;\n match?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n message?: string;\n}\n\nexport interface OffsetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'offset';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport interface KeysetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'keyset';\n docs: T[];\n limit: number;\n hasMore: boolean;\n next: string | null;\n}\n\nexport interface AggregatePaginationResponse<T = unknown> {\n success: boolean;\n method: 'aggregate';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport type PaginatedResponse<T = unknown> =\n | OffsetPaginationResponse<T>\n | KeysetPaginationResponse<T>\n | AggregatePaginationResponse<T>;\n\nexport interface DeleteResponse {\n success: boolean;\n deleted: boolean;\n id?: string;\n soft?: boolean;\n message?: string;\n count?: number;\n}\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\nexport type SortDirection = 1 | -1 | 'asc' | 'desc';\nexport type SortSpec = Record<string, SortDirection> | string;\n\nexport type FilterOperator =\n | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte'\n | 'in' | 'nin'\n | 'contains' | 'startsWith' | 'endsWith' | 'regex';\n\nexport interface QueryParams {\n page?: number;\n limit?: number;\n after?: string;\n cursor?: string;\n sort?: string;\n select?: string;\n populate?: string | string[];\n populateOptions?: PopulateOption[];\n lean?: boolean | 'true' | 'false';\n [key: string]: unknown;\n}\n\nexport interface RequestOptions {\n token?: string | null;\n organizationId?: string | null;\n cache?: RequestCache;\n revalidate?: number;\n tags?: string[];\n headerOptions?: Record<string, string>;\n responseType?: 'json' | 'blob' | 'text';\n signal?: AbortSignal;\n}\n\nexport interface BaseApiConfig {\n basePath?: string;\n defaultParams?: {\n limit?: number;\n page?: number;\n [key: string]: unknown;\n };\n cache?: RequestCache;\n headers?: Record<string, string>;\n client?: ArcClient;\n}\n\n// ============================================================================\n// Request Function Type\n// ============================================================================\n\ntype RequestFn = <T = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n options?: ApiRequestOptions,\n) => Promise<T>;\n\n// ============================================================================\n// Base API Class\n// ============================================================================\n\nexport class BaseApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n> {\n readonly entity: string;\n readonly config: Required<Omit<BaseApiConfig, 'client'>>;\n readonly baseUrl: string;\n private readonly requestFn: RequestFn;\n\n constructor(entity: string, config: BaseApiConfig = {}) {\n this.entity = entity;\n this.requestFn = config.client?.request ?? handleApiRequest;\n this.config = {\n basePath: config.basePath ?? '/api/v1',\n defaultParams: {\n limit: 10,\n page: 1,\n ...(config.defaultParams || {}),\n },\n cache: config.cache ?? 'no-store',\n headers: {\n ...(config.headers || {}),\n },\n };\n\n this.baseUrl = `${this.config.basePath}/${this.entity}`;\n }\n\n createQueryString(params: Record<string, unknown> = {}): string {\n return createQueryString(params);\n }\n\n prepareParams(params: QueryParams = {}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const CRITICAL_FILTERS = ['organizationId', 'ownerId'];\n\n Object.entries(params).forEach(([key, value]) => {\n if (CRITICAL_FILTERS.includes(key)) {\n result[key] = value || null;\n return;\n }\n\n if (key === 'populateOptions') {\n if (Array.isArray(value) && value.length > 0) {\n result[key] = value;\n }\n return;\n }\n\n if (value !== undefined && value !== '') {\n if (['page', 'limit'].includes(key)) {\n result[key] = parseInt(String(value)) || (key === 'page' ? 1 : 10);\n } else if (Array.isArray(value)) {\n if (value.length > 1) {\n result[`${key}[in]`] = value.join(',');\n } else if (value.length === 1) {\n result[key] = value[0];\n }\n } else {\n result[key] = value;\n }\n }\n });\n\n return result;\n }\n\n async getAll({\n token = null,\n organizationId = null,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, requestOptions);\n }\n\n async getById({\n token = null,\n organizationId = null,\n id,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n params?: { select?: string; populate?: string | string[] };\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const queryString = this.createQueryString(params);\n const url = queryString ? `${this.baseUrl}/${id}?${queryString}` : `${this.baseUrl}/${id}`;\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', url, requestOptions);\n }\n\n async create({\n token,\n organizationId = null,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: TCreate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', this.baseUrl, requestOptions);\n }\n\n async update({\n token,\n organizationId = null,\n id,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n data: TUpdate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('PATCH', `${this.baseUrl}/${id}`, requestOptions);\n }\n\n async delete({\n token,\n organizationId = null,\n id,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<DeleteResponse> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = { ...options };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('DELETE', `${this.baseUrl}/${id}`, requestOptions);\n }\n\n async upload({\n token,\n organizationId = null,\n data,\n path,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: FormData;\n path?: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const url = path ? `${this.baseUrl}/${path}` : this.baseUrl;\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', url, requestOptions);\n }\n\n async search({\n token = null,\n organizationId = null,\n searchParams = {},\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n searchParams?: Record<string, unknown>;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const queryParams = { ...params, ...searchParams };\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, requestOptions);\n }\n\n async findBy({\n token = null,\n organizationId = null,\n field,\n value,\n operator,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n field: string;\n value: unknown;\n operator?: FilterOperator;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<PaginatedResponse<TDoc>> {\n if (!field || value === undefined) {\n throw new Error('Field and value are required');\n }\n\n const queryParams: QueryParams = { ...params };\n\n if (operator) {\n queryParams[`${field}[${operator}]`] = Array.isArray(value) ? value.join(',') : value;\n } else {\n queryParams[field] = value;\n }\n\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, requestOptions);\n }\n\n async request<TResponse = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n {\n token,\n organizationId = null,\n data,\n params,\n options = {},\n }: {\n token?: string;\n organizationId?: string | null;\n data?: unknown;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}\n ): Promise<TResponse> {\n let url = endpoint;\n\n if (params) {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n url = `${endpoint}?${queryString}`;\n }\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn(method, url, requestOptions);\n }\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport function createCrudApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n>(entity: string, config: BaseApiConfig = {}): BaseApi<TDoc, TCreate, TUpdate> {\n return new BaseApi<TDoc, TCreate, TUpdate>(entity, config);\n}\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\nexport type ExtractDoc<T> = T extends PaginatedResponse<infer D> ? D : never;\n\nexport function isOffsetPagination<T>(\n response: PaginatedResponse<T>\n): response is OffsetPaginationResponse<T> {\n return response.method === 'offset';\n}\n\nexport function isKeysetPagination<T>(\n response: PaginatedResponse<T>\n): response is KeysetPaginationResponse<T> {\n return response.method === 'keyset';\n}\n\nexport function isAggregatePagination<T>(\n response: PaginatedResponse<T>\n): response is AggregatePaginationResponse<T> {\n return response.method === 'aggregate';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"api.js","names":[],"sources":["../src/api.ts"],"sourcesContent":["import { handleApiRequest, createQueryString } from './client.js';\nimport type { ApiRequestOptions, ArcClient } from './client.js';\n\n// ============================================================================\n// Populate Types\n// ============================================================================\n\nexport interface PopulateOption {\n path: string;\n select?: string;\n match?: Record<string, unknown>;\n}\n\n// ============================================================================\n// Response Types\n// ============================================================================\n\nexport interface ApiResponse<T = unknown> {\n success: boolean;\n data?: T;\n message?: string;\n}\n\nexport interface OffsetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'offset';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport interface KeysetPaginationResponse<T = unknown> {\n success: boolean;\n method: 'keyset';\n docs: T[];\n limit: number;\n hasMore: boolean;\n next: string | null;\n}\n\nexport interface AggregatePaginationResponse<T = unknown> {\n success: boolean;\n method: 'aggregate';\n docs: T[];\n page: number;\n limit: number;\n total: number;\n pages: number;\n hasNext: boolean;\n hasPrev: boolean;\n warning?: string;\n}\n\nexport type PaginatedResponse<T = unknown> =\n | OffsetPaginationResponse<T>\n | KeysetPaginationResponse<T>\n | AggregatePaginationResponse<T>;\n\nexport interface DeleteResponse {\n success: boolean;\n data?: {\n message?: string;\n id?: string;\n soft?: boolean;\n };\n}\n\n// ============================================================================\n// Request Types\n// ============================================================================\n\nexport type SortDirection = 1 | -1 | 'asc' | 'desc';\nexport type SortSpec = Record<string, SortDirection> | string;\n\nexport type FilterOperator =\n | 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte'\n | 'in' | 'nin'\n | 'contains' | 'startsWith' | 'endsWith' | 'regex';\n\nexport interface QueryParams {\n page?: number;\n limit?: number;\n after?: string;\n cursor?: string;\n sort?: string;\n select?: string;\n populate?: string | string[];\n populateOptions?: PopulateOption[];\n lean?: boolean | 'true' | 'false';\n [key: string]: unknown;\n}\n\nexport interface RequestOptions {\n token?: string | null;\n organizationId?: string | null;\n cache?: RequestCache;\n revalidate?: number;\n tags?: string[];\n headerOptions?: Record<string, string>;\n responseType?: 'json' | 'blob' | 'text';\n signal?: AbortSignal;\n}\n\nexport interface BaseApiConfig {\n basePath?: string;\n defaultParams?: {\n limit?: number;\n page?: number;\n [key: string]: unknown;\n };\n cache?: RequestCache;\n headers?: Record<string, string>;\n client?: ArcClient;\n}\n\n// ============================================================================\n// Request Function Type\n// ============================================================================\n\ntype RequestFn = <T = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n options?: ApiRequestOptions,\n) => Promise<T>;\n\n// ============================================================================\n// Base API Class\n// ============================================================================\n\nexport class BaseApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n> {\n readonly entity: string;\n readonly config: Required<Omit<BaseApiConfig, 'client'>>;\n readonly baseUrl: string;\n private readonly requestFn: RequestFn;\n\n constructor(entity: string, config: BaseApiConfig = {}) {\n this.entity = entity;\n this.requestFn = config.client?.request ?? handleApiRequest;\n this.config = {\n basePath: config.basePath ?? '/api/v1',\n defaultParams: {\n limit: 10,\n page: 1,\n ...(config.defaultParams || {}),\n },\n cache: config.cache ?? 'no-store',\n headers: {\n ...(config.headers || {}),\n },\n };\n\n this.baseUrl = `${this.config.basePath}/${this.entity}`;\n }\n\n /** Merge per-instance headers into request options */\n private withHeaders(options: ApiRequestOptions): ApiRequestOptions {\n const instanceHeaders = this.config.headers;\n if (!instanceHeaders || Object.keys(instanceHeaders).length === 0) return options;\n return {\n ...options,\n headerOptions: { ...instanceHeaders, ...(options.headerOptions ?? {}) },\n };\n }\n\n createQueryString(params: Record<string, unknown> = {}): string {\n return createQueryString(params);\n }\n\n prepareParams(params: QueryParams = {}): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n const CRITICAL_FILTERS = ['organizationId', 'ownerId'];\n\n Object.entries(params).forEach(([key, value]) => {\n if (CRITICAL_FILTERS.includes(key)) {\n result[key] = value || null;\n return;\n }\n\n if (key === 'populateOptions') {\n if (Array.isArray(value) && value.length > 0) {\n result[key] = value;\n }\n return;\n }\n\n if (value !== undefined && value !== '') {\n if (['page', 'limit'].includes(key)) {\n result[key] = parseInt(String(value)) || (key === 'page' ? 1 : 10);\n } else if (Array.isArray(value)) {\n if (value.length > 1) {\n result[`${key}[in]`] = value.join(',');\n } else if (value.length === 1) {\n result[key] = value[0];\n }\n } else {\n result[key] = value;\n }\n }\n });\n\n return result;\n }\n\n async getAll({\n token = null,\n organizationId = null,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async getById({\n token = null,\n organizationId = null,\n id,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n params?: { select?: string; populate?: string | string[] };\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const queryString = this.createQueryString(params);\n const url = queryString ? `${this.baseUrl}/${id}?${queryString}` : `${this.baseUrl}/${id}`;\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', url, this.withHeaders(requestOptions));\n }\n\n async create({\n token,\n organizationId = null,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: TCreate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', this.baseUrl, this.withHeaders(requestOptions));\n }\n\n async update({\n token,\n organizationId = null,\n id,\n data,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n data: TUpdate;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('PATCH', `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));\n }\n\n async delete({\n token,\n organizationId = null,\n id,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n id: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<DeleteResponse> {\n if (!id) throw new Error('ID is required');\n\n const requestOptions: ApiRequestOptions = { ...options };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('DELETE', `${this.baseUrl}/${id}`, this.withHeaders(requestOptions));\n }\n\n async upload({\n token,\n organizationId = null,\n data,\n id,\n path,\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n data: FormData;\n /** Resource ID — shorthand for path, appended as `baseUrl/{id}/upload` */\n id?: string;\n /** Custom sub-path appended as `baseUrl/{path}`. Takes precedence over `id`. */\n path?: string;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<ApiResponse<TDoc>> {\n const suffix = path ?? (id ? `${id}/upload` : undefined);\n const url = suffix ? `${this.baseUrl}/${suffix}` : this.baseUrl;\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('POST', url, this.withHeaders(requestOptions));\n }\n\n async search({\n token = null,\n organizationId = null,\n searchParams = {},\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n searchParams?: Record<string, unknown>;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}): Promise<PaginatedResponse<TDoc>> {\n const queryParams = { ...params, ...searchParams };\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async findBy({\n token = null,\n organizationId = null,\n field,\n value,\n operator,\n params = {},\n options = {},\n }: {\n token?: string | null;\n organizationId?: string | null;\n field: string;\n value: unknown;\n operator?: FilterOperator;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n }): Promise<PaginatedResponse<TDoc>> {\n if (!field || value === undefined) {\n throw new Error('Field and value are required');\n }\n\n const queryParams: QueryParams = { ...params };\n\n if (operator) {\n queryParams[`${field}[${operator}]`] = Array.isArray(value) ? value.join(',') : value;\n } else {\n queryParams[field] = value;\n }\n\n const processedParams = this.prepareParams(queryParams);\n const queryString = this.createQueryString(processedParams);\n\n const requestOptions: ApiRequestOptions = {\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn('GET', `${this.baseUrl}?${queryString}`, this.withHeaders(requestOptions));\n }\n\n async request<TResponse = unknown>(\n method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE',\n endpoint: string,\n {\n token,\n organizationId = null,\n data,\n params,\n options = {},\n }: {\n token?: string;\n organizationId?: string | null;\n data?: unknown;\n params?: QueryParams;\n options?: Omit<RequestOptions, 'token' | 'organizationId'>;\n } = {}\n ): Promise<TResponse> {\n let url = endpoint;\n\n if (params) {\n const processedParams = this.prepareParams(params);\n const queryString = this.createQueryString(processedParams);\n url = `${endpoint}?${queryString}`;\n }\n\n const requestOptions: ApiRequestOptions = {\n body: data,\n cache: this.config.cache,\n ...options,\n };\n\n if (token) requestOptions.token = token;\n if (organizationId) requestOptions.organizationId = organizationId;\n\n return this.requestFn(method, url, this.withHeaders(requestOptions));\n }\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\nexport function createCrudApi<\n TDoc = Record<string, unknown>,\n TCreate = Partial<TDoc>,\n TUpdate = Partial<TDoc>\n>(entity: string, config: BaseApiConfig = {}): BaseApi<TDoc, TCreate, TUpdate> {\n return new BaseApi<TDoc, TCreate, TUpdate>(entity, config);\n}\n\n// ============================================================================\n// Type Helpers\n// ============================================================================\n\nexport type ExtractDoc<T> = T extends PaginatedResponse<infer D> ? D : never;\n\nexport function isOffsetPagination<T>(\n response: PaginatedResponse<T>\n): response is OffsetPaginationResponse<T> {\n return response.method === 'offset';\n}\n\nexport function isKeysetPagination<T>(\n response: PaginatedResponse<T>\n): response is KeysetPaginationResponse<T> {\n return response.method === 'keyset';\n}\n\nexport function isAggregatePagination<T>(\n response: PaginatedResponse<T>\n): response is AggregatePaginationResponse<T> {\n return response.method === 'aggregate';\n}\n"],"mappings":"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"}
|
package/dist/hooks.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { ArcClient, UseRouterHook } from "./client.js";
|
|
2
|
+
import { MutationCallbacks, MutationMessages, TransitionMutationReturn } from "./mutation.js";
|
|
2
3
|
import { CacheUtils, DetailQueryOptions, DetailQueryResult, InfiniteListQueryOptions, InfiniteListQueryResult, ListQueryOptions, ListQueryResult, QueryKeys } from "./query.js";
|
|
3
|
-
import {
|
|
4
|
+
import { QueryKey } from "@tanstack/react-query";
|
|
4
5
|
|
|
5
6
|
//#region src/hooks.d.ts
|
|
6
7
|
interface CrudApi<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
|
|
@@ -42,6 +43,22 @@ interface CrudApi<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
|
|
|
42
43
|
organizationId?: string | null;
|
|
43
44
|
id: string;
|
|
44
45
|
}) => Promise<unknown>;
|
|
46
|
+
upload?: (options: {
|
|
47
|
+
token?: string | null;
|
|
48
|
+
organizationId?: string | null;
|
|
49
|
+
data: FormData;
|
|
50
|
+
id?: string;
|
|
51
|
+
path?: string;
|
|
52
|
+
}) => Promise<unknown>;
|
|
53
|
+
search?: (options: {
|
|
54
|
+
token?: string | null;
|
|
55
|
+
organizationId?: string | null;
|
|
56
|
+
params?: Record<string, unknown>;
|
|
57
|
+
options?: {
|
|
58
|
+
signal?: AbortSignal;
|
|
59
|
+
[key: string]: unknown;
|
|
60
|
+
};
|
|
61
|
+
}) => Promise<unknown>;
|
|
45
62
|
}
|
|
46
63
|
interface CrudHooksConfig<T, TCreate = Partial<T>, TUpdate = Partial<T>> {
|
|
47
64
|
api: CrudApi<T, TCreate, TUpdate>;
|
|
@@ -92,6 +109,7 @@ interface DeleteParams {
|
|
|
92
109
|
interface CallOptions<TData = unknown> {
|
|
93
110
|
onSuccess?: (data: TData) => void;
|
|
94
111
|
onError?: (error: Error) => void;
|
|
112
|
+
onSettled?: (data: TData | undefined, error: Error | null) => void;
|
|
95
113
|
silent?: boolean;
|
|
96
114
|
}
|
|
97
115
|
interface CrudActions<T, TCreate, TUpdate> {
|
|
@@ -112,18 +130,38 @@ interface CrudHooksReturn<T, TCreate, TUpdate> {
|
|
|
112
130
|
KEYS: QueryKeys;
|
|
113
131
|
cache: CacheUtils<T>;
|
|
114
132
|
useList: {
|
|
115
|
-
/** New signature — auto-injects token/orgId from configureAuth() context */(params?: Record<string, unknown>, options?: ListQueryOptions): ListQueryResult<T>; /** Legacy signature — explicit token */
|
|
116
|
-
(token: string | null, params?: Record<string, unknown>, options?: ListQueryOptions): ListQueryResult<T>;
|
|
133
|
+
/** New signature — auto-injects token/orgId from configureAuth() context */(params?: Record<string, unknown>, options?: ListQueryOptions<T>): ListQueryResult<T>; /** Legacy signature — explicit token */
|
|
134
|
+
(token: string | null, params?: Record<string, unknown>, options?: ListQueryOptions<T>): ListQueryResult<T>;
|
|
117
135
|
};
|
|
118
136
|
useDetail: {
|
|
119
|
-
/** New signature — auto-injects token from configureAuth() context */(id: string | null, options?: DetailQueryOptions): DetailQueryResult<T>; /** Legacy signature — explicit token */
|
|
120
|
-
(id: string | null, token: string | null, options?: DetailQueryOptions): DetailQueryResult<T>;
|
|
137
|
+
/** New signature — auto-injects token from configureAuth() context */(id: string | null, options?: DetailQueryOptions<T>): DetailQueryResult<T>; /** Legacy signature — explicit token */
|
|
138
|
+
(id: string | null, token: string | null, options?: DetailQueryOptions<T>): DetailQueryResult<T>;
|
|
121
139
|
};
|
|
122
140
|
useInfiniteList: {
|
|
123
141
|
/** New signature — auto-injects token/orgId from configureAuth() context */(params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>; /** Legacy signature — explicit token */
|
|
124
142
|
(token: string | null, params?: Record<string, unknown>, options?: InfiniteListQueryOptions): InfiniteListQueryResult<T>;
|
|
125
143
|
};
|
|
126
144
|
useActions: () => CrudActions<T, TCreate, TUpdate>;
|
|
145
|
+
useUpload: (options?: {
|
|
146
|
+
invalidateQueries?: QueryKey[];
|
|
147
|
+
messages?: MutationMessages;
|
|
148
|
+
onSuccess?: (data: unknown) => void;
|
|
149
|
+
onError?: (error: Error) => void;
|
|
150
|
+
onSettled?: (data: unknown | undefined, error: Error | null) => void;
|
|
151
|
+
}) => TransitionMutationReturn<unknown, {
|
|
152
|
+
data: FormData;
|
|
153
|
+
id?: string;
|
|
154
|
+
path?: string;
|
|
155
|
+
}>;
|
|
156
|
+
useSearch: (query: string, params?: Record<string, unknown>, options?: ListQueryOptions<T>) => ListQueryResult<T>;
|
|
157
|
+
useCustomMutation: <TData = unknown, TVariables = unknown>(config: {
|
|
158
|
+
mutationFn: (variables: TVariables) => Promise<TData>;
|
|
159
|
+
invalidateQueries?: QueryKey[];
|
|
160
|
+
messages?: MutationMessages;
|
|
161
|
+
onSuccess?: (data: TData, variables: TVariables) => void;
|
|
162
|
+
onError?: (error: Error, variables: TVariables) => void;
|
|
163
|
+
onSettled?: (data: TData | undefined, error: Error | null, variables: TVariables) => void;
|
|
164
|
+
}) => TransitionMutationReturn<TData, TVariables>;
|
|
127
165
|
useNavigation: () => NavigateFn<T>;
|
|
128
166
|
}
|
|
129
167
|
/**
|
package/dist/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","names":[],"sources":["../src/hooks.ts"],"mappings":"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"}
|
package/dist/hooks.js
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
import { getAuthContext, getAuthMode } from "./client.js";
|
|
4
4
|
import { isKeysetPagination, isOffsetPagination } from "./api.js";
|
|
5
5
|
import { DEFAULT_QUERY_CONFIG, createCacheUtils, createDetailQuery, createInfiniteListQuery, createListQuery, createQueryKeys, getItemId, updateListCache } from "./query.js";
|
|
6
|
-
import { createOptimisticMutation } from "./mutation.js";
|
|
7
|
-
import { useQueryClient } from "@tanstack/react-query";
|
|
8
|
-
import { useCallback } from "react";
|
|
6
|
+
import { createOptimisticMutation, useMutationWithTransition } from "./mutation.js";
|
|
7
|
+
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
|
8
|
+
import { useCallback, useRef } from "react";
|
|
9
9
|
|
|
10
10
|
//#region src/hooks.ts
|
|
11
11
|
let useRouterHook = null;
|
|
@@ -68,11 +68,14 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
68
68
|
organizationId,
|
|
69
69
|
...restParams
|
|
70
70
|
}),
|
|
71
|
-
queryFn: () => api.getAll({
|
|
71
|
+
queryFn: ({ signal }) => api.getAll({
|
|
72
72
|
token,
|
|
73
73
|
organizationId,
|
|
74
74
|
params: restParams,
|
|
75
|
-
options: {
|
|
75
|
+
options: {
|
|
76
|
+
signal,
|
|
77
|
+
...requestOpts
|
|
78
|
+
}
|
|
76
79
|
}),
|
|
77
80
|
enabled: createEnabledRule(token, queryOpts),
|
|
78
81
|
options: {
|
|
@@ -84,7 +87,8 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
84
87
|
refetchIntervalInBackground: queryOpts.refetchIntervalInBackground
|
|
85
88
|
},
|
|
86
89
|
prefillDetailCache: queryOpts.prefillDetailCache ?? true,
|
|
87
|
-
detailKeyBuilder: (id) => KEYS.detail(id)
|
|
90
|
+
detailKeyBuilder: (id) => KEYS.detail(id),
|
|
91
|
+
select: queryOpts.select
|
|
88
92
|
});
|
|
89
93
|
}
|
|
90
94
|
function useDetail(id, tokenOrOptions, maybeOptions) {
|
|
@@ -105,12 +109,15 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
105
109
|
const { organizationId, params: queryParams, request: requestOpts, ...restOptions } = options;
|
|
106
110
|
return createDetailQuery({
|
|
107
111
|
queryKey: queryParams ? [...KEYS.detail(id || ""), queryParams] : KEYS.detail(id || ""),
|
|
108
|
-
queryFn: () => api.getById({
|
|
112
|
+
queryFn: ({ signal }) => api.getById({
|
|
109
113
|
id,
|
|
110
114
|
token,
|
|
111
115
|
organizationId,
|
|
112
116
|
params: queryParams,
|
|
113
|
-
options: {
|
|
117
|
+
options: {
|
|
118
|
+
signal,
|
|
119
|
+
...requestOpts
|
|
120
|
+
}
|
|
114
121
|
}),
|
|
115
122
|
enabled: !!id && createEnabledRule(token, restOptions),
|
|
116
123
|
options: {
|
|
@@ -119,11 +126,14 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
119
126
|
structuralSharing: restOptions.structuralSharing ?? config.structuralSharing,
|
|
120
127
|
refetchInterval: restOptions.refetchInterval,
|
|
121
128
|
refetchIntervalInBackground: restOptions.refetchIntervalInBackground
|
|
122
|
-
}
|
|
129
|
+
},
|
|
130
|
+
select: restOptions.select
|
|
123
131
|
});
|
|
124
132
|
}
|
|
125
133
|
function useActions() {
|
|
126
134
|
const queryClient = useQueryClient();
|
|
135
|
+
const silentRef = useRef(false);
|
|
136
|
+
const shouldToast = useCallback(() => !silentRef.current, []);
|
|
127
137
|
const createMutation = createOptimisticMutation({
|
|
128
138
|
mutationFn: ({ token, organizationId, data }) => api.create({
|
|
129
139
|
token,
|
|
@@ -132,6 +142,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
132
142
|
}),
|
|
133
143
|
queryClient,
|
|
134
144
|
queryKeys: [KEYS.lists()],
|
|
145
|
+
shouldToast,
|
|
135
146
|
optimisticUpdate: (oldData, { data }) => {
|
|
136
147
|
const optimisticItem = {
|
|
137
148
|
...data,
|
|
@@ -146,6 +157,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
146
157
|
onError: (error, variables) => {
|
|
147
158
|
callbacks.onCreate?.onError?.(error, { data: variables.data }, void 0);
|
|
148
159
|
},
|
|
160
|
+
onSettled: (data, error, variables) => {
|
|
161
|
+
callbacks.onCreate?.onSettled?.(data, error, { data: variables.data }, void 0);
|
|
162
|
+
},
|
|
149
163
|
messages: {
|
|
150
164
|
success: config.messages.createSuccess,
|
|
151
165
|
error: config.messages.createError
|
|
@@ -161,6 +175,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
161
175
|
}),
|
|
162
176
|
queryClient,
|
|
163
177
|
queryKeys: [KEYS.lists()],
|
|
178
|
+
shouldToast,
|
|
164
179
|
optimisticUpdate: (oldData, { id, data }) => {
|
|
165
180
|
const updated = updateListCache(oldData, (arr) => (arr || []).map((item) => getItemId(item) === id ? {
|
|
166
181
|
...item,
|
|
@@ -175,11 +190,11 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
175
190
|
} : current);
|
|
176
191
|
return updated;
|
|
177
192
|
},
|
|
178
|
-
onSuccess: (data, { id }) => {
|
|
193
|
+
onSuccess: (data, { id, data: updateData }) => {
|
|
179
194
|
queryClient.invalidateQueries({ queryKey: KEYS.detail(id) });
|
|
180
195
|
callbacks.onUpdate?.onSuccess?.(data, {
|
|
181
196
|
id,
|
|
182
|
-
data:
|
|
197
|
+
data: updateData
|
|
183
198
|
}, void 0);
|
|
184
199
|
},
|
|
185
200
|
onError: (error, { id, data }) => {
|
|
@@ -188,6 +203,12 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
188
203
|
data
|
|
189
204
|
}, void 0);
|
|
190
205
|
},
|
|
206
|
+
onSettled: (data, error, { id, data: updateData }) => {
|
|
207
|
+
callbacks.onUpdate?.onSettled?.(data, error, {
|
|
208
|
+
id,
|
|
209
|
+
data: updateData
|
|
210
|
+
}, void 0);
|
|
211
|
+
},
|
|
191
212
|
messages: {
|
|
192
213
|
success: config.messages.updateSuccess,
|
|
193
214
|
error: config.messages.updateError
|
|
@@ -202,6 +223,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
202
223
|
}),
|
|
203
224
|
queryClient,
|
|
204
225
|
queryKeys: [KEYS.lists()],
|
|
226
|
+
shouldToast,
|
|
205
227
|
optimisticUpdate: (oldData, { id }) => {
|
|
206
228
|
queryClient.removeQueries({ queryKey: KEYS.detail(id) });
|
|
207
229
|
return updateListCache(oldData, (arr) => (arr || []).filter((item) => getItemId(item) !== id));
|
|
@@ -212,6 +234,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
212
234
|
onError: (error, { id }) => {
|
|
213
235
|
callbacks.onDelete?.onError?.(error, { id }, void 0);
|
|
214
236
|
},
|
|
237
|
+
onSettled: (data, error, { id }) => {
|
|
238
|
+
callbacks.onDelete?.onSettled?.(data, error, { id }, void 0);
|
|
239
|
+
},
|
|
215
240
|
messages: {
|
|
216
241
|
success: config.messages.deleteSuccess,
|
|
217
242
|
error: config.messages.deleteError
|
|
@@ -227,33 +252,48 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
227
252
|
};
|
|
228
253
|
};
|
|
229
254
|
const create = async (params, options) => {
|
|
255
|
+
silentRef.current = options?.silent ?? false;
|
|
230
256
|
try {
|
|
231
257
|
const result = await createMutation.mutateAsync(resolveAuth(params));
|
|
232
258
|
options?.onSuccess?.(result);
|
|
259
|
+
options?.onSettled?.(result, null);
|
|
233
260
|
return result;
|
|
234
261
|
} catch (error) {
|
|
235
262
|
options?.onError?.(error);
|
|
263
|
+
options?.onSettled?.(void 0, error);
|
|
236
264
|
throw error;
|
|
265
|
+
} finally {
|
|
266
|
+
silentRef.current = false;
|
|
237
267
|
}
|
|
238
268
|
};
|
|
239
269
|
const update = async (params, options) => {
|
|
270
|
+
silentRef.current = options?.silent ?? false;
|
|
240
271
|
try {
|
|
241
272
|
const result = await updateMutation.mutateAsync(resolveAuth(params));
|
|
242
273
|
options?.onSuccess?.(result);
|
|
274
|
+
options?.onSettled?.(result, null);
|
|
243
275
|
return result;
|
|
244
276
|
} catch (error) {
|
|
245
277
|
options?.onError?.(error);
|
|
278
|
+
options?.onSettled?.(void 0, error);
|
|
246
279
|
throw error;
|
|
280
|
+
} finally {
|
|
281
|
+
silentRef.current = false;
|
|
247
282
|
}
|
|
248
283
|
};
|
|
249
284
|
const remove = async (params, options) => {
|
|
285
|
+
silentRef.current = options?.silent ?? false;
|
|
250
286
|
try {
|
|
251
287
|
const result = await deleteMutation.mutateAsync(resolveAuth(params));
|
|
252
288
|
options?.onSuccess?.(result);
|
|
289
|
+
options?.onSettled?.(result, null);
|
|
253
290
|
return result;
|
|
254
291
|
} catch (error) {
|
|
255
292
|
options?.onError?.(error);
|
|
293
|
+
options?.onSettled?.(void 0, error);
|
|
256
294
|
throw error;
|
|
295
|
+
} finally {
|
|
296
|
+
silentRef.current = false;
|
|
257
297
|
}
|
|
258
298
|
};
|
|
259
299
|
return {
|
|
@@ -292,7 +332,7 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
292
332
|
organizationId,
|
|
293
333
|
...restParams
|
|
294
334
|
}), "infinite"],
|
|
295
|
-
queryFn: ({ pageParam }) => {
|
|
335
|
+
queryFn: ({ pageParam, signal }) => {
|
|
296
336
|
const paginationParams = typeof pageParam === "string" ? { after: pageParam } : { page: pageParam };
|
|
297
337
|
return api.getAll({
|
|
298
338
|
token,
|
|
@@ -301,7 +341,10 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
301
341
|
...restParams,
|
|
302
342
|
...paginationParams
|
|
303
343
|
},
|
|
304
|
-
options: {
|
|
344
|
+
options: {
|
|
345
|
+
signal,
|
|
346
|
+
...requestOpts
|
|
347
|
+
}
|
|
305
348
|
});
|
|
306
349
|
},
|
|
307
350
|
enabled: createEnabledRule(token, queryOpts),
|
|
@@ -321,6 +364,81 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
321
364
|
}
|
|
322
365
|
});
|
|
323
366
|
}
|
|
367
|
+
function useUpload(options) {
|
|
368
|
+
if (!api.upload) throw new Error(`[arc-next] "${entityKey}" api does not define an upload method`);
|
|
369
|
+
const uploadApi = api.upload;
|
|
370
|
+
return useMutationWithTransition({
|
|
371
|
+
mutationFn: ({ data, id, path }) => {
|
|
372
|
+
const auth = getAuthContext();
|
|
373
|
+
return uploadApi({
|
|
374
|
+
token: auth.token,
|
|
375
|
+
organizationId: auth.organizationId,
|
|
376
|
+
data,
|
|
377
|
+
id,
|
|
378
|
+
path
|
|
379
|
+
});
|
|
380
|
+
},
|
|
381
|
+
invalidateQueries: options?.invalidateQueries ?? [KEYS.lists()],
|
|
382
|
+
onSuccess: (data) => options?.onSuccess?.(data),
|
|
383
|
+
onError: (error) => options?.onError?.(error),
|
|
384
|
+
onSettled: (data, error) => options?.onSettled?.(data, error),
|
|
385
|
+
messages: options?.messages ?? {
|
|
386
|
+
success: `${singular} uploaded successfully`,
|
|
387
|
+
error: `Failed to upload ${singular.toLowerCase()}`
|
|
388
|
+
},
|
|
389
|
+
toastHandler: instanceToast
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
function useSearch(query, params, options) {
|
|
393
|
+
if (!api.search) throw new Error(`[arc-next] "${entityKey}" api does not define a search method`);
|
|
394
|
+
const searchApi = api.search;
|
|
395
|
+
const auth = getAuthContext();
|
|
396
|
+
const token = auth.token;
|
|
397
|
+
const organizationId = params?.organizationId ?? auth.organizationId;
|
|
398
|
+
const { organizationId: _, ...restParams } = params ?? {};
|
|
399
|
+
const searchParams = {
|
|
400
|
+
q: query,
|
|
401
|
+
...restParams
|
|
402
|
+
};
|
|
403
|
+
const { request: requestOpts, ...queryOpts } = options ?? {};
|
|
404
|
+
const searchKeyParams = organizationId ? {
|
|
405
|
+
organizationId,
|
|
406
|
+
...searchParams
|
|
407
|
+
} : searchParams;
|
|
408
|
+
return createListQuery({
|
|
409
|
+
queryKey: [
|
|
410
|
+
...KEYS.lists(),
|
|
411
|
+
"search",
|
|
412
|
+
searchKeyParams
|
|
413
|
+
],
|
|
414
|
+
queryFn: ({ signal }) => searchApi({
|
|
415
|
+
token,
|
|
416
|
+
organizationId,
|
|
417
|
+
params: searchParams,
|
|
418
|
+
options: {
|
|
419
|
+
signal,
|
|
420
|
+
...requestOpts
|
|
421
|
+
}
|
|
422
|
+
}),
|
|
423
|
+
enabled: query.length > 0 && createEnabledRule(token, queryOpts),
|
|
424
|
+
options: {
|
|
425
|
+
staleTime: queryOpts.staleTime ?? config.staleTime,
|
|
426
|
+
gcTime: queryOpts.gcTime ?? config.gcTime
|
|
427
|
+
},
|
|
428
|
+
select: queryOpts.select
|
|
429
|
+
});
|
|
430
|
+
}
|
|
431
|
+
function useCustomMutation(mutationConfig) {
|
|
432
|
+
return useMutationWithTransition({
|
|
433
|
+
mutationFn: mutationConfig.mutationFn,
|
|
434
|
+
invalidateQueries: mutationConfig.invalidateQueries ?? [KEYS.lists()],
|
|
435
|
+
onSuccess: mutationConfig.onSuccess,
|
|
436
|
+
onError: mutationConfig.onError,
|
|
437
|
+
onSettled: mutationConfig.onSettled,
|
|
438
|
+
messages: mutationConfig.messages,
|
|
439
|
+
toastHandler: instanceToast
|
|
440
|
+
});
|
|
441
|
+
}
|
|
324
442
|
function useNavigation() {
|
|
325
443
|
const queryClient = useQueryClient();
|
|
326
444
|
const router = (instanceNavigation ?? useRouterHook)?.();
|
|
@@ -340,6 +458,9 @@ function createCrudHooks({ api, entityKey, singular, defaults = {}, callbacks =
|
|
|
340
458
|
useDetail,
|
|
341
459
|
useInfiniteList,
|
|
342
460
|
useActions,
|
|
461
|
+
useUpload,
|
|
462
|
+
useSearch,
|
|
463
|
+
useCustomMutation,
|
|
343
464
|
useNavigation
|
|
344
465
|
};
|
|
345
466
|
}
|