next-data-kit 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +478 -0
  3. package/dist/client/components/data-kit-table.d.ts +29 -0
  4. package/dist/client/components/data-kit.d.ts +19 -0
  5. package/dist/client/components/index.d.ts +3 -0
  6. package/dist/client/components/ui/button.d.ts +14 -0
  7. package/dist/client/components/ui/checkbox.d.ts +5 -0
  8. package/dist/client/components/ui/dropdown-menu.d.ts +28 -0
  9. package/dist/client/components/ui/index.d.ts +9 -0
  10. package/dist/client/components/ui/pagination.d.ts +14 -0
  11. package/dist/client/components/ui/popover.d.ts +10 -0
  12. package/dist/client/components/ui/select.d.ts +18 -0
  13. package/dist/client/components/ui/switch.d.ts +5 -0
  14. package/dist/client/components/ui/table.d.ts +11 -0
  15. package/dist/client/context/index.d.ts +22 -0
  16. package/dist/client/hooks/index.d.ts +7 -0
  17. package/dist/client/hooks/useDataKit.d.ts +9 -0
  18. package/dist/client/hooks/usePagination.d.ts +18 -0
  19. package/dist/client/hooks/useSelection.d.ts +13 -0
  20. package/dist/client/index.d.ts +11 -0
  21. package/dist/client/utils/cn.d.ts +10 -0
  22. package/dist/client/utils/index.d.ts +60 -0
  23. package/dist/client.d.ts +7 -0
  24. package/dist/index.d.cts +652 -0
  25. package/dist/index.d.ts +652 -0
  26. package/dist/react-data-kit-DmTzxNTc.d.cts +225 -0
  27. package/dist/react-data-kit-DmTzxNTc.d.ts +225 -0
  28. package/dist/server.cjs +222 -0
  29. package/dist/server.cjs.map +1 -0
  30. package/dist/server.d.cts +68 -0
  31. package/dist/server.d.ts +68 -0
  32. package/dist/server.js +216 -0
  33. package/dist/server.js.map +1 -0
  34. package/dist/types/component.d.ts +106 -0
  35. package/dist/types/database/mongo.d.ts +129 -0
  36. package/dist/types/hook.d.ts +100 -0
  37. package/dist/types/index.cjs +15 -0
  38. package/dist/types/index.cjs.map +1 -0
  39. package/dist/types/index.d.cts +252 -0
  40. package/dist/types/index.d.ts +12 -0
  41. package/dist/types/index.js +13 -0
  42. package/dist/types/index.js.map +1 -0
  43. package/dist/types/react-data-kit.d.ts +95 -0
  44. package/dist/types/selectable.d.ts +43 -0
  45. package/package.json +127 -0
@@ -0,0 +1,225 @@
1
+ /**
2
+ * react-data-kit - Database Types (Mongo)
3
+ *
4
+ * MongoDB-specific types.
5
+ * Consolidated into a single file for simplicity.
6
+ */
7
+ /**
8
+ * Sort order for database queries
9
+ */
10
+ type TSortOrder = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending';
11
+ /**
12
+ * ObjectId placeholder type - compatible with MongoDB ObjectId.
13
+ */
14
+ type TObjectId = {
15
+ toString(): string;
16
+ toHexString(): string;
17
+ equals(otherId: TObjectId | string): boolean;
18
+ };
19
+ /**
20
+ * Generic document type that represents a database document with an ID.
21
+ */
22
+ type TDocument<TId = unknown> = {
23
+ _id: TId;
24
+ createdAt?: Date;
25
+ updatedAt?: Date;
26
+ };
27
+ /**
28
+ * Mongo document base (includes common Mongo-only fields).
29
+ */
30
+ type TMongoDocument = TDocument<string | TObjectId> & {
31
+ __v?: number;
32
+ };
33
+ /**
34
+ * Hydrated document type - represents a document with methods.
35
+ */
36
+ type THydratedDocument<T, TId = unknown> = T & TDocument<TId>;
37
+ /**
38
+ * Hydrated Mongo document.
39
+ */
40
+ type TMongoHydratedDocument<T> = T & TMongoDocument & {
41
+ toObject(): T;
42
+ toJSON(): T;
43
+ };
44
+ /**
45
+ * Filter operators for individual fields (Mongo subset)
46
+ */
47
+ type TMongoFilterOperators<T> = {
48
+ $eq?: T;
49
+ $ne?: T;
50
+ $gt?: T;
51
+ $gte?: T;
52
+ $lt?: T;
53
+ $lte?: T;
54
+ $in?: T[];
55
+ $nin?: T[];
56
+ $exists?: boolean;
57
+ $all?: T extends Array<infer U> ? U[] : never;
58
+ $elemMatch?: T extends Array<infer U> ? TMongoFilterQuery<U> : never;
59
+ $size?: number;
60
+ $regex?: string | RegExp;
61
+ $options?: string;
62
+ $type?: string | number;
63
+ };
64
+ /**
65
+ * Mongo root operators.
66
+ */
67
+ type TMongoRootFilterOperators<T> = {
68
+ $and?: TMongoFilterQuery<T>[];
69
+ $or?: TMongoFilterQuery<T>[];
70
+ $nor?: TMongoFilterQuery<T>[];
71
+ $not?: TMongoFilterQuery<T>;
72
+ $text?: {
73
+ $search: string;
74
+ $language?: string;
75
+ $caseSensitive?: boolean;
76
+ $diacriticSensitive?: boolean;
77
+ };
78
+ $where?: string | ((this: T) => boolean);
79
+ };
80
+ /**
81
+ * Mongo filter query type.
82
+ */
83
+ type TMongoFilterQuery<T> = {
84
+ [P in keyof T]?: T[P] | TMongoFilterOperators<T[P]>;
85
+ } & TMongoRootFilterOperators<T>;
86
+ /**
87
+ * Populate options for query builder.
88
+ */
89
+ type TPopulateOptions = {
90
+ path: string;
91
+ select?: string | Record<string, 0 | 1>;
92
+ model?: string;
93
+ match?: Record<string, unknown>;
94
+ populate?: TPopulateOptions | TPopulateOptions[];
95
+ };
96
+ /**
97
+ * Query builder for chaining query operations.
98
+ */
99
+ type TQueryBuilder<TResult, TQueryHelpers = object> = Promise<TResult> & {
100
+ sort(options: Record<string, TSortOrder>): TQueryBuilder<TResult, TQueryHelpers>;
101
+ limit(count: number): TQueryBuilder<TResult, TQueryHelpers>;
102
+ skip(count: number): TQueryBuilder<TResult, TQueryHelpers>;
103
+ select(fields: string | Record<string, 0 | 1>): TQueryBuilder<TResult, TQueryHelpers>;
104
+ populate(path: string | TPopulateOptions): TQueryBuilder<TResult, TQueryHelpers>;
105
+ lean(): TQueryBuilder<TResult, TQueryHelpers>;
106
+ exec(): Promise<TResult>;
107
+ };
108
+ /**
109
+ * Generic Model type.
110
+ */
111
+ type TModel<TRawDocType = unknown, TQueryHelpers = object, TId = unknown, TFilter = unknown> = {
112
+ countDocuments(filter?: TFilter): Promise<number>;
113
+ find(filter?: TFilter): TQueryBuilder<TRawDocType[], TQueryHelpers>;
114
+ findOne(filter?: TFilter): TQueryBuilder<TRawDocType | null, TQueryHelpers>;
115
+ findById(id: TId): TQueryBuilder<TRawDocType | null, TQueryHelpers>;
116
+ };
117
+ /**
118
+ * Convenience alias for a Mongo-backed model.
119
+ */
120
+ type TMongoModel<TRawDocType = unknown, TQueryHelpers = object> = TModel<TRawDocType, TQueryHelpers, string | TObjectId, TMongoFilterQuery<TRawDocType>>;
121
+ /**
122
+ * Extract raw document type from a Model
123
+ */
124
+ type TExtractDocType<M> = M extends TModel<infer TRawDocType, unknown, unknown, unknown> ? TRawDocType : never;
125
+ /**
126
+ * Extract hydrated document type from a Model
127
+ */
128
+ type TExtractHydratedDoc<M> = M extends TModel<infer TRawDocType, unknown, infer TId, unknown> ? THydratedDocument<TRawDocType, TId> : never;
129
+
130
+ /**
131
+ * react-data-kit - React Data Kit Types
132
+ *
133
+ * Core types for the react-data-kit server action and components.
134
+ */
135
+
136
+ /**
137
+ * Sort options type that references keys from the item type
138
+ */
139
+ type TSortOptions<T> = {
140
+ [K in keyof T]?: TSortOrder;
141
+ };
142
+ /**
143
+ * Sort entry for array-based sorting
144
+ */
145
+ type TSortEntry = {
146
+ path: string;
147
+ value: 1 | -1;
148
+ };
149
+ /**
150
+ * Filter configuration for automatic filtering
151
+ */
152
+ type TFilterConfig = {
153
+ [key: string]: {
154
+ type: 'regex' | 'exact';
155
+ field?: string;
156
+ };
157
+ };
158
+ /**
159
+ * Custom filter configuration
160
+ * Allows defining custom filter functions for specific filter keys
161
+ */
162
+ type TFilterCustomConfig<T = unknown> = {
163
+ [id: string]: (data: unknown) => TMongoFilterQuery<T>;
164
+ };
165
+ /**
166
+ * Variant of TFilterCustomConfig that allows customizing the returned filter shape.
167
+ * Useful for Mongo (operator-based) vs. other ORMs (where clauses) in the future.
168
+ */
169
+ type TFilterCustomConfigWithFilter<TDoc = unknown, TFilter = TMongoFilterQuery<TDoc>> = {
170
+ [id: string]: (data: unknown) => TFilter;
171
+ };
172
+ /**
173
+ * React Data Kit server action input
174
+ */
175
+ type TDataKitInput<T = unknown> = {
176
+ action?: 'FETCH';
177
+ page?: number;
178
+ limit?: number;
179
+ sort?: TSortOptions<T>;
180
+ sorts?: TSortEntry[];
181
+ query?: Record<string, unknown>;
182
+ filter?: Record<string, unknown>;
183
+ filterConfig?: TFilterConfig;
184
+ filterCustom?: TFilterCustomConfig<T>;
185
+ };
186
+ /**
187
+ * React Data Kit server action result
188
+ */
189
+ type TDataKitResult<R> = {
190
+ type: 'ITEMS';
191
+ items: R[];
192
+ documentTotal: number;
193
+ };
194
+ /**
195
+ * Pagination info for client-side use
196
+ */
197
+ type TPaginationInfo = {
198
+ currentPage: number;
199
+ totalPages: number;
200
+ totalItems: number;
201
+ itemsPerPage: number;
202
+ hasNextPage: boolean;
203
+ hasPrevPage: boolean;
204
+ };
205
+ /**
206
+ * Calculate pagination info from react-data-kit result
207
+ */
208
+ declare const calculatePagination: (page: number, limit: number, total: number) => TPaginationInfo;
209
+ /**
210
+ * React Data Kit Adapter Interface
211
+ * Defines the contract for a database adapter.
212
+ */
213
+ type TDataKitAdapter<T> = (params: Readonly<{
214
+ filter: Record<string, unknown>;
215
+ sorts: TSortEntry[];
216
+ limit: number;
217
+ page: number;
218
+ skip: number;
219
+ input: TDataKitInput<T>;
220
+ }>) => Promise<{
221
+ items: T[];
222
+ total: number;
223
+ }>;
224
+
225
+ export { type TDataKitInput as T, type TDataKitAdapter as a, type TMongoModel as b, type TMongoFilterQuery as c, type TFilterCustomConfigWithFilter as d, type TSortOptions as e, type TDataKitResult as f, type TExtractDocType as g, type TModel as h, type THydratedDocument as i, type TSortOrder as j, type TFilterCustomConfig as k, type TFilterConfig as l, type TMongoFilterOperators as m, type TMongoRootFilterOperators as n, type TObjectId as o, type TMongoDocument as p, type TMongoHydratedDocument as q, type TSortEntry as r, type TDocument as s, type TQueryBuilder as t, type TPopulateOptions as u, type TExtractHydratedDoc as v, type TPaginationInfo as w, calculatePagination as x };
@@ -0,0 +1,225 @@
1
+ /**
2
+ * react-data-kit - Database Types (Mongo)
3
+ *
4
+ * MongoDB-specific types.
5
+ * Consolidated into a single file for simplicity.
6
+ */
7
+ /**
8
+ * Sort order for database queries
9
+ */
10
+ type TSortOrder = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending';
11
+ /**
12
+ * ObjectId placeholder type - compatible with MongoDB ObjectId.
13
+ */
14
+ type TObjectId = {
15
+ toString(): string;
16
+ toHexString(): string;
17
+ equals(otherId: TObjectId | string): boolean;
18
+ };
19
+ /**
20
+ * Generic document type that represents a database document with an ID.
21
+ */
22
+ type TDocument<TId = unknown> = {
23
+ _id: TId;
24
+ createdAt?: Date;
25
+ updatedAt?: Date;
26
+ };
27
+ /**
28
+ * Mongo document base (includes common Mongo-only fields).
29
+ */
30
+ type TMongoDocument = TDocument<string | TObjectId> & {
31
+ __v?: number;
32
+ };
33
+ /**
34
+ * Hydrated document type - represents a document with methods.
35
+ */
36
+ type THydratedDocument<T, TId = unknown> = T & TDocument<TId>;
37
+ /**
38
+ * Hydrated Mongo document.
39
+ */
40
+ type TMongoHydratedDocument<T> = T & TMongoDocument & {
41
+ toObject(): T;
42
+ toJSON(): T;
43
+ };
44
+ /**
45
+ * Filter operators for individual fields (Mongo subset)
46
+ */
47
+ type TMongoFilterOperators<T> = {
48
+ $eq?: T;
49
+ $ne?: T;
50
+ $gt?: T;
51
+ $gte?: T;
52
+ $lt?: T;
53
+ $lte?: T;
54
+ $in?: T[];
55
+ $nin?: T[];
56
+ $exists?: boolean;
57
+ $all?: T extends Array<infer U> ? U[] : never;
58
+ $elemMatch?: T extends Array<infer U> ? TMongoFilterQuery<U> : never;
59
+ $size?: number;
60
+ $regex?: string | RegExp;
61
+ $options?: string;
62
+ $type?: string | number;
63
+ };
64
+ /**
65
+ * Mongo root operators.
66
+ */
67
+ type TMongoRootFilterOperators<T> = {
68
+ $and?: TMongoFilterQuery<T>[];
69
+ $or?: TMongoFilterQuery<T>[];
70
+ $nor?: TMongoFilterQuery<T>[];
71
+ $not?: TMongoFilterQuery<T>;
72
+ $text?: {
73
+ $search: string;
74
+ $language?: string;
75
+ $caseSensitive?: boolean;
76
+ $diacriticSensitive?: boolean;
77
+ };
78
+ $where?: string | ((this: T) => boolean);
79
+ };
80
+ /**
81
+ * Mongo filter query type.
82
+ */
83
+ type TMongoFilterQuery<T> = {
84
+ [P in keyof T]?: T[P] | TMongoFilterOperators<T[P]>;
85
+ } & TMongoRootFilterOperators<T>;
86
+ /**
87
+ * Populate options for query builder.
88
+ */
89
+ type TPopulateOptions = {
90
+ path: string;
91
+ select?: string | Record<string, 0 | 1>;
92
+ model?: string;
93
+ match?: Record<string, unknown>;
94
+ populate?: TPopulateOptions | TPopulateOptions[];
95
+ };
96
+ /**
97
+ * Query builder for chaining query operations.
98
+ */
99
+ type TQueryBuilder<TResult, TQueryHelpers = object> = Promise<TResult> & {
100
+ sort(options: Record<string, TSortOrder>): TQueryBuilder<TResult, TQueryHelpers>;
101
+ limit(count: number): TQueryBuilder<TResult, TQueryHelpers>;
102
+ skip(count: number): TQueryBuilder<TResult, TQueryHelpers>;
103
+ select(fields: string | Record<string, 0 | 1>): TQueryBuilder<TResult, TQueryHelpers>;
104
+ populate(path: string | TPopulateOptions): TQueryBuilder<TResult, TQueryHelpers>;
105
+ lean(): TQueryBuilder<TResult, TQueryHelpers>;
106
+ exec(): Promise<TResult>;
107
+ };
108
+ /**
109
+ * Generic Model type.
110
+ */
111
+ type TModel<TRawDocType = unknown, TQueryHelpers = object, TId = unknown, TFilter = unknown> = {
112
+ countDocuments(filter?: TFilter): Promise<number>;
113
+ find(filter?: TFilter): TQueryBuilder<TRawDocType[], TQueryHelpers>;
114
+ findOne(filter?: TFilter): TQueryBuilder<TRawDocType | null, TQueryHelpers>;
115
+ findById(id: TId): TQueryBuilder<TRawDocType | null, TQueryHelpers>;
116
+ };
117
+ /**
118
+ * Convenience alias for a Mongo-backed model.
119
+ */
120
+ type TMongoModel<TRawDocType = unknown, TQueryHelpers = object> = TModel<TRawDocType, TQueryHelpers, string | TObjectId, TMongoFilterQuery<TRawDocType>>;
121
+ /**
122
+ * Extract raw document type from a Model
123
+ */
124
+ type TExtractDocType<M> = M extends TModel<infer TRawDocType, unknown, unknown, unknown> ? TRawDocType : never;
125
+ /**
126
+ * Extract hydrated document type from a Model
127
+ */
128
+ type TExtractHydratedDoc<M> = M extends TModel<infer TRawDocType, unknown, infer TId, unknown> ? THydratedDocument<TRawDocType, TId> : never;
129
+
130
+ /**
131
+ * react-data-kit - React Data Kit Types
132
+ *
133
+ * Core types for the react-data-kit server action and components.
134
+ */
135
+
136
+ /**
137
+ * Sort options type that references keys from the item type
138
+ */
139
+ type TSortOptions<T> = {
140
+ [K in keyof T]?: TSortOrder;
141
+ };
142
+ /**
143
+ * Sort entry for array-based sorting
144
+ */
145
+ type TSortEntry = {
146
+ path: string;
147
+ value: 1 | -1;
148
+ };
149
+ /**
150
+ * Filter configuration for automatic filtering
151
+ */
152
+ type TFilterConfig = {
153
+ [key: string]: {
154
+ type: 'regex' | 'exact';
155
+ field?: string;
156
+ };
157
+ };
158
+ /**
159
+ * Custom filter configuration
160
+ * Allows defining custom filter functions for specific filter keys
161
+ */
162
+ type TFilterCustomConfig<T = unknown> = {
163
+ [id: string]: (data: unknown) => TMongoFilterQuery<T>;
164
+ };
165
+ /**
166
+ * Variant of TFilterCustomConfig that allows customizing the returned filter shape.
167
+ * Useful for Mongo (operator-based) vs. other ORMs (where clauses) in the future.
168
+ */
169
+ type TFilterCustomConfigWithFilter<TDoc = unknown, TFilter = TMongoFilterQuery<TDoc>> = {
170
+ [id: string]: (data: unknown) => TFilter;
171
+ };
172
+ /**
173
+ * React Data Kit server action input
174
+ */
175
+ type TDataKitInput<T = unknown> = {
176
+ action?: 'FETCH';
177
+ page?: number;
178
+ limit?: number;
179
+ sort?: TSortOptions<T>;
180
+ sorts?: TSortEntry[];
181
+ query?: Record<string, unknown>;
182
+ filter?: Record<string, unknown>;
183
+ filterConfig?: TFilterConfig;
184
+ filterCustom?: TFilterCustomConfig<T>;
185
+ };
186
+ /**
187
+ * React Data Kit server action result
188
+ */
189
+ type TDataKitResult<R> = {
190
+ type: 'ITEMS';
191
+ items: R[];
192
+ documentTotal: number;
193
+ };
194
+ /**
195
+ * Pagination info for client-side use
196
+ */
197
+ type TPaginationInfo = {
198
+ currentPage: number;
199
+ totalPages: number;
200
+ totalItems: number;
201
+ itemsPerPage: number;
202
+ hasNextPage: boolean;
203
+ hasPrevPage: boolean;
204
+ };
205
+ /**
206
+ * Calculate pagination info from react-data-kit result
207
+ */
208
+ declare const calculatePagination: (page: number, limit: number, total: number) => TPaginationInfo;
209
+ /**
210
+ * React Data Kit Adapter Interface
211
+ * Defines the contract for a database adapter.
212
+ */
213
+ type TDataKitAdapter<T> = (params: Readonly<{
214
+ filter: Record<string, unknown>;
215
+ sorts: TSortEntry[];
216
+ limit: number;
217
+ page: number;
218
+ skip: number;
219
+ input: TDataKitInput<T>;
220
+ }>) => Promise<{
221
+ items: T[];
222
+ total: number;
223
+ }>;
224
+
225
+ export { type TDataKitInput as T, type TDataKitAdapter as a, type TMongoModel as b, type TMongoFilterQuery as c, type TFilterCustomConfigWithFilter as d, type TSortOptions as e, type TDataKitResult as f, type TExtractDocType as g, type TModel as h, type THydratedDocument as i, type TSortOrder as j, type TFilterCustomConfig as k, type TFilterConfig as l, type TMongoFilterOperators as m, type TMongoRootFilterOperators as n, type TObjectId as o, type TMongoDocument as p, type TMongoHydratedDocument as q, type TSortEntry as r, type TDocument as s, type TQueryBuilder as t, type TPopulateOptions as u, type TExtractHydratedDoc as v, type TPaginationInfo as w, calculatePagination as x };
@@ -0,0 +1,222 @@
1
+ 'use strict';
2
+
3
+ // src/server/adapters/mongoose.ts
4
+ var isProvided = (value) => value !== void 0 && value !== null && value !== "";
5
+ var mongooseAdapter = (model, options = {}) => {
6
+ const { filter: customFilterFn, filterCustom, defaultSort = { _id: -1 } } = options;
7
+ return async ({ filter, sorts, limit, skip, input }) => {
8
+ let sortOption;
9
+ if (input.sort && Object.keys(input.sort).length > 0) {
10
+ sortOption = input.sort;
11
+ } else if (sorts && sorts.length > 0) {
12
+ sortOption = sorts.reduce((acc, s) => {
13
+ if (s?.path && (s.value === 1 || s.value === -1)) {
14
+ acc[s.path] = s.value;
15
+ }
16
+ return acc;
17
+ }, {});
18
+ } else {
19
+ sortOption = defaultSort;
20
+ }
21
+ let filterQuery = {};
22
+ if (input.query) {
23
+ Object.entries(input.query).forEach(([key, value]) => {
24
+ if (isProvided(value)) {
25
+ filterQuery[key] = value;
26
+ }
27
+ });
28
+ }
29
+ if (customFilterFn) {
30
+ const customQuery = customFilterFn(filter);
31
+ filterQuery = { ...filterQuery, ...customQuery };
32
+ }
33
+ if (filter && !customFilterFn) {
34
+ if (input.filterConfig) {
35
+ Object.entries(filter).forEach(([key, value]) => {
36
+ if (isProvided(value) && input.filterConfig?.[key]) {
37
+ const config = input.filterConfig[key];
38
+ const fieldName = config?.field ?? key;
39
+ if (config?.type === "regex") {
40
+ filterQuery[fieldName] = {
41
+ $regex: value,
42
+ $options: "i"
43
+ };
44
+ } else if (config?.type === "exact") {
45
+ filterQuery[fieldName] = value;
46
+ }
47
+ }
48
+ });
49
+ } else {
50
+ Object.entries(filter).forEach(([key, value]) => {
51
+ if (isProvided(value)) {
52
+ if (typeof value === "string") {
53
+ filterQuery[key] = {
54
+ $regex: value,
55
+ $options: "i"
56
+ };
57
+ } else {
58
+ filterQuery[key] = value;
59
+ }
60
+ }
61
+ });
62
+ }
63
+ }
64
+ if (filterCustom && filter) {
65
+ Object.entries(filter).forEach(([key, value]) => {
66
+ if (isProvided(value) && filterCustom[key]) {
67
+ const customFilter = filterCustom[key](value);
68
+ filterQuery = { ...filterQuery, ...customFilter };
69
+ }
70
+ });
71
+ }
72
+ const total = await model.countDocuments(filterQuery);
73
+ const items = await model.find(filterQuery).sort(sortOption).limit(limit).skip(skip);
74
+ return { items, total };
75
+ };
76
+ };
77
+
78
+ // src/server/action.ts
79
+ var dataKitServerAction = async (props) => {
80
+ const { input, adapter, item, filter, filterCustom, defaultSort } = props;
81
+ const finalAdapter = typeof adapter === "function" ? adapter : mongooseAdapter(adapter, {
82
+ filter,
83
+ filterCustom,
84
+ defaultSort
85
+ });
86
+ switch (input.action ?? "FETCH") {
87
+ case "FETCH": {
88
+ if (!input.limit || !input.page) {
89
+ throw new Error("Invalid input: missing limit or page");
90
+ }
91
+ const limit = input.limit;
92
+ const skip = limit * (input.page - 1);
93
+ const { items, total } = await finalAdapter({
94
+ filter: input.filter ?? {},
95
+ sorts: input.sorts ?? [],
96
+ limit,
97
+ page: input.page,
98
+ skip,
99
+ input
100
+ });
101
+ const processedItems = await Promise.all(items.map((dataItem) => item(dataItem)));
102
+ return {
103
+ type: "ITEMS",
104
+ items: processedItems,
105
+ documentTotal: total
106
+ };
107
+ }
108
+ default:
109
+ throw new Error(`Unsupported action: ${input.action}`);
110
+ }
111
+ };
112
+
113
+ // src/server/adapters/memory.ts
114
+ var isProvided2 = (value) => value !== void 0 && value !== null && value !== "";
115
+ var getValueByPath = (obj, path) => {
116
+ if (!path) return void 0;
117
+ const parts = path.split(".");
118
+ let current = obj;
119
+ for (const part of parts) {
120
+ if (current && typeof current === "object" && part in current) {
121
+ current = current[part];
122
+ } else {
123
+ return void 0;
124
+ }
125
+ }
126
+ return current;
127
+ };
128
+ var matchesExact = (rowValue, needle) => {
129
+ if (Array.isArray(needle)) return needle.includes(rowValue);
130
+ return rowValue === needle;
131
+ };
132
+ var matchesRegexLike = (rowValue, needle) => {
133
+ if (!isProvided2(needle)) return true;
134
+ if (rowValue === void 0 || rowValue === null) return false;
135
+ const hay = String(rowValue);
136
+ if (needle instanceof RegExp) return needle.test(hay);
137
+ const n = String(needle);
138
+ return hay.toLowerCase().includes(n.toLowerCase());
139
+ };
140
+ var compareValues = (a, b) => {
141
+ if (a === b) return 0;
142
+ if (a === void 0 || a === null) return -1;
143
+ if (b === void 0 || b === null) return 1;
144
+ if (typeof a === "number" && typeof b === "number") return a - b;
145
+ if (typeof a === "bigint" && typeof b === "bigint") return a < b ? -1 : 1;
146
+ const as = String(a);
147
+ const bs = String(b);
148
+ return as.localeCompare(bs);
149
+ };
150
+ var normalizeSorts = (sorts) => Array.isArray(sorts) ? sorts.filter((s) => !!s?.path && (s.value === 1 || s.value === -1)) : [];
151
+ var adapterMemory = (dataset, options = {}) => {
152
+ const { defaultFilterType = "exact" } = options;
153
+ return async ({ filter, sorts, limit, skip, input }) => {
154
+ const filterConfig = input.filterConfig;
155
+ const query = input.query ?? {};
156
+ let rows = dataset.filter((row) => {
157
+ for (const [key, value] of Object.entries(query)) {
158
+ if (!isProvided2(value)) continue;
159
+ const rowValue = getValueByPath(row, key);
160
+ if (!matchesExact(rowValue, value)) return false;
161
+ }
162
+ return true;
163
+ });
164
+ const effectiveFilter = filter ?? {};
165
+ rows = rows.filter((row) => {
166
+ for (const [key, value] of Object.entries(effectiveFilter)) {
167
+ if (!isProvided2(value)) continue;
168
+ const config = filterConfig?.[key];
169
+ const field = config?.field ?? key;
170
+ const rowValue = getValueByPath(row, field);
171
+ const type = config?.type ?? defaultFilterType;
172
+ if (type === "regex") {
173
+ if (!matchesRegexLike(rowValue, value)) return false;
174
+ } else {
175
+ if (!matchesExact(rowValue, value)) return false;
176
+ }
177
+ }
178
+ return true;
179
+ });
180
+ const normalizedSorts = normalizeSorts(sorts);
181
+ if (normalizedSorts.length > 0) {
182
+ rows = [...rows].sort((ra, rb) => {
183
+ for (const s of normalizedSorts) {
184
+ const av = getValueByPath(ra, s.path);
185
+ const bv = getValueByPath(rb, s.path);
186
+ const cmp = compareValues(av, bv);
187
+ if (cmp !== 0) return s.value === 1 ? cmp : -cmp;
188
+ }
189
+ return 0;
190
+ });
191
+ }
192
+ const total = rows.length;
193
+ const items = rows.slice(skip, skip + limit);
194
+ return { items, total };
195
+ };
196
+ };
197
+
198
+ // src/server/utils.ts
199
+ var escapeRegex = (str) => {
200
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
201
+ };
202
+ var createSearchFilter = (fields) => {
203
+ return (value) => {
204
+ if (!value || typeof value !== "string") {
205
+ return {};
206
+ }
207
+ const escapedValue = escapeRegex(value);
208
+ return {
209
+ $or: fields.map((field) => ({
210
+ [field]: { $regex: escapedValue, $options: "i" }
211
+ }))
212
+ };
213
+ };
214
+ };
215
+
216
+ exports.adapterMemory = adapterMemory;
217
+ exports.createSearchFilter = createSearchFilter;
218
+ exports.dataKitServerAction = dataKitServerAction;
219
+ exports.escapeRegex = escapeRegex;
220
+ exports.mongooseAdapter = mongooseAdapter;
221
+ //# sourceMappingURL=server.cjs.map
222
+ //# sourceMappingURL=server.cjs.map