@classytic/mongokit 3.2.0 → 3.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/README.md +470 -193
  2. package/dist/actions/index.d.mts +9 -0
  3. package/dist/actions/index.mjs +15 -0
  4. package/dist/aggregate-BAi4Do-X.mjs +767 -0
  5. package/dist/aggregate-CCHI7F51.d.mts +269 -0
  6. package/dist/ai/index.d.mts +125 -0
  7. package/dist/ai/index.mjs +203 -0
  8. package/dist/cache-keys-C8Z9B5sw.mjs +204 -0
  9. package/dist/chunk-DQk6qfdC.mjs +18 -0
  10. package/dist/create-BuO6xt0v.mjs +55 -0
  11. package/dist/custom-id.plugin-B_zIs6gE.mjs +1818 -0
  12. package/dist/custom-id.plugin-BzZI4gnE.d.mts +893 -0
  13. package/dist/index.d.mts +1012 -0
  14. package/dist/index.mjs +1906 -0
  15. package/dist/limits-DsNeCx4D.mjs +299 -0
  16. package/dist/logger-D8ily-PP.mjs +51 -0
  17. package/dist/mongooseToJsonSchema-COdDEkIJ.mjs +317 -0
  18. package/dist/{mongooseToJsonSchema-CaRF_bCN.d.ts → mongooseToJsonSchema-Wbvjfwkn.d.mts} +16 -89
  19. package/dist/pagination/PaginationEngine.d.mts +93 -0
  20. package/dist/pagination/PaginationEngine.mjs +196 -0
  21. package/dist/plugins/index.d.mts +3 -0
  22. package/dist/plugins/index.mjs +3 -0
  23. package/dist/types-D-gploPr.d.mts +1241 -0
  24. package/dist/utils/{index.d.ts → index.d.mts} +14 -21
  25. package/dist/utils/index.mjs +5 -0
  26. package/package.json +21 -21
  27. package/dist/actions/index.d.ts +0 -3
  28. package/dist/actions/index.js +0 -5
  29. package/dist/ai/index.d.ts +0 -175
  30. package/dist/ai/index.js +0 -206
  31. package/dist/chunks/chunk-2ZN65ZOP.js +0 -93
  32. package/dist/chunks/chunk-44KXLGPO.js +0 -388
  33. package/dist/chunks/chunk-DEVXDBRL.js +0 -1226
  34. package/dist/chunks/chunk-I7CWNAJB.js +0 -46
  35. package/dist/chunks/chunk-JWUAVZ3L.js +0 -8
  36. package/dist/chunks/chunk-UE2IEXZJ.js +0 -306
  37. package/dist/chunks/chunk-URLJFIR7.js +0 -22
  38. package/dist/chunks/chunk-VWKIKZYF.js +0 -737
  39. package/dist/chunks/chunk-WSFCRVEQ.js +0 -7
  40. package/dist/index-BDn5fSTE.d.ts +0 -516
  41. package/dist/index.d.ts +0 -1422
  42. package/dist/index.js +0 -1893
  43. package/dist/pagination/PaginationEngine.d.ts +0 -117
  44. package/dist/pagination/PaginationEngine.js +0 -3
  45. package/dist/plugins/index.d.ts +0 -922
  46. package/dist/plugins/index.js +0 -6
  47. package/dist/types-Jni1KgkP.d.ts +0 -780
  48. package/dist/utils/index.js +0 -5
@@ -0,0 +1,204 @@
1
+ //#region src/utils/field-selection.ts
2
+ /**
3
+ * Get allowed fields for a user based on their context
4
+ *
5
+ * @param user - User object from request.user (or null for public)
6
+ * @param preset - Field preset configuration
7
+ * @returns Array of allowed field names
8
+ *
9
+ * @example
10
+ * const fields = getFieldsForUser(request.user, {
11
+ * public: ['id', 'name', 'price'],
12
+ * authenticated: ['description', 'features'],
13
+ * admin: ['createdAt', 'internalNotes']
14
+ * });
15
+ */
16
+ function getFieldsForUser(user, preset) {
17
+ if (!preset) throw new Error("Field preset is required");
18
+ const fields = [...preset.public || []];
19
+ if (user) {
20
+ fields.push(...preset.authenticated || []);
21
+ const roles = Array.isArray(user.roles) ? user.roles : user.roles ? [user.roles] : [];
22
+ if (roles.includes("admin") || roles.includes("superadmin")) fields.push(...preset.admin || []);
23
+ }
24
+ return [...new Set(fields)];
25
+ }
26
+ /**
27
+ * Get Mongoose projection string for query .select()
28
+ *
29
+ * @param user - User object from request.user
30
+ * @param preset - Field preset configuration
31
+ * @returns Space-separated field names for Mongoose .select()
32
+ *
33
+ * @example
34
+ * const projection = getMongooseProjection(request.user, fieldPresets.gymPlans);
35
+ * const plans = await GymPlan.find({ organizationId }).select(projection).lean();
36
+ */
37
+ function getMongooseProjection(user, preset) {
38
+ return getFieldsForUser(user, preset).join(" ");
39
+ }
40
+ /**
41
+ * Filter a single object to include only allowed fields
42
+ */
43
+ function filterObject(obj, allowedFields) {
44
+ if (!obj || typeof obj !== "object" || Array.isArray(obj)) return obj;
45
+ const filtered = {};
46
+ for (const field of allowedFields) if (field in obj) filtered[field] = obj[field];
47
+ return filtered;
48
+ }
49
+ /**
50
+ * Filter response data to include only allowed fields
51
+ *
52
+ * Use this for complex responses where Mongoose projections aren't applicable:
53
+ * - Aggregation pipeline results
54
+ * - Data from multiple sources
55
+ * - Custom computed fields
56
+ *
57
+ * For simple DB queries, prefer getMongooseProjection() (10x faster)
58
+ *
59
+ * @param data - Data to filter
60
+ * @param preset - Field preset configuration
61
+ * @param user - User object from request.user
62
+ * @returns Filtered data
63
+ *
64
+ * @example
65
+ * const stats = await calculateComplexStats();
66
+ * const filtered = filterResponseData(stats, fieldPresets.dashboard, request.user);
67
+ * return reply.send(filtered);
68
+ */
69
+ function filterResponseData(data, preset, user = null) {
70
+ const allowedFields = getFieldsForUser(user, preset);
71
+ if (Array.isArray(data)) return data.map((item) => filterObject(item, allowedFields));
72
+ return filterObject(data, allowedFields);
73
+ }
74
+ /**
75
+ * Helper to create field presets (module-level)
76
+ *
77
+ * Each module should define its own field preset in its own directory.
78
+ * This keeps modules independent and self-contained.
79
+ *
80
+ * @param config - Field configuration
81
+ * @returns Field preset
82
+ *
83
+ * @example
84
+ * // In modules/gym-plan/gym-plan.fields.ts
85
+ * export const gymPlanFieldPreset = createFieldPreset({
86
+ * public: ['id', 'name', 'price'],
87
+ * authenticated: ['features', 'description'],
88
+ * admin: ['createdAt', 'updatedAt', 'internalNotes']
89
+ * });
90
+ */
91
+ function createFieldPreset(config) {
92
+ return {
93
+ public: config.public || [],
94
+ authenticated: config.authenticated || [],
95
+ admin: config.admin || []
96
+ };
97
+ }
98
+
99
+ //#endregion
100
+ //#region src/utils/cache-keys.ts
101
+ /**
102
+ * Simple hash function for query parameters
103
+ * Using djb2 algorithm - fast and good distribution
104
+ */
105
+ function hashString(str) {
106
+ let hash = 5381;
107
+ for (let i = 0; i < str.length; i++) hash = (hash << 5) + hash ^ str.charCodeAt(i);
108
+ return (hash >>> 0).toString(16);
109
+ }
110
+ /**
111
+ * Normalize and stringify an object for hashing
112
+ * Ensures deterministic key generation regardless of property order
113
+ */
114
+ function stableStringify(obj) {
115
+ if (obj === null || obj === void 0) return "";
116
+ if (typeof obj !== "object") return String(obj);
117
+ if (Array.isArray(obj)) return "[" + obj.map(stableStringify).join(",") + "]";
118
+ return "{" + Object.keys(obj).sort().map((key) => `${key}:${stableStringify(obj[key])}`).join(",") + "}";
119
+ }
120
+ /**
121
+ * Generate cache key for getById operations
122
+ *
123
+ * Format: {prefix}:id:{model}:{documentId}
124
+ *
125
+ * @example
126
+ * byIdKey('mk', 'User', '507f1f77bcf86cd799439011')
127
+ * // => 'mk:id:User:507f1f77bcf86cd799439011'
128
+ */
129
+ function byIdKey(prefix, model, id) {
130
+ return `${prefix}:id:${model}:${id}`;
131
+ }
132
+ /**
133
+ * Generate cache key for single-document queries
134
+ *
135
+ * Format: {prefix}:one:{model}:{queryHash}
136
+ *
137
+ * @example
138
+ * byQueryKey('mk', 'User', { email: 'john@example.com' })
139
+ * // => 'mk:one:User:a1b2c3d4'
140
+ */
141
+ function byQueryKey(prefix, model, query, options) {
142
+ return `${prefix}:one:${model}:${hashString(stableStringify({
143
+ q: query,
144
+ s: options?.select,
145
+ p: options?.populate
146
+ }))}`;
147
+ }
148
+ /**
149
+ * Generate cache key for paginated list queries
150
+ *
151
+ * Format: {prefix}:list:{model}:{version}:{queryHash}
152
+ *
153
+ * The version component enables efficient bulk invalidation:
154
+ * - On any mutation, bump the version
155
+ * - All list cache keys become invalid without scanning/deleting each
156
+ *
157
+ * @example
158
+ * listQueryKey('mk', 'User', 1, { filters: { status: 'active' }, page: 1, limit: 20 })
159
+ * // => 'mk:list:User:1:e5f6g7h8'
160
+ */
161
+ function listQueryKey(prefix, model, version, params) {
162
+ return `${prefix}:list:${model}:${version}:${hashString(stableStringify({
163
+ f: params.filters,
164
+ s: params.sort,
165
+ pg: params.page,
166
+ lm: params.limit,
167
+ af: params.after,
168
+ sl: params.select,
169
+ pp: params.populate
170
+ }))}`;
171
+ }
172
+ /**
173
+ * Generate cache key for collection version tag
174
+ *
175
+ * Format: {prefix}:ver:{model}
176
+ *
177
+ * Used to track mutation version for list invalidation
178
+ */
179
+ function versionKey(prefix, model) {
180
+ return `${prefix}:ver:${model}`;
181
+ }
182
+ /**
183
+ * Generate pattern for clearing all cache keys for a model
184
+ *
185
+ * Format: {prefix}:*:{model}:*
186
+ *
187
+ * @example
188
+ * modelPattern('mk', 'User')
189
+ * // => 'mk:*:User:*'
190
+ */
191
+ function modelPattern(prefix, model) {
192
+ return `${prefix}:*:${model}:*`;
193
+ }
194
+ /**
195
+ * Generate pattern for clearing all list cache keys for a model
196
+ *
197
+ * Format: {prefix}:list:{model}:*
198
+ */
199
+ function listPattern(prefix, model) {
200
+ return `${prefix}:list:${model}:*`;
201
+ }
202
+
203
+ //#endregion
204
+ export { modelPattern as a, filterResponseData as c, listQueryKey as i, getFieldsForUser as l, byQueryKey as n, versionKey as o, listPattern as r, createFieldPreset as s, byIdKey as t, getMongooseProjection as u };
@@ -0,0 +1,18 @@
1
+ //#region \0rolldown/runtime.js
2
+ var __defProp = Object.defineProperty;
3
+ var __exportAll = (all, no_symbols) => {
4
+ let target = {};
5
+ for (var name in all) {
6
+ __defProp(target, name, {
7
+ get: all[name],
8
+ enumerable: true
9
+ });
10
+ }
11
+ if (!no_symbols) {
12
+ __defProp(target, Symbol.toStringTag, { value: "Module" });
13
+ }
14
+ return target;
15
+ };
16
+
17
+ //#endregion
18
+ export { __exportAll as t };
@@ -0,0 +1,55 @@
1
+ import { t as __exportAll } from "./chunk-DQk6qfdC.mjs";
2
+
3
+ //#region src/actions/create.ts
4
+ var create_exports = /* @__PURE__ */ __exportAll({
5
+ create: () => create,
6
+ createDefault: () => createDefault,
7
+ createMany: () => createMany,
8
+ upsert: () => upsert
9
+ });
10
+ /**
11
+ * Create single document
12
+ */
13
+ async function create(Model, data, options = {}) {
14
+ const document = new Model(data);
15
+ await document.save({ session: options.session });
16
+ return document;
17
+ }
18
+ /**
19
+ * Create multiple documents
20
+ */
21
+ async function createMany(Model, dataArray, options = {}) {
22
+ return Model.insertMany(dataArray, {
23
+ session: options.session,
24
+ ordered: options.ordered !== false
25
+ });
26
+ }
27
+ /**
28
+ * Create with defaults (useful for initialization)
29
+ */
30
+ async function createDefault(Model, overrides = {}, options = {}) {
31
+ const defaults = {};
32
+ Model.schema.eachPath((path, schemaType) => {
33
+ const schemaOptions = schemaType.options;
34
+ if (schemaOptions.default !== void 0 && path !== "_id") defaults[path] = typeof schemaOptions.default === "function" ? schemaOptions.default() : schemaOptions.default;
35
+ });
36
+ return create(Model, {
37
+ ...defaults,
38
+ ...overrides
39
+ }, options);
40
+ }
41
+ /**
42
+ * Upsert (create or update)
43
+ */
44
+ async function upsert(Model, query, data, options = {}) {
45
+ return Model.findOneAndUpdate(query, { $setOnInsert: data }, {
46
+ upsert: true,
47
+ returnDocument: "after",
48
+ runValidators: true,
49
+ session: options.session,
50
+ ...options.updatePipeline !== void 0 ? { updatePipeline: options.updatePipeline } : {}
51
+ });
52
+ }
53
+
54
+ //#endregion
55
+ export { upsert as i, createMany as n, create_exports as r, create as t };