next-data-kit 3.0.0 → 4.0.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 (54) hide show
  1. package/README.md +90 -168
  2. package/dist/client/components/data-kit-table.d.ts.map +1 -1
  3. package/dist/client/components/data-kit-table.js +0 -3
  4. package/dist/client/components/data-kit-table.js.map +1 -1
  5. package/dist/client/components/data-kit.d.ts.map +1 -1
  6. package/dist/client/components/data-kit.js +0 -3
  7. package/dist/client/components/data-kit.js.map +1 -1
  8. package/dist/client/context/index.d.ts.map +1 -1
  9. package/dist/client/context/index.js +0 -6
  10. package/dist/client/context/index.js.map +1 -1
  11. package/dist/client/hooks/useDataKit.d.ts.map +1 -1
  12. package/dist/client/hooks/useDataKit.js +0 -3
  13. package/dist/client/hooks/useDataKit.js.map +1 -1
  14. package/dist/client/hooks/usePagination.d.ts.map +1 -1
  15. package/dist/client/hooks/usePagination.js +0 -6
  16. package/dist/client/hooks/usePagination.js.map +1 -1
  17. package/dist/client/hooks/useSelection.d.ts.map +1 -1
  18. package/dist/client/hooks/useSelection.js +0 -6
  19. package/dist/client/hooks/useSelection.js.map +1 -1
  20. package/dist/client/utils/index.d.ts.map +1 -1
  21. package/dist/client/utils/index.js +0 -15
  22. package/dist/client/utils/index.js.map +1 -1
  23. package/dist/index.cjs +41 -20
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +49 -99
  26. package/dist/index.d.ts +49 -99
  27. package/dist/index.js +41 -20
  28. package/dist/index.js.map +1 -1
  29. package/dist/next-data-kit-DgLsBFv3.d.cts +143 -0
  30. package/dist/next-data-kit-DgLsBFv3.d.ts +143 -0
  31. package/dist/server.cjs +43 -20
  32. package/dist/server.cjs.map +1 -1
  33. package/dist/server.d.cts +54 -14
  34. package/dist/server.d.ts +54 -14
  35. package/dist/server.js +42 -21
  36. package/dist/server.js.map +1 -1
  37. package/dist/types/component.d.ts.map +1 -1
  38. package/dist/types/database/mongo.d.ts +5 -87
  39. package/dist/types/database/mongo.d.ts.map +1 -1
  40. package/dist/types/database/mongo.js +1 -2
  41. package/dist/types/database/mongo.js.map +1 -1
  42. package/dist/types/hook.d.ts.map +1 -1
  43. package/dist/types/index.cjs.map +1 -1
  44. package/dist/types/index.d.cts +2 -2
  45. package/dist/types/index.d.ts +6 -6
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/types/index.js +1 -1
  48. package/dist/types/index.js.map +1 -1
  49. package/dist/types/next-data-kit.d.ts.map +1 -1
  50. package/dist/types/next-data-kit.js.map +1 -1
  51. package/dist/types/selectable.d.ts.map +1 -1
  52. package/package.json +6 -1
  53. package/dist/next-data-kit-DBl9PPWh.d.cts +0 -225
  54. package/dist/next-data-kit-DBl9PPWh.d.ts +0 -225
@@ -0,0 +1,143 @@
1
+ /**
2
+ * next-data-kit - Database Types (Mongo)
3
+ *
4
+ * MongoDB-specific types for filters and queries.
5
+ */
6
+ /**
7
+ * Sort order for database queries
8
+ */
9
+ type TSortOrder = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending';
10
+ /**
11
+ * Filter operators for individual fields (Mongo subset)
12
+ */
13
+ type TMongoFilterOperators<T> = {
14
+ $eq?: T;
15
+ $ne?: T;
16
+ $gt?: T;
17
+ $gte?: T;
18
+ $lt?: T;
19
+ $lte?: T;
20
+ $in?: T[];
21
+ $nin?: T[];
22
+ $exists?: boolean;
23
+ $regex?: string | RegExp;
24
+ $options?: string;
25
+ };
26
+ /**
27
+ * Mongo root operators.
28
+ */
29
+ type TMongoRootFilterOperators<T> = {
30
+ $and?: TMongoFilterQuery<T>[];
31
+ $or?: TMongoFilterQuery<T>[];
32
+ $nor?: TMongoFilterQuery<T>[];
33
+ };
34
+ /**
35
+ * Mongo filter query type.
36
+ */
37
+ type TMongoFilterQuery<T> = {
38
+ [P in keyof T]?: T[P] | TMongoFilterOperators<T[P]>;
39
+ } & TMongoRootFilterOperators<T>;
40
+ /**
41
+ * Minimal Mongoose Model interface for the adapter.
42
+ */
43
+ type TMongoModel<_TRawDocType = unknown, _TQueryHelpers = object> = {
44
+ countDocuments(filter?: any): Promise<number>;
45
+ find(filter?: any, projection?: any, options?: any): any;
46
+ };
47
+
48
+ /**
49
+ * next-data-kit - React Data Kit Types
50
+ *
51
+ * Core types for the next-data-kit server action and components.
52
+ */
53
+
54
+ /**
55
+ * Sort options type that references keys from the item type
56
+ */
57
+ type TSortOptions<T> = {
58
+ [K in keyof T]?: TSortOrder;
59
+ };
60
+ /**
61
+ * Sort entry for array-based sorting
62
+ */
63
+ type TSortEntry = {
64
+ path: string;
65
+ value: 1 | -1;
66
+ };
67
+ /**
68
+ * Filter configuration for automatic filtering
69
+ */
70
+ type TFilterConfig = {
71
+ [key: string]: {
72
+ type: 'REGEX' | 'EXACT';
73
+ field?: string;
74
+ };
75
+ };
76
+ /**
77
+ * Custom filter configuration
78
+ * Allows defining custom filter functions for specific filter keys
79
+ */
80
+ type TFilterCustomConfig<T = unknown> = {
81
+ [id: string]: (data: unknown) => TMongoFilterQuery<T>;
82
+ };
83
+ /**
84
+ * Variant of TFilterCustomConfig that allows customizing the returned filter shape.
85
+ * Useful for Mongo (operator-based) vs. other ORMs (where clauses) in the future.
86
+ */
87
+ type TFilterCustomConfigWithFilter<TDoc = unknown, TFilter = TMongoFilterQuery<TDoc>> = {
88
+ [id: string]: (data: unknown) => TFilter;
89
+ };
90
+ /**
91
+ * React Data Kit server action input
92
+ */
93
+ type TDataKitInput<T = unknown> = {
94
+ action?: 'FETCH';
95
+ page?: number;
96
+ limit?: number;
97
+ sort?: TSortOptions<T>;
98
+ sorts?: TSortEntry[];
99
+ query?: Record<string, string | number | boolean>;
100
+ filter?: Record<string, unknown>;
101
+ filterConfig?: TFilterConfig;
102
+ filterCustom?: TFilterCustomConfig<T>;
103
+ };
104
+ /**
105
+ * React Data Kit server action result
106
+ */
107
+ type TDataKitResult<R> = {
108
+ type: 'ITEMS';
109
+ items: R[];
110
+ documentTotal: number;
111
+ };
112
+ /**
113
+ * Pagination info for client-side use
114
+ */
115
+ type TPaginationInfo = {
116
+ currentPage: number;
117
+ totalPages: number;
118
+ totalItems: number;
119
+ itemsPerPage: number;
120
+ hasNextPage: boolean;
121
+ hasPrevPage: boolean;
122
+ };
123
+ /**
124
+ * Calculate pagination info from next-data-kit result
125
+ */
126
+ declare const calculatePagination: (page: number, limit: number, total: number) => TPaginationInfo;
127
+ /**
128
+ * React Data Kit Adapter Interface
129
+ * Defines the contract for a database adapter.
130
+ */
131
+ type TDataKitAdapter<T> = (params: Readonly<{
132
+ filter: Record<string, unknown>;
133
+ sorts: TSortEntry[];
134
+ limit: number;
135
+ page: number;
136
+ skip: number;
137
+ input: TDataKitInput<T>;
138
+ }>) => Promise<{
139
+ items: T[];
140
+ total: number;
141
+ }>;
142
+
143
+ export { type TDataKitInput as T, type TMongoFilterQuery as a, type TFilterCustomConfigWithFilter as b, type TSortOptions as c, type TDataKitResult as d, type TDataKitAdapter as e, type TMongoModel as f, type TSortOrder as g, type TFilterCustomConfig as h, type TFilterConfig as i, type TSortEntry as j, type TMongoFilterOperators as k, type TMongoRootFilterOperators as l, type TPaginationInfo as m, calculatePagination as n };
@@ -0,0 +1,143 @@
1
+ /**
2
+ * next-data-kit - Database Types (Mongo)
3
+ *
4
+ * MongoDB-specific types for filters and queries.
5
+ */
6
+ /**
7
+ * Sort order for database queries
8
+ */
9
+ type TSortOrder = 1 | -1 | 'asc' | 'desc' | 'ascending' | 'descending';
10
+ /**
11
+ * Filter operators for individual fields (Mongo subset)
12
+ */
13
+ type TMongoFilterOperators<T> = {
14
+ $eq?: T;
15
+ $ne?: T;
16
+ $gt?: T;
17
+ $gte?: T;
18
+ $lt?: T;
19
+ $lte?: T;
20
+ $in?: T[];
21
+ $nin?: T[];
22
+ $exists?: boolean;
23
+ $regex?: string | RegExp;
24
+ $options?: string;
25
+ };
26
+ /**
27
+ * Mongo root operators.
28
+ */
29
+ type TMongoRootFilterOperators<T> = {
30
+ $and?: TMongoFilterQuery<T>[];
31
+ $or?: TMongoFilterQuery<T>[];
32
+ $nor?: TMongoFilterQuery<T>[];
33
+ };
34
+ /**
35
+ * Mongo filter query type.
36
+ */
37
+ type TMongoFilterQuery<T> = {
38
+ [P in keyof T]?: T[P] | TMongoFilterOperators<T[P]>;
39
+ } & TMongoRootFilterOperators<T>;
40
+ /**
41
+ * Minimal Mongoose Model interface for the adapter.
42
+ */
43
+ type TMongoModel<_TRawDocType = unknown, _TQueryHelpers = object> = {
44
+ countDocuments(filter?: any): Promise<number>;
45
+ find(filter?: any, projection?: any, options?: any): any;
46
+ };
47
+
48
+ /**
49
+ * next-data-kit - React Data Kit Types
50
+ *
51
+ * Core types for the next-data-kit server action and components.
52
+ */
53
+
54
+ /**
55
+ * Sort options type that references keys from the item type
56
+ */
57
+ type TSortOptions<T> = {
58
+ [K in keyof T]?: TSortOrder;
59
+ };
60
+ /**
61
+ * Sort entry for array-based sorting
62
+ */
63
+ type TSortEntry = {
64
+ path: string;
65
+ value: 1 | -1;
66
+ };
67
+ /**
68
+ * Filter configuration for automatic filtering
69
+ */
70
+ type TFilterConfig = {
71
+ [key: string]: {
72
+ type: 'REGEX' | 'EXACT';
73
+ field?: string;
74
+ };
75
+ };
76
+ /**
77
+ * Custom filter configuration
78
+ * Allows defining custom filter functions for specific filter keys
79
+ */
80
+ type TFilterCustomConfig<T = unknown> = {
81
+ [id: string]: (data: unknown) => TMongoFilterQuery<T>;
82
+ };
83
+ /**
84
+ * Variant of TFilterCustomConfig that allows customizing the returned filter shape.
85
+ * Useful for Mongo (operator-based) vs. other ORMs (where clauses) in the future.
86
+ */
87
+ type TFilterCustomConfigWithFilter<TDoc = unknown, TFilter = TMongoFilterQuery<TDoc>> = {
88
+ [id: string]: (data: unknown) => TFilter;
89
+ };
90
+ /**
91
+ * React Data Kit server action input
92
+ */
93
+ type TDataKitInput<T = unknown> = {
94
+ action?: 'FETCH';
95
+ page?: number;
96
+ limit?: number;
97
+ sort?: TSortOptions<T>;
98
+ sorts?: TSortEntry[];
99
+ query?: Record<string, string | number | boolean>;
100
+ filter?: Record<string, unknown>;
101
+ filterConfig?: TFilterConfig;
102
+ filterCustom?: TFilterCustomConfig<T>;
103
+ };
104
+ /**
105
+ * React Data Kit server action result
106
+ */
107
+ type TDataKitResult<R> = {
108
+ type: 'ITEMS';
109
+ items: R[];
110
+ documentTotal: number;
111
+ };
112
+ /**
113
+ * Pagination info for client-side use
114
+ */
115
+ type TPaginationInfo = {
116
+ currentPage: number;
117
+ totalPages: number;
118
+ totalItems: number;
119
+ itemsPerPage: number;
120
+ hasNextPage: boolean;
121
+ hasPrevPage: boolean;
122
+ };
123
+ /**
124
+ * Calculate pagination info from next-data-kit result
125
+ */
126
+ declare const calculatePagination: (page: number, limit: number, total: number) => TPaginationInfo;
127
+ /**
128
+ * React Data Kit Adapter Interface
129
+ * Defines the contract for a database adapter.
130
+ */
131
+ type TDataKitAdapter<T> = (params: Readonly<{
132
+ filter: Record<string, unknown>;
133
+ sorts: TSortEntry[];
134
+ limit: number;
135
+ page: number;
136
+ skip: number;
137
+ input: TDataKitInput<T>;
138
+ }>) => Promise<{
139
+ items: T[];
140
+ total: number;
141
+ }>;
142
+
143
+ export { type TDataKitInput as T, type TMongoFilterQuery as a, type TFilterCustomConfigWithFilter as b, type TSortOptions as c, type TDataKitResult as d, type TDataKitAdapter as e, type TMongoModel as f, type TSortOrder as g, type TFilterCustomConfig as h, type TFilterConfig as i, type TSortEntry as j, type TMongoFilterOperators as k, type TMongoRootFilterOperators as l, type TPaginationInfo as m, calculatePagination as n };
package/dist/server.cjs CHANGED
@@ -3,6 +3,11 @@
3
3
  var zod = require('zod');
4
4
 
5
5
  // src/server/utils.ts
6
+ var isProvided = (value) => value !== void 0 && value !== null && value !== "";
7
+ var isSafeKey = (key) => {
8
+ const unsafeKeys = ["__proto__", "constructor", "prototype"];
9
+ return !unsafeKeys.includes(key);
10
+ };
6
11
  var escapeRegex = (str) => {
7
12
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
8
13
  };
@@ -21,11 +26,6 @@ var createSearchFilter = (fields) => {
21
26
  };
22
27
 
23
28
  // src/server/adapters/mongoose.ts
24
- var isProvided = (value) => value !== void 0 && value !== null && value !== "";
25
- var isSafeKey = (key) => {
26
- const unsafeKeys = ["__proto__", "constructor", "prototype"];
27
- return !unsafeKeys.includes(key);
28
- };
29
29
  var mongooseAdapter = (model, options = {}) => {
30
30
  const { filter: customFilterFn, filterCustom, defaultSort = { _id: -1 } } = options;
31
31
  return async ({ filter, sorts, limit, skip, input }) => {
@@ -100,9 +100,7 @@ var mongooseAdapter = (model, options = {}) => {
100
100
  };
101
101
 
102
102
  // src/server/action.ts
103
- var dataKitServerAction = async (props) => {
104
- const { input, adapter, item, maxLimit = 100, filterCustom, queryAllowed } = props;
105
- const filterAllowed = filterCustom ? Object.keys(filterCustom) : void 0;
103
+ async function executeDataKit(input, adapter, item, maxLimit, filterAllowed, queryAllowed) {
106
104
  if (input.query) {
107
105
  const safeQuery = {};
108
106
  Object.keys(input.query).forEach((key) => {
@@ -133,7 +131,6 @@ var dataKitServerAction = async (props) => {
133
131
  });
134
132
  input.filter = safeFilter;
135
133
  }
136
- const finalAdapter = typeof adapter === "function" ? adapter : mongooseAdapter(adapter, props);
137
134
  switch (input.action ?? "FETCH") {
138
135
  case "FETCH": {
139
136
  if (!input.limit || !input.page) {
@@ -141,7 +138,7 @@ var dataKitServerAction = async (props) => {
141
138
  }
142
139
  const limit = Math.min(input.limit, maxLimit);
143
140
  const skip = limit * (input.page - 1);
144
- const { items, total } = await finalAdapter({
141
+ const { items, total } = await adapter({
145
142
  filter: input.filter ?? {},
146
143
  sorts: input.sorts ?? [],
147
144
  limit,
@@ -159,7 +156,26 @@ var dataKitServerAction = async (props) => {
159
156
  default:
160
157
  throw new Error(`Unsupported action: ${input.action}`);
161
158
  }
162
- };
159
+ }
160
+ async function dataKitServerAction(props) {
161
+ const { input, item, maxLimit = 100, queryAllowed, filterAllowed: explicitFilterAllowed } = props;
162
+ const filterCustom = "filterCustom" in props ? props.filterCustom : void 0;
163
+ const filterAllowed = explicitFilterAllowed ?? (filterCustom ? Object.keys(filterCustom) : void 0);
164
+ let finalAdapter;
165
+ if ("adapter" in props && props.adapter) {
166
+ finalAdapter = props.adapter;
167
+ } else if ("model" in props && props.model) {
168
+ const model = props.model;
169
+ finalAdapter = mongooseAdapter(model, {
170
+ filter: props.filter,
171
+ filterCustom: props.filterCustom,
172
+ defaultSort: props.defaultSort
173
+ });
174
+ } else {
175
+ throw new Error("Either model or adapter must be provided");
176
+ }
177
+ return executeDataKit(input, finalAdapter, item, maxLimit, filterAllowed, queryAllowed);
178
+ }
163
179
 
164
180
  // src/server/adapters/memory.ts
165
181
  var isProvided2 = (value) => value !== void 0 && value !== null && value !== "";
@@ -250,15 +266,20 @@ var dataKitSchemaZod = zod.z.object({
250
266
  limit: zod.z.number().int().positive().optional(),
251
267
  query: zod.z.record(zod.z.string(), zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean()])).optional(),
252
268
  filter: zod.z.record(zod.z.string(), zod.z.union([zod.z.string(), zod.z.number(), zod.z.boolean(), zod.z.null()])).optional(),
253
- filterConfig: zod.z.record(zod.z.string(), zod.z.object({
254
- type: zod.z.enum(["REGEX", "EXACT"]),
255
- field: zod.z.string().optional()
256
- })).optional(),
257
- sorts: zod.z.array(zod.z.object({
258
- path: zod.z.string().max(100),
259
- // Limit path length to prevent abuse
260
- value: zod.z.literal(-1).or(zod.z.literal(1))
261
- })).max(5).optional(),
269
+ filterConfig: zod.z.record(
270
+ zod.z.string(),
271
+ zod.z.object({
272
+ type: zod.z.enum(["REGEX", "EXACT"]),
273
+ field: zod.z.string().optional()
274
+ })
275
+ ).optional(),
276
+ sorts: zod.z.array(
277
+ zod.z.object({
278
+ path: zod.z.string().max(100),
279
+ // Limit path length to prevent abuse
280
+ value: zod.z.literal(-1).or(zod.z.literal(1))
281
+ })
282
+ ).max(5).optional(),
262
283
  // Limit to 5 sort fields
263
284
  sort: zod.z.record(zod.z.string(), zod.z.literal(1).or(zod.z.literal(-1))).optional()
264
285
  });
@@ -268,6 +289,8 @@ exports.createSearchFilter = createSearchFilter;
268
289
  exports.dataKitSchemaZod = dataKitSchemaZod;
269
290
  exports.dataKitServerAction = dataKitServerAction;
270
291
  exports.escapeRegex = escapeRegex;
292
+ exports.isProvided = isProvided;
293
+ exports.isSafeKey = isSafeKey;
271
294
  exports.mongooseAdapter = mongooseAdapter;
272
295
  //# sourceMappingURL=server.cjs.map
273
296
  //# sourceMappingURL=server.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server/utils.ts","../src/server/adapters/mongoose.ts","../src/server/action.ts","../src/server/adapters/memory.ts","../src/server/schema.ts"],"names":["isProvided","z"],"mappings":"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","file":"server.cjs","sourcesContent":["/**\n * next-data-kit - Server Utilities\n */\n\nimport type { TMongoFilterQuery } from '../types';\n\n/**\n * Helper to escape regex special characters in a string\n */\nexport const escapeRegex = (str: string): string => {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n};\n\n/**\n * Create a search filter for multiple fields\n * \n * @example\n * ```typescript\n * filterCustom: {\n * search: createSearchFilter(['name', 'email', 'phone'])\n * }\n * ```\n */\nexport const createSearchFilter = <T>(\n fields: (keyof T | string)[]\n): (value: unknown) => TMongoFilterQuery<T> => {\n return (value: unknown): TMongoFilterQuery<T> => {\n if (!value || typeof value !== 'string') {\n return {} as TMongoFilterQuery<T>;\n }\n\n const escapedValue = escapeRegex(value);\n return {\n $or: fields.map((field) => ({\n [field]: { $regex: escapedValue, $options: 'i' },\n })),\n } as TMongoFilterQuery<T>;\n };\n};\n","/**\n * next-data-kit - Mongoose Adapter\n *\n * Database adapter for Mongoose/MongoDB.\n */\n\nimport type {\n TMongoModel,\n TMongoFilterQuery,\n TSortOrder,\n TSortOptions,\n TFilterCustomConfigWithFilter,\n TDataKitAdapter,\n TExtractDocType,\n} from '../../types';\n\n// ** ============================================================================\n// ** Helpers\n// ** ============================================================================\n\nimport { escapeRegex } from '../utils';\n\n// ** ============================================================================\n// ** Helpers\n// ** ============================================================================\n\nconst isProvided = (value: unknown): boolean =>\n value !== undefined && value !== null && value !== '';\n\nconst isSafeKey = (key: string): boolean => {\n const unsafeKeys = ['__proto__', 'constructor', 'prototype'];\n return !unsafeKeys.includes(key);\n};\n\n// ** ============================================================================\n// ** Adapter\n// ** ============================================================================\n\nexport const mongooseAdapter = <\n M extends TMongoModel<unknown, object>,\n DocType = TExtractDocType<M>\n>(\n model: M,\n options: Readonly<{\n filter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<DocType>;\n filterCustom?: TFilterCustomConfigWithFilter<DocType, TMongoFilterQuery<DocType>>;\n defaultSort?: TSortOptions<DocType>;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n [key: string]: any;\n }> = {}\n): TDataKitAdapter<DocType> => {\n // ** Deconstruct options\n const { filter: customFilterFn, filterCustom, defaultSort = { _id: -1 } as TSortOptions<DocType> } = options;\n\n return async ({ filter, sorts, limit, skip, input }) => {\n // ** Normalize sort\n let sortOption: Record<string, TSortOrder>;\n\n if (input.sort && Object.keys(input.sort).length > 0) {\n sortOption = input.sort as Record<string, TSortOrder>;\n } else if (sorts && sorts.length > 0) {\n sortOption = sorts.reduce<Record<string, TSortOrder>>((acc, s) => {\n if (s?.path && (s.value === 1 || s.value === -1)) {\n acc[s.path] = s.value;\n }\n return acc;\n }, {});\n } else {\n sortOption = defaultSort as Record<string, TSortOrder>;\n }\n\n // ** Construct filter query\n let filterQuery: TMongoFilterQuery<DocType> = {};\n\n // ** Query params (exact match)\n if (input.query) {\n Object.entries(input.query).forEach(([key, value]) => {\n if (isProvided(value) && isSafeKey(key)) {\n (filterQuery as Record<string, unknown>)[key] = value;\n }\n });\n }\n\n // ** Custom filter function\n if (customFilterFn) {\n const customQuery = customFilterFn(filter);\n filterQuery = { ...filterQuery, ...customQuery };\n }\n\n // ** User defined filters\n if (filter && !customFilterFn) {\n if (input.filterConfig) {\n Object.entries(filter).forEach(([key, value]) => {\n if (isProvided(value) && isSafeKey(key) && input.filterConfig?.[key]) {\n const config = input.filterConfig[key];\n const fieldName = config?.field ?? key;\n\n if (config?.type === 'REGEX') {\n (filterQuery as Record<string, unknown>)[fieldName] = {\n $regex: escapeRegex(String(value)),\n $options: 'i',\n };\n } else if (config?.type === 'EXACT') {\n (filterQuery as Record<string, unknown>)[fieldName] = value;\n }\n }\n });\n } else {\n // ** Default automatic filtering\n Object.entries(filter).forEach(([key, value]) => {\n if (isProvided(value) && isSafeKey(key)) {\n if (typeof value === 'string') {\n (filterQuery as Record<string, unknown>)[key] = {\n $regex: escapeRegex(value),\n $options: 'i',\n };\n } else if (typeof value === 'number' || typeof value === 'boolean') {\n (filterQuery as Record<string, unknown>)[key] = value;\n }\n }\n });\n }\n }\n\n // ** Custom filter logic (filterCustom)\n if (filterCustom && filter) {\n Object.entries(filter).forEach(([key, value]) => {\n if (isProvided(value) && isSafeKey(key) && filterCustom[key]) {\n const customFilter = filterCustom[key]!(value);\n filterQuery = { ...filterQuery, ...customFilter };\n }\n });\n }\n\n // ** Execute queries\n const total = await model.countDocuments(filterQuery as TMongoFilterQuery<unknown>);\n const items = await model\n .find(filterQuery as TMongoFilterQuery<unknown>)\n .sort(sortOption)\n .limit(limit)\n .skip(skip) as unknown as DocType[];\n\n return { items, total };\n };\n};\n","/**\n * next-data-kit - Server Action\n *\n * The main server-side function for handling table data fetching\n * with pagination, filtering, and sorting.\n */\n\nimport { mongooseAdapter } from './adapters/mongoose';\nimport type { TDataKitInput, TDataKitResult, TDataKitAdapter, TMongoModel, TMongoFilterQuery, TFilterCustomConfigWithFilter, TSortOptions } from '../types';\n\n// ** ============================================================================\n// ** Types\n// ** ============================================================================\n\nexport type TDataKitServerActionOptions<T, R> = {\n\t// ** The input from the client\n\tinput: TDataKitInput<T>;\n\t// ** The database adapter or Mongoose model\n\tadapter: TDataKitAdapter<T> | TMongoModel<T>;\n\t// ** Function to transform each item before returning\n\titem: (item: T) => Promise<R> | R;\n\t// ** Custom filter function\n\tfilter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<T>;\n\t// ** Custom filter configuration (defines allowed filter keys)\n\tfilterCustom?: TFilterCustomConfigWithFilter<T, TMongoFilterQuery<T>>;\n\t// ** Default sort options\n\tdefaultSort?: TSortOptions<T>;\n\t// ** Maximum limit per page (default: 100)\n\tmaxLimit?: number;\n\t// ** Whitelist of allowed query fields\n\tqueryAllowed?: string[];\n};\n\n// ** ============================================================================\n// ** Server Action\n// ** ============================================================================\n\nexport const dataKitServerAction = async <T, R>(props: Readonly<TDataKitServerActionOptions<T, R>>): Promise<TDataKitResult<R>> => {\n\t// ** Deconstruct Props\n\tconst { input, adapter, item, maxLimit = 100, filterCustom, queryAllowed } = props;\n\n\t// ** Auto-generate filterAllowed from filterCustom keys (server defines what's allowed)\n\tconst filterAllowed = filterCustom ? Object.keys(filterCustom) : undefined;\n\n\t// ** Whitelist filtering for security (if configured)\n\t// ** We do this here instead of in the adapter to keep the adapter simple and \"dumb\"\n\n\t// ** Check Query\n\tif (input.query) {\n\t\tconst safeQuery: Record<string, string | number | boolean> = {};\n\t\tObject.keys(input.query).forEach(key => {\n\t\t\tif (queryAllowed && !queryAllowed.includes(key)) {\n\t\t\t\tthrow new Error(`[Security] Query field '${key}' is not allowed.`);\n\t\t\t}\n\t\t\t// ** Enforce primitive values only (Anti-NoSQL Injection)\n\t\t\tconst val = input.query![key];\n\t\t\tif (val !== null && typeof val === 'object') {\n\t\t\t\tthrow new Error(`[Security] Query value for '${key}' must be a primitive.`);\n\t\t\t}\n\t\t\tif (val !== undefined) {\n\t\t\t\tsafeQuery[key] = val;\n\t\t\t}\n\t\t});\n\t\tinput.query = safeQuery;\n\t}\n\n\t// ** Check Filter\n\tif (input.filter) {\n\t\tconst safeFilter: Record<string, unknown> = {};\n\t\tObject.keys(input.filter).forEach(key => {\n\t\t\tif (filterAllowed && !filterAllowed.includes(key)) {\n\t\t\t\tthrow new Error(`[Security] Filter field '${key}' is not allowed.`);\n\t\t\t}\n\t\t\t// ** Enforce primitive values only (Anti-NoSQL Injection)\n\t\t\tconst val = input.filter![key];\n\t\t\tif (val !== null && typeof val === 'object') {\n\t\t\t\tthrow new Error(`[Security] Filter value for '${key}' must be a primitive.`);\n\t\t\t}\n\t\t\tsafeFilter[key] = val;\n\t\t});\n\t\tinput.filter = safeFilter;\n\t}\n\n\t// ** Determine adapter\n\tconst finalAdapter: TDataKitAdapter<T> = typeof adapter === 'function' ? adapter : mongooseAdapter(adapter as TMongoModel<T>, props);\n\n\t// ** Handle action\n\tswitch (input.action ?? 'FETCH') {\n\t\tcase 'FETCH': {\n\t\t\tif (!input.limit || !input.page) {\n\t\t\t\tthrow new Error('Invalid input: missing limit or page');\n\t\t\t}\n\n\t\t\tconst limit = Math.min(input.limit, maxLimit);\n\t\t\tconst skip = limit * (input.page - 1);\n\n\t\t\t// ** Fetch data using adapter\n\t\t\tconst { items, total } = await finalAdapter({\n\t\t\t\tfilter: input.filter ?? {},\n\t\t\t\tsorts: input.sorts ?? [],\n\t\t\t\tlimit,\n\t\t\t\tpage: input.page,\n\t\t\t\tskip,\n\t\t\t\tinput,\n\t\t\t});\n\n\t\t\t// ** Process each item through the item mapper function\n\t\t\tconst processedItems = await Promise.all(items.map(dataItem => item(dataItem)));\n\n\t\t\treturn {\n\t\t\t\ttype: 'ITEMS',\n\t\t\t\titems: processedItems,\n\t\t\t\tdocumentTotal: total,\n\t\t\t};\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported action: ${(input as { action?: string }).action}`);\n\t}\n};\n","/**\n * next-data-kit - Memory Adapter\n *\n * In-memory adapter for demos, tests, and local playgrounds.\n * Implements the React Data Kit adapter contract over an array dataset.\n */\n\nimport type { TFilterConfig, TSortEntry, TDataKitAdapter } from '../../types';\n\nconst isProvided = (value: unknown): boolean =>\n value !== undefined && value !== null && value !== '';\n\nconst getValueByPath = (obj: unknown, path: string): unknown => {\n if (!path) return undefined;\n const parts = path.split('.');\n let current: unknown = obj;\n for (const part of parts) {\n if (current && typeof current === 'object' && part in (current as Record<string, unknown>)) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return current;\n};\n\nconst matchesExact = (rowValue: unknown, needle: unknown): boolean => {\n if (Array.isArray(needle)) return needle.includes(rowValue as never);\n return rowValue === needle;\n};\n\nconst matchesRegexLike = (rowValue: unknown, needle: unknown): boolean => {\n if (!isProvided(needle)) return true;\n if (rowValue === undefined || rowValue === null) return false;\n const hay = String(rowValue);\n\n if (needle instanceof RegExp) return needle.test(hay);\n const n = String(needle);\n return hay.toLowerCase().includes(n.toLowerCase());\n};\n\nconst compareValues = (a: unknown, b: unknown): number => {\n if (a === b) return 0;\n if (a === undefined || a === null) return -1;\n if (b === undefined || b === null) return 1;\n\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n if (typeof a === 'bigint' && typeof b === 'bigint') return a < b ? -1 : 1;\n\n const as = String(a);\n const bs = String(b);\n return as.localeCompare(bs);\n};\n\nconst normalizeSorts = (sorts: TSortEntry[] | undefined): TSortEntry[] =>\n Array.isArray(sorts) ? sorts.filter((s) => !!s?.path && (s.value === 1 || s.value === -1)) : [];\n\n/**\n * Creates an adapter that pages/filters/sorts an in-memory dataset.\n */\nexport const adapterMemory = <T extends Record<string, unknown>>(\n dataset: ReadonlyArray<T>,\n options: Readonly<{\n /** default behavior for filter keys not present in filterConfig */\n defaultFilterType?: 'regex' | 'exact';\n }> = {}\n): TDataKitAdapter<T> => {\n const { defaultFilterType = 'exact' } = options;\n\n return async ({ filter, sorts, limit, skip, input }) => {\n const filterConfig: TFilterConfig | undefined = input.filterConfig;\n const query = input.query ?? {};\n\n // 1) Apply query (exact match)\n let rows = dataset.filter((row) => {\n for (const [key, value] of Object.entries(query)) {\n if (!isProvided(value)) continue;\n const rowValue = getValueByPath(row, key);\n if (!matchesExact(rowValue, value)) return false;\n }\n return true;\n });\n\n // 2) Apply filter (via filterConfig when present)\n const effectiveFilter = filter ?? {};\n rows = rows.filter((row) => {\n for (const [key, value] of Object.entries(effectiveFilter)) {\n if (!isProvided(value)) continue;\n\n const config = filterConfig?.[key];\n const field = config?.field ?? key;\n const rowValue = getValueByPath(row, field);\n\n const type = config?.type ?? defaultFilterType;\n if (type === 'regex') {\n if (!matchesRegexLike(rowValue, value)) return false;\n } else {\n if (!matchesExact(rowValue, value)) return false;\n }\n }\n return true;\n });\n\n // 3) Sort\n const normalizedSorts = normalizeSorts(sorts);\n if (normalizedSorts.length > 0) {\n rows = [...rows].sort((ra, rb) => {\n for (const s of normalizedSorts) {\n const av = getValueByPath(ra, s.path);\n const bv = getValueByPath(rb, s.path);\n const cmp = compareValues(av, bv);\n if (cmp !== 0) return s.value === 1 ? cmp : -cmp;\n }\n return 0;\n });\n }\n\n const total = rows.length;\n const items = rows.slice(skip, skip + limit);\n return { items, total };\n };\n};\n","import { z } from 'zod';\n\nexport const dataKitSchemaZod = z.object({\n page: z.number().int().positive().optional(),\n limit: z.number().int().positive().optional(),\n query: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n filter: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),\n filterConfig: z.record(z.string(), z.object({\n type: z.enum([\"REGEX\", \"EXACT\"]),\n field: z.string().optional()\n })).optional(),\n sorts: z.array(z.object({\n path: z.string().max(100), // Limit path length to prevent abuse\n value: z.literal(-1).or(z.literal(1))\n })).max(5).optional(), // Limit to 5 sort fields\n sort: z.record(z.string(), z.literal(1).or(z.literal(-1))).optional(),\n});\n\nexport type TDataKitSchemaZod = z.infer<typeof dataKitSchemaZod>;\n"]}
1
+ {"version":3,"sources":["../src/server/utils.ts","../src/server/adapters/mongoose.ts","../src/server/action.ts","../src/server/adapters/memory.ts","../src/server/schema.ts"],"names":["isProvided","z"],"mappings":"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","file":"server.cjs","sourcesContent":["/**\n * next-data-kit - Server Utilities\n */\n\nimport type { TMongoFilterQuery } from '../types';\n\n/**\n * Check if a value is provided (not undefined, null, or empty string)\n */\nexport const isProvided = (value: unknown): boolean => value !== undefined && value !== null && value !== '';\n\n/**\n * Check if a key is safe (not a prototype pollution key)\n */\nexport const isSafeKey = (key: string): boolean => {\n\tconst unsafeKeys = ['__proto__', 'constructor', 'prototype'];\n\treturn !unsafeKeys.includes(key);\n};\n\n/**\n * Helper to escape regex special characters in a string\n */\nexport const escapeRegex = (str: string): string => {\n\treturn str.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n};\n\n/**\n * Create a search filter for multiple fields\n *\n * @example\n * ```typescript\n * filterCustom: {\n * search: createSearchFilter(['name', 'email', 'phone'])\n * }\n * ```\n */\nexport const createSearchFilter = <T>(fields: (keyof T | string)[]): ((value: unknown) => TMongoFilterQuery<T>) => {\n\treturn (value: unknown): TMongoFilterQuery<T> => {\n\t\tif (!value || typeof value !== 'string') {\n\t\t\treturn {} as TMongoFilterQuery<T>;\n\t\t}\n\n\t\tconst escapedValue = escapeRegex(value);\n\t\treturn {\n\t\t\t$or: fields.map(field => ({\n\t\t\t\t[field]: { $regex: escapedValue, $options: 'i' },\n\t\t\t})),\n\t\t} as TMongoFilterQuery<T>;\n\t};\n};\n","/**\n * next-data-kit - Mongoose Adapter\n *\n * Database adapter for Mongoose/MongoDB.\n */\n\nimport type { TMongoModel, TMongoFilterQuery, TSortOrder, TSortOptions, TFilterCustomConfigWithFilter, TDataKitAdapter } from '../../types';\nimport { escapeRegex, isProvided, isSafeKey } from '../utils';\n\nexport const mongooseAdapter = <DocType = unknown>(\n\tmodel: TMongoModel<DocType>,\n\toptions: Readonly<{\n\t\tfilter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<DocType>;\n\t\tfilterCustom?: TFilterCustomConfigWithFilter<DocType, TMongoFilterQuery<DocType>>;\n\t\tdefaultSort?: TSortOptions<DocType>;\n\t\t// eslint-disable-next-line @typescript-eslint/no-explicit-any\n\t\t[key: string]: any;\n\t}> = {},\n): TDataKitAdapter<DocType> => {\n\t// ** Deconstruct options\n\tconst { filter: customFilterFn, filterCustom, defaultSort = { _id: -1 } as TSortOptions<DocType> } = options;\n\n\treturn async ({ filter, sorts, limit, skip, input }) => {\n\t\t// ** Normalize sort\n\t\tlet sortOption: Record<string, TSortOrder>;\n\n\t\tif (input.sort && Object.keys(input.sort).length > 0) {\n\t\t\tsortOption = input.sort as Record<string, TSortOrder>;\n\t\t} else if (sorts && sorts.length > 0) {\n\t\t\tsortOption = sorts.reduce<Record<string, TSortOrder>>((acc, s) => {\n\t\t\t\tif (s?.path && (s.value === 1 || s.value === -1)) {\n\t\t\t\t\tacc[s.path] = s.value;\n\t\t\t\t}\n\t\t\t\treturn acc;\n\t\t\t}, {});\n\t\t} else {\n\t\t\tsortOption = defaultSort as Record<string, TSortOrder>;\n\t\t}\n\n\t\t// ** Construct filter query\n\t\tlet filterQuery: TMongoFilterQuery<DocType> = {};\n\n\t\t// ** Query params (exact match)\n\t\tif (input.query) {\n\t\t\tObject.entries(input.query).forEach(([key, value]) => {\n\t\t\t\tif (isProvided(value) && isSafeKey(key)) {\n\t\t\t\t\t(filterQuery as Record<string, unknown>)[key] = value;\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// ** Custom filter function\n\t\tif (customFilterFn) {\n\t\t\tconst customQuery = customFilterFn(filter);\n\t\t\tfilterQuery = { ...filterQuery, ...customQuery };\n\t\t}\n\n\t\t// ** User defined filters\n\t\tif (filter && !customFilterFn) {\n\t\t\tif (input.filterConfig) {\n\t\t\t\tObject.entries(filter).forEach(([key, value]) => {\n\t\t\t\t\tif (isProvided(value) && isSafeKey(key) && input.filterConfig?.[key]) {\n\t\t\t\t\t\tconst config = input.filterConfig[key];\n\t\t\t\t\t\tconst fieldName = config?.field ?? key;\n\n\t\t\t\t\t\tif (config?.type === 'REGEX') {\n\t\t\t\t\t\t\t(filterQuery as Record<string, unknown>)[fieldName] = {\n\t\t\t\t\t\t\t\t$regex: escapeRegex(String(value)),\n\t\t\t\t\t\t\t\t$options: 'i',\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (config?.type === 'EXACT') {\n\t\t\t\t\t\t\t(filterQuery as Record<string, unknown>)[fieldName] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t} else {\n\t\t\t\t// ** Default automatic filtering\n\t\t\t\tObject.entries(filter).forEach(([key, value]) => {\n\t\t\t\t\tif (isProvided(value) && isSafeKey(key)) {\n\t\t\t\t\t\tif (typeof value === 'string') {\n\t\t\t\t\t\t\t(filterQuery as Record<string, unknown>)[key] = {\n\t\t\t\t\t\t\t\t$regex: escapeRegex(value),\n\t\t\t\t\t\t\t\t$options: 'i',\n\t\t\t\t\t\t\t};\n\t\t\t\t\t\t} else if (typeof value === 'number' || typeof value === 'boolean') {\n\t\t\t\t\t\t\t(filterQuery as Record<string, unknown>)[key] = value;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\n\t\t// ** Custom filter logic (filterCustom)\n\t\tif (filterCustom && filter) {\n\t\t\tObject.entries(filter).forEach(([key, value]) => {\n\t\t\t\tif (isProvided(value) && isSafeKey(key) && filterCustom[key]) {\n\t\t\t\t\tconst customFilter = filterCustom[key]!(value);\n\t\t\t\t\tfilterQuery = { ...filterQuery, ...customFilter };\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// ** Execute queries\n\t\tconst total = await model.countDocuments(filterQuery as TMongoFilterQuery<unknown>);\n\t\tconst items = (await model\n\t\t\t.find(filterQuery as TMongoFilterQuery<unknown>)\n\t\t\t.sort(sortOption)\n\t\t\t.limit(limit)\n\t\t\t.skip(skip)) as unknown as DocType[];\n\n\t\treturn { items, total };\n\t};\n};\n","/**\n * next-data-kit - Server Action\n *\n * The main server-side function for handling table data fetching\n * with pagination, filtering, and sorting.\n */\n\nimport { mongooseAdapter } from './adapters/mongoose';\nimport type { Model } from 'mongoose';\nimport type { TDataKitInput, TDataKitResult, TDataKitAdapter, TMongoModel, TMongoFilterQuery, TFilterCustomConfigWithFilter, TSortOptions } from '../types';\n\n/**\n * Extract document type from a Mongoose Model.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type TExtractDocType<M> = M extends Model<infer TRawDocType, any, any, any, any, any> ? TRawDocType : never;\n\n/**\n * Base options shared by both mongoose and adapter versions\n */\ntype TBaseOptions<TDoc, R> = {\n\tinput: TDataKitInput<TDoc>;\n\titem: (item: TDoc) => Promise<R> | R;\n\tfilterAllowed?: string[];\n\tmaxLimit?: number;\n\tqueryAllowed?: (keyof TDoc | string)[];\n};\n\n/**\n * Options when using a Mongoose model\n */\ntype TMongooseOptions<M, TDoc, R> = TBaseOptions<TDoc, R> & {\n\tmodel: M;\n\tadapter?: never;\n\tfilter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<TDoc>;\n\tfilterCustom?: TFilterCustomConfigWithFilter<TDoc, TMongoFilterQuery<TDoc>>;\n\tdefaultSort?: TSortOptions<TDoc>;\n};\n\n/**\n * Options when using a custom adapter\n */\ntype TAdapterOptions<TDoc, R> = TBaseOptions<TDoc, R> & {\n\tadapter: TDataKitAdapter<TDoc>;\n\tmodel?: never;\n\tfilter?: never;\n\tfilterCustom?: TFilterCustomConfigWithFilter<TDoc, unknown>;\n\tdefaultSort?: never;\n};\n\n/**\n * Core execution logic shared by both overloads\n */\nasync function executeDataKit<TDoc, R>(input: TDataKitInput<TDoc>, adapter: TDataKitAdapter<TDoc>, item: (item: TDoc) => Promise<R> | R, maxLimit: number, filterAllowed?: string[], queryAllowed?: (keyof TDoc | string)[]): Promise<TDataKitResult<R>> {\n\t// Check Query\n\tif (input.query) {\n\t\tconst safeQuery: Record<string, string | number | boolean> = {};\n\t\tObject.keys(input.query).forEach(key => {\n\t\t\tif (queryAllowed && !queryAllowed.includes(key)) {\n\t\t\t\tthrow new Error(`[Security] Query field '${key}' is not allowed.`);\n\t\t\t}\n\t\t\tconst val = input.query![key];\n\t\t\tif (val !== null && typeof val === 'object') {\n\t\t\t\tthrow new Error(`[Security] Query value for '${key}' must be a primitive.`);\n\t\t\t}\n\t\t\tif (val !== undefined) {\n\t\t\t\tsafeQuery[key] = val;\n\t\t\t}\n\t\t});\n\t\tinput.query = safeQuery;\n\t}\n\n\t// Check Filter\n\tif (input.filter) {\n\t\tconst safeFilter: Record<string, unknown> = {};\n\t\tObject.keys(input.filter).forEach(key => {\n\t\t\tif (filterAllowed && !filterAllowed.includes(key)) {\n\t\t\t\tthrow new Error(`[Security] Filter field '${key}' is not allowed.`);\n\t\t\t}\n\t\t\tconst val = input.filter![key];\n\t\t\tif (val !== null && typeof val === 'object') {\n\t\t\t\tthrow new Error(`[Security] Filter value for '${key}' must be a primitive.`);\n\t\t\t}\n\t\t\tsafeFilter[key] = val;\n\t\t});\n\t\tinput.filter = safeFilter;\n\t}\n\n\t// Handle action\n\tswitch (input.action ?? 'FETCH') {\n\t\tcase 'FETCH': {\n\t\t\tif (!input.limit || !input.page) {\n\t\t\t\tthrow new Error('Invalid input: missing limit or page');\n\t\t\t}\n\n\t\t\tconst limit = Math.min(input.limit, maxLimit);\n\t\t\tconst skip = limit * (input.page - 1);\n\n\t\t\tconst { items, total } = await adapter({\n\t\t\t\tfilter: input.filter ?? {},\n\t\t\t\tsorts: input.sorts ?? [],\n\t\t\t\tlimit,\n\t\t\t\tpage: input.page,\n\t\t\t\tskip,\n\t\t\t\tinput,\n\t\t\t});\n\n\t\t\tconst processedItems = await Promise.all(items.map(dataItem => item(dataItem)));\n\n\t\t\treturn {\n\t\t\t\ttype: 'ITEMS',\n\t\t\t\titems: processedItems,\n\t\t\t\tdocumentTotal: total,\n\t\t\t};\n\t\t}\n\n\t\tdefault:\n\t\t\tthrow new Error(`Unsupported action: ${(input as { action?: string }).action}`);\n\t}\n}\n\n/**\n * Server action with Mongoose model (auto-infers document type)\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function dataKitServerAction<M extends Model<any>, R = unknown>(props: Readonly<TMongooseOptions<M, TExtractDocType<M>, R>>): Promise<TDataKitResult<R>>;\n\n/**\n * Server action with custom adapter\n */\nexport async function dataKitServerAction<TDoc, R = unknown>(props: Readonly<TAdapterOptions<TDoc, R>>): Promise<TDataKitResult<R>>;\n\n/**\n * Implementation\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function dataKitServerAction<M extends Model<any>, TDoc = any, R = unknown>(props: Readonly<TMongooseOptions<M, TDoc, R> | TAdapterOptions<TDoc, R>>): Promise<TDataKitResult<R>> {\n\tconst { input, item, maxLimit = 100, queryAllowed, filterAllowed: explicitFilterAllowed } = props;\n\n\t// Determine filterAllowed\n\tconst filterCustom = 'filterCustom' in props ? props.filterCustom : undefined;\n\tconst filterAllowed = explicitFilterAllowed ?? (filterCustom ? Object.keys(filterCustom) : undefined);\n\n\t// Determine adapter\n\tlet finalAdapter: TDataKitAdapter<TDoc>;\n\n\tif ('adapter' in props && props.adapter) {\n\t\tfinalAdapter = props.adapter;\n\t} else if ('model' in props && props.model) {\n\t\tconst model = props.model as unknown as TMongoModel<TDoc>;\n\t\tfinalAdapter = mongooseAdapter(model, {\n\t\t\tfilter: props.filter,\n\t\t\tfilterCustom: props.filterCustom,\n\t\t\tdefaultSort: props.defaultSort,\n\t\t}) as TDataKitAdapter<TDoc>;\n\t} else {\n\t\tthrow new Error('Either model or adapter must be provided');\n\t}\n\n\treturn executeDataKit(input, finalAdapter, item, maxLimit, filterAllowed, queryAllowed);\n}\n","/**\n * next-data-kit - Memory Adapter\n *\n * In-memory adapter for demos, tests, and local playgrounds.\n * Implements the React Data Kit adapter contract over an array dataset.\n */\n\nimport type { TFilterConfig, TSortEntry, TDataKitAdapter } from '../../types';\n\nconst isProvided = (value: unknown): boolean =>\n value !== undefined && value !== null && value !== '';\n\nconst getValueByPath = (obj: unknown, path: string): unknown => {\n if (!path) return undefined;\n const parts = path.split('.');\n let current: unknown = obj;\n for (const part of parts) {\n if (current && typeof current === 'object' && part in (current as Record<string, unknown>)) {\n current = (current as Record<string, unknown>)[part];\n } else {\n return undefined;\n }\n }\n return current;\n};\n\nconst matchesExact = (rowValue: unknown, needle: unknown): boolean => {\n if (Array.isArray(needle)) return needle.includes(rowValue as never);\n return rowValue === needle;\n};\n\nconst matchesRegexLike = (rowValue: unknown, needle: unknown): boolean => {\n if (!isProvided(needle)) return true;\n if (rowValue === undefined || rowValue === null) return false;\n const hay = String(rowValue);\n\n if (needle instanceof RegExp) return needle.test(hay);\n const n = String(needle);\n return hay.toLowerCase().includes(n.toLowerCase());\n};\n\nconst compareValues = (a: unknown, b: unknown): number => {\n if (a === b) return 0;\n if (a === undefined || a === null) return -1;\n if (b === undefined || b === null) return 1;\n\n if (typeof a === 'number' && typeof b === 'number') return a - b;\n if (typeof a === 'bigint' && typeof b === 'bigint') return a < b ? -1 : 1;\n\n const as = String(a);\n const bs = String(b);\n return as.localeCompare(bs);\n};\n\nconst normalizeSorts = (sorts: TSortEntry[] | undefined): TSortEntry[] =>\n Array.isArray(sorts) ? sorts.filter((s) => !!s?.path && (s.value === 1 || s.value === -1)) : [];\n\n/**\n * Creates an adapter that pages/filters/sorts an in-memory dataset.\n */\nexport const adapterMemory = <T extends Record<string, unknown>>(\n dataset: ReadonlyArray<T>,\n options: Readonly<{\n /** default behavior for filter keys not present in filterConfig */\n defaultFilterType?: 'regex' | 'exact';\n }> = {}\n): TDataKitAdapter<T> => {\n const { defaultFilterType = 'exact' } = options;\n\n return async ({ filter, sorts, limit, skip, input }) => {\n const filterConfig: TFilterConfig | undefined = input.filterConfig;\n const query = input.query ?? {};\n\n // 1) Apply query (exact match)\n let rows = dataset.filter((row) => {\n for (const [key, value] of Object.entries(query)) {\n if (!isProvided(value)) continue;\n const rowValue = getValueByPath(row, key);\n if (!matchesExact(rowValue, value)) return false;\n }\n return true;\n });\n\n // 2) Apply filter (via filterConfig when present)\n const effectiveFilter = filter ?? {};\n rows = rows.filter((row) => {\n for (const [key, value] of Object.entries(effectiveFilter)) {\n if (!isProvided(value)) continue;\n\n const config = filterConfig?.[key];\n const field = config?.field ?? key;\n const rowValue = getValueByPath(row, field);\n\n const type = config?.type ?? defaultFilterType;\n if (type === 'regex') {\n if (!matchesRegexLike(rowValue, value)) return false;\n } else {\n if (!matchesExact(rowValue, value)) return false;\n }\n }\n return true;\n });\n\n // 3) Sort\n const normalizedSorts = normalizeSorts(sorts);\n if (normalizedSorts.length > 0) {\n rows = [...rows].sort((ra, rb) => {\n for (const s of normalizedSorts) {\n const av = getValueByPath(ra, s.path);\n const bv = getValueByPath(rb, s.path);\n const cmp = compareValues(av, bv);\n if (cmp !== 0) return s.value === 1 ? cmp : -cmp;\n }\n return 0;\n });\n }\n\n const total = rows.length;\n const items = rows.slice(skip, skip + limit);\n return { items, total };\n };\n};\n","import { z } from 'zod';\n\nexport const dataKitSchemaZod = z.object({\n\tpage: z.number().int().positive().optional(),\n\tlimit: z.number().int().positive().optional(),\n\tquery: z.record(z.string(), z.union([z.string(), z.number(), z.boolean()])).optional(),\n\tfilter: z.record(z.string(), z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),\n\tfilterConfig: z\n\t\t.record(\n\t\t\tz.string(),\n\t\t\tz.object({\n\t\t\t\ttype: z.enum(['REGEX', 'EXACT']),\n\t\t\t\tfield: z.string().optional(),\n\t\t\t}),\n\t\t)\n\t\t.optional(),\n\tsorts: z\n\t\t.array(\n\t\t\tz.object({\n\t\t\t\tpath: z.string().max(100), // Limit path length to prevent abuse\n\t\t\t\tvalue: z.literal(-1).or(z.literal(1)),\n\t\t\t}),\n\t\t)\n\t\t.max(5)\n\t\t.optional(), // Limit to 5 sort fields\n\tsort: z.record(z.string(), z.literal(1).or(z.literal(-1))).optional(),\n});\n\nexport type TDataKitSchemaZod = z.infer<typeof dataKitSchemaZod>;\n"]}
package/dist/server.d.cts CHANGED
@@ -1,5 +1,6 @@
1
- import { T as TDataKitInput, a as TDataKitAdapter, b as TMongoModel, c as TMongoFilterQuery, d as TFilterCustomConfigWithFilter, e as TSortOptions, f as TDataKitResult, g as TExtractDocType } from './next-data-kit-DBl9PPWh.cjs';
2
- export { l as TFilterConfig, k as TFilterCustomConfig, i as THydratedDocument, h as TModel, p as TMongoDocument, m as TMongoFilterOperators, q as TMongoHydratedDocument, n as TMongoRootFilterOperators, o as TObjectId, j as TSortOrder } from './next-data-kit-DBl9PPWh.cjs';
1
+ import { Model } from 'mongoose';
2
+ import { T as TDataKitInput, a as TMongoFilterQuery, b as TFilterCustomConfigWithFilter, c as TSortOptions, d as TDataKitResult, e as TDataKitAdapter, f as TMongoModel } from './next-data-kit-DgLsBFv3.cjs';
3
+ export { i as TFilterConfig, h as TFilterCustomConfig, g as TSortOrder } from './next-data-kit-DgLsBFv3.cjs';
3
4
  import { z } from 'zod';
4
5
 
5
6
  /**
@@ -9,17 +10,48 @@ import { z } from 'zod';
9
10
  * with pagination, filtering, and sorting.
10
11
  */
11
12
 
12
- type TDataKitServerActionOptions<T, R> = {
13
- input: TDataKitInput<T>;
14
- adapter: TDataKitAdapter<T> | TMongoModel<T>;
15
- item: (item: T) => Promise<R> | R;
16
- filter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<T>;
17
- filterCustom?: TFilterCustomConfigWithFilter<T, TMongoFilterQuery<T>>;
18
- defaultSort?: TSortOptions<T>;
13
+ /**
14
+ * Extract document type from a Mongoose Model.
15
+ */
16
+ type TExtractDocType<M> = M extends Model<infer TRawDocType, any, any, any, any, any> ? TRawDocType : never;
17
+ /**
18
+ * Base options shared by both mongoose and adapter versions
19
+ */
20
+ type TBaseOptions<TDoc, R> = {
21
+ input: TDataKitInput<TDoc>;
22
+ item: (item: TDoc) => Promise<R> | R;
23
+ filterAllowed?: string[];
19
24
  maxLimit?: number;
20
- queryAllowed?: string[];
25
+ queryAllowed?: (keyof TDoc | string)[];
26
+ };
27
+ /**
28
+ * Options when using a Mongoose model
29
+ */
30
+ type TMongooseOptions<M, TDoc, R> = TBaseOptions<TDoc, R> & {
31
+ model: M;
32
+ adapter?: never;
33
+ filter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<TDoc>;
34
+ filterCustom?: TFilterCustomConfigWithFilter<TDoc, TMongoFilterQuery<TDoc>>;
35
+ defaultSort?: TSortOptions<TDoc>;
36
+ };
37
+ /**
38
+ * Options when using a custom adapter
39
+ */
40
+ type TAdapterOptions<TDoc, R> = TBaseOptions<TDoc, R> & {
41
+ adapter: TDataKitAdapter<TDoc>;
42
+ model?: never;
43
+ filter?: never;
44
+ filterCustom?: TFilterCustomConfigWithFilter<TDoc, unknown>;
45
+ defaultSort?: never;
21
46
  };
22
- declare const dataKitServerAction: <T, R>(props: Readonly<TDataKitServerActionOptions<T, R>>) => Promise<TDataKitResult<R>>;
47
+ /**
48
+ * Server action with Mongoose model (auto-infers document type)
49
+ */
50
+ declare function dataKitServerAction<M extends Model<any>, R = unknown>(props: Readonly<TMongooseOptions<M, TExtractDocType<M>, R>>): Promise<TDataKitResult<R>>;
51
+ /**
52
+ * Server action with custom adapter
53
+ */
54
+ declare function dataKitServerAction<TDoc, R = unknown>(props: Readonly<TAdapterOptions<TDoc, R>>): Promise<TDataKitResult<R>>;
23
55
 
24
56
  /**
25
57
  * next-data-kit - Mongoose Adapter
@@ -27,7 +59,7 @@ declare const dataKitServerAction: <T, R>(props: Readonly<TDataKitServerActionOp
27
59
  * Database adapter for Mongoose/MongoDB.
28
60
  */
29
61
 
30
- declare const mongooseAdapter: <M extends TMongoModel<unknown, object>, DocType = TExtractDocType<M>>(model: M, options?: Readonly<{
62
+ declare const mongooseAdapter: <DocType = unknown>(model: TMongoModel<DocType>, options?: Readonly<{
31
63
  filter?: (filterInput?: Record<string, unknown>) => TMongoFilterQuery<DocType>;
32
64
  filterCustom?: TFilterCustomConfigWithFilter<DocType, TMongoFilterQuery<DocType>>;
33
65
  defaultSort?: TSortOptions<DocType>;
@@ -53,6 +85,14 @@ declare const adapterMemory: <T extends Record<string, unknown>>(dataset: Readon
53
85
  * next-data-kit - Server Utilities
54
86
  */
55
87
 
88
+ /**
89
+ * Check if a value is provided (not undefined, null, or empty string)
90
+ */
91
+ declare const isProvided: (value: unknown) => boolean;
92
+ /**
93
+ * Check if a key is safe (not a prototype pollution key)
94
+ */
95
+ declare const isSafeKey: (key: string) => boolean;
56
96
  /**
57
97
  * Helper to escape regex special characters in a string
58
98
  */
@@ -67,7 +107,7 @@ declare const escapeRegex: (str: string) => string;
67
107
  * }
68
108
  * ```
69
109
  */
70
- declare const createSearchFilter: <T>(fields: (keyof T | string)[]) => (value: unknown) => TMongoFilterQuery<T>;
110
+ declare const createSearchFilter: <T>(fields: (keyof T | string)[]) => ((value: unknown) => TMongoFilterQuery<T>);
71
111
 
72
112
  declare const dataKitSchemaZod: z.ZodObject<{
73
113
  page: z.ZodOptional<z.ZodNumber>;
@@ -126,4 +166,4 @@ declare const dataKitSchemaZod: z.ZodObject<{
126
166
  }>;
127
167
  type TDataKitSchemaZod = z.infer<typeof dataKitSchemaZod>;
128
168
 
129
- export { TDataKitAdapter, TDataKitInput, TDataKitResult, type TDataKitSchemaZod, type TDataKitServerActionOptions, TExtractDocType, TFilterCustomConfigWithFilter, TMongoFilterQuery, TMongoModel, TSortOptions, adapterMemory, createSearchFilter, dataKitSchemaZod, dataKitServerAction, escapeRegex, mongooseAdapter };
169
+ export { TDataKitAdapter, TDataKitInput, TDataKitResult, type TDataKitSchemaZod, type TExtractDocType, TFilterCustomConfigWithFilter, TMongoFilterQuery, TMongoModel, TSortOptions, adapterMemory, createSearchFilter, dataKitSchemaZod, dataKitServerAction, escapeRegex, isProvided, isSafeKey, mongooseAdapter };