@lyxa.ai/core 1.1.67 → 1.1.69

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 (22) hide show
  1. package/dist/libraries/mongo/models/embedded/trip-leg.mode.d.ts +1 -0
  2. package/dist/libraries/mongo/models/embedded/trip-leg.mode.js +5 -0
  3. package/dist/libraries/mongo/models/embedded/trip-leg.mode.js.map +1 -1
  4. package/dist/libraries/mongo/models/message.model.d.ts +3 -2
  5. package/dist/libraries/mongo/models/message.model.js +17 -5
  6. package/dist/libraries/mongo/models/message.model.js.map +1 -1
  7. package/dist/libraries/socket/core/socket-event-registry.map.d.ts +54 -3
  8. package/dist/libraries/socket/events/chatlist-message-send.socket.event.d.ts +37 -0
  9. package/dist/libraries/socket/events/chatlist-message-send.socket.event.js +4 -0
  10. package/dist/libraries/socket/events/chatlist-message-send.socket.event.js.map +1 -1
  11. package/dist/libraries/socket/events/chatroom-message-send.socket.event.d.ts +73 -7
  12. package/dist/libraries/socket/events/chatroom-message-send.socket.event.js +8 -1
  13. package/dist/libraries/socket/events/chatroom-message-send.socket.event.js.map +1 -1
  14. package/dist/types/README.md +1 -1
  15. package/dist/types/package.json +1 -1
  16. package/dist/types/utilities/validation/filter-schema.factory.d.ts +5 -4
  17. package/dist/types/utilities/validation/filter-schema.factory.js +11 -11
  18. package/dist/types/utilities/validation/filter-schema.factory.js.map +1 -1
  19. package/dist/utilities/validation/filter-schema.factory.d.ts +5 -4
  20. package/dist/utilities/validation/filter-schema.factory.js +11 -11
  21. package/dist/utilities/validation/filter-schema.factory.js.map +1 -1
  22. package/package.json +1 -1
@@ -13,6 +13,7 @@ export declare class TripLeg {
13
13
  type?: FaqAccountType;
14
14
  rider?: Ref<Rider>;
15
15
  orders?: mongoose.Types.ObjectId[];
16
+ orderId?: string;
16
17
  user?: Ref<User>;
17
18
  shop?: Ref<Shop>;
18
19
  shopType?: ItemType;
@@ -25,6 +25,7 @@ class TripLeg {
25
25
  type;
26
26
  rider;
27
27
  orders;
28
+ orderId;
28
29
  user;
29
30
  shop;
30
31
  shopType;
@@ -73,6 +74,10 @@ __decorate([
73
74
  (0, typegoose_1.prop)({ ref: () => order_model_1.Order }),
74
75
  __metadata("design:type", Array)
75
76
  ], TripLeg.prototype, "orders", void 0);
77
+ __decorate([
78
+ (0, typegoose_1.prop)({ type: String }),
79
+ __metadata("design:type", String)
80
+ ], TripLeg.prototype, "orderId", void 0);
76
81
  __decorate([
77
82
  (0, typegoose_1.prop)({ ref: () => user_model_1.User }),
78
83
  __metadata("design:type", Object)
@@ -1 +1 @@
1
- {"version":3,"file":"trip-leg.mode.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/trip-leg.mode.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA2D;AAC3D,gDAAuC;AACvC,gDAAuC;AACvC,qDAAqF;AACrF,8CAAqC;AACrC,8CAAqC;AAGrC,MAAa,OAAO;IAEnB,IAAI,CAAU;IAGd,OAAO,CAAU;IAGjB,kBAAkB,CAAU;IAG5B,QAAQ,CAAU;IAGlB,SAAS,CAAU;IAOnB,IAAI,CAAkB;IAGtB,KAAK,CAAc;IAGnB,MAAM,CAA6B;IAGnC,IAAI,CAAa;IAGjB,IAAI,CAAa;IAMjB,QAAQ,CAAY;IAMpB,MAAM,CAAiB;IAGvB,aAAa,CAAa;IAG1B,aAAa,CAAa;IAG1B,qBAAqB,CAAc;IAGnC,QAAQ,CAAa;IAGrB,QAAQ,CAAa;IAKrB,gBAAgB,CAAc;CAC9B;AAlED,0BAkEC;AAhEA;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;qCACT;AAGd;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACN;AAGjB;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDACK;AAG5B;IADC,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yCACrB;AAGlB;IADC,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0CACpB;AAOnB;IALC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,qBAAc;QACpB,OAAO,EAAE,qBAAc,CAAC,KAAK;KAC7B,CAAC;;qCACoB;AAGtB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAK,EAAE,CAAC;;sCACR;AAGnB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAK,EAAE,CAAC;;uCACQ;AAGnC;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;qCACT;AAGjB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;qCACT;AAMjB;IAJC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,eAAQ;KACd,CAAC;;yCACkB;AAMpB;IAJC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,oBAAa;KACnB,CAAC;;uCACqB;AAGvB;IADC,IAAA,gBAAI,GAAE;;8CACmB;AAG1B;IADC,IAAA,gBAAI,GAAE;;8CACmB;AAG1B;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;;sDACQ;AAGnC;IADC,IAAA,gBAAI,GAAE;;yCACc;AAGrB;IADC,IAAA,gBAAI,GAAE;;yCACc;AAKrB;IAHC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;KAChB,CAAC;;iDAC4B","sourcesContent":["import { Ref, prop, mongoose } from '@typegoose/typegoose';\nimport { Order } from '../order.model';\nimport { Rider } from '../rider.model';\nimport { FaqAccountType, ItemType, TripLegStatus } from '../../../../utilities/enum';\nimport { User } from '../user.model';\nimport { Shop } from '../shop.model';\nimport { IDistance, IDuration } from '../../../map/interfaces/IMapService';\n\nexport class TripLeg {\n\t@prop({ type: String })\n\tname?: string;\n\n\t@prop({ type: String })\n\taddress?: string;\n\n\t@prop({ type: String })\n\taddressDescription?: string;\n\n\t@prop({ required: true, type: Number })\n\tlatitude?: number;\n\n\t@prop({ required: true, type: Number })\n\tlongitude?: number;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: FaqAccountType,\n\t\tdefault: FaqAccountType.RIDER,\n\t})\n\ttype?: FaqAccountType;\n\n\t@prop({ ref: () => Rider })\n\trider?: Ref<Rider>;\n\n\t@prop({ ref: () => Order })\n\torders?: mongoose.Types.ObjectId[];\n\n\t@prop({ ref: () => User })\n\tuser?: Ref<User>;\n\n\t@prop({ ref: () => Shop })\n\tshop?: Ref<Shop>;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: ItemType,\n\t})\n\tshopType?: ItemType;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: TripLegStatus,\n\t})\n\tstatus?: TripLegStatus;\n\n\t@prop()\n\ttotalDistance?: IDistance;\n\n\t@prop()\n\ttotalDuration?: IDuration;\n\n\t@prop({ type: [[Number]] })\n\ttotalOverviewPolyline?: number[][];\n\n\t@prop()\n\tdistance?: IDistance;\n\n\t@prop()\n\tduration?: IDuration;\n\n\t@prop({\n\t\ttype: [[Number]],\n\t})\n\toverviewPolyline?: number[][];\n}\n"]}
1
+ {"version":3,"file":"trip-leg.mode.js","sourceRoot":"/","sources":["libraries/mongo/models/embedded/trip-leg.mode.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAA2D;AAC3D,gDAAuC;AACvC,gDAAuC;AACvC,qDAAqF;AACrF,8CAAqC;AACrC,8CAAqC;AAGrC,MAAa,OAAO;IAEnB,IAAI,CAAU;IAGd,OAAO,CAAU;IAGjB,kBAAkB,CAAU;IAG5B,QAAQ,CAAU;IAGlB,SAAS,CAAU;IAOnB,IAAI,CAAkB;IAGtB,KAAK,CAAc;IAGnB,MAAM,CAA6B;IAGnC,OAAO,CAAU;IAGjB,IAAI,CAAa;IAGjB,IAAI,CAAa;IAMjB,QAAQ,CAAY;IAMpB,MAAM,CAAiB;IAGvB,aAAa,CAAa;IAG1B,aAAa,CAAa;IAG1B,qBAAqB,CAAc;IAGnC,QAAQ,CAAa;IAGrB,QAAQ,CAAa;IAKrB,gBAAgB,CAAc;CAC9B;AArED,0BAqEC;AAnEA;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;qCACT;AAGd;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACN;AAGjB;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;mDACK;AAG5B;IADC,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;yCACrB;AAGlB;IADC,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;0CACpB;AAOnB;IALC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,qBAAc;QACpB,OAAO,EAAE,qBAAc,CAAC,KAAK;KAC7B,CAAC;;qCACoB;AAGtB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAK,EAAE,CAAC;;sCACR;AAGnB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,mBAAK,EAAE,CAAC;;uCACQ;AAGnC;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACN;AAGjB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;qCACT;AAGjB;IADC,IAAA,gBAAI,EAAC,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,iBAAI,EAAE,CAAC;;qCACT;AAMjB;IAJC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,eAAQ;KACd,CAAC;;yCACkB;AAMpB;IAJC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,oBAAa;KACnB,CAAC;;uCACqB;AAGvB;IADC,IAAA,gBAAI,GAAE;;8CACmB;AAG1B;IADC,IAAA,gBAAI,GAAE;;8CACmB;AAG1B;IADC,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;;sDACQ;AAGnC;IADC,IAAA,gBAAI,GAAE;;yCACc;AAGrB;IADC,IAAA,gBAAI,GAAE;;yCACc;AAKrB;IAHC,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;KAChB,CAAC;;iDAC4B","sourcesContent":["import { Ref, prop, mongoose } from '@typegoose/typegoose';\nimport { Order } from '../order.model';\nimport { Rider } from '../rider.model';\nimport { FaqAccountType, ItemType, TripLegStatus } from '../../../../utilities/enum';\nimport { User } from '../user.model';\nimport { Shop } from '../shop.model';\nimport { IDistance, IDuration } from '../../../map/interfaces/IMapService';\n\nexport class TripLeg {\n\t@prop({ type: String })\n\tname?: string;\n\n\t@prop({ type: String })\n\taddress?: string;\n\n\t@prop({ type: String })\n\taddressDescription?: string;\n\n\t@prop({ required: true, type: Number })\n\tlatitude?: number;\n\n\t@prop({ required: true, type: Number })\n\tlongitude?: number;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: FaqAccountType,\n\t\tdefault: FaqAccountType.RIDER,\n\t})\n\ttype?: FaqAccountType;\n\n\t@prop({ ref: () => Rider })\n\trider?: Ref<Rider>;\n\n\t@prop({ ref: () => Order })\n\torders?: mongoose.Types.ObjectId[];\n\n\t@prop({ type: String })\n\torderId?: string;\n\n\t@prop({ ref: () => User })\n\tuser?: Ref<User>;\n\n\t@prop({ ref: () => Shop })\n\tshop?: Ref<Shop>;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: ItemType,\n\t})\n\tshopType?: ItemType;\n\n\t@prop({\n\t\ttype: String,\n\t\tenum: TripLegStatus,\n\t})\n\tstatus?: TripLegStatus;\n\n\t@prop()\n\ttotalDistance?: IDistance;\n\n\t@prop()\n\ttotalDuration?: IDuration;\n\n\t@prop({ type: [[Number]] })\n\ttotalOverviewPolyline?: number[][];\n\n\t@prop()\n\tdistance?: IDistance;\n\n\t@prop()\n\tduration?: IDuration;\n\n\t@prop({\n\t\ttype: [[Number]],\n\t})\n\toverviewPolyline?: number[][];\n}\n"]}
@@ -6,9 +6,10 @@ import { Shop } from './shop.model';
6
6
  import { MediaType, UserRef } from '../../../utilities/enum';
7
7
  import { Rider } from './rider.model';
8
8
  import { Chatroom } from './chat-room.model';
9
- export declare class Media extends TimeStamps {
10
- url: string;
9
+ export declare class Media {
10
+ mediaUrl: string;
11
11
  mediaType: MediaType;
12
+ mimeType: string;
12
13
  thumbnailUrl?: string;
13
14
  name?: string;
14
15
  }
@@ -14,9 +14,10 @@ const typegoose_1 = require("@typegoose/typegoose");
14
14
  const defaultClasses_1 = require("@typegoose/typegoose/lib/defaultClasses");
15
15
  const enum_1 = require("../../../utilities/enum");
16
16
  const chat_room_model_1 = require("./chat-room.model");
17
- class Media extends defaultClasses_1.TimeStamps {
18
- url;
17
+ class Media {
18
+ mediaUrl;
19
19
  mediaType;
20
+ mimeType;
20
21
  thumbnailUrl;
21
22
  name;
22
23
  }
@@ -24,11 +25,15 @@ exports.Media = Media;
24
25
  __decorate([
25
26
  (0, typegoose_1.prop)({ required: true }),
26
27
  __metadata("design:type", String)
27
- ], Media.prototype, "url", void 0);
28
+ ], Media.prototype, "mediaUrl", void 0);
28
29
  __decorate([
29
30
  (0, typegoose_1.prop)({ required: true, type: String, enum: enum_1.MediaType }),
30
31
  __metadata("design:type", String)
31
32
  ], Media.prototype, "mediaType", void 0);
33
+ __decorate([
34
+ (0, typegoose_1.prop)({ required: true }),
35
+ __metadata("design:type", String)
36
+ ], Media.prototype, "mimeType", void 0);
32
37
  __decorate([
33
38
  (0, typegoose_1.prop)(),
34
39
  __metadata("design:type", String)
@@ -52,7 +57,7 @@ __decorate([
52
57
  __metadata("design:type", Object)
53
58
  ], Message.prototype, "chatroom", void 0);
54
59
  __decorate([
55
- (0, typegoose_1.prop)({ required: true, type: String }),
60
+ (0, typegoose_1.prop)({ type: String }),
56
61
  __metadata("design:type", String)
57
62
  ], Message.prototype, "content", void 0);
58
63
  __decorate([
@@ -60,7 +65,14 @@ __decorate([
60
65
  __metadata("design:type", String)
61
66
  ], Message.prototype, "senderType", void 0);
62
67
  __decorate([
63
- (0, typegoose_1.prop)({ type: () => [Media], default: [] }),
68
+ (0, typegoose_1.prop)({
69
+ type: () => [Media],
70
+ default: [],
71
+ validate: {
72
+ validator: (v) => v.length <= 4,
73
+ message: 'Maximum 4 media items per message',
74
+ },
75
+ }),
64
76
  __metadata("design:type", Array)
65
77
  ], Message.prototype, "media", void 0);
66
78
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"message.model.js","sourceRoot":"/","sources":["libraries/mongo/models/message.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAsE;AACtE,4EAAqE;AAIrE,kDAA6D;AAE7D,uDAA6C;AAE7C,MAAa,KAAM,SAAQ,2BAAU;IAE7B,GAAG,CAAU;IAGb,SAAS,CAAY;IAGrB,YAAY,CAAU;IAGtB,IAAI,CAAU;CACrB;AAZD,sBAYC;AAVO;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;kCACL;AAGb;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAS,EAAE,CAAC;;wCAC5B;AAGrB;IADN,IAAA,gBAAI,GAAE;;2CACsB;AAGtB;IADN,IAAA,gBAAI,GAAE;;mCACc;AAWf,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,2BAAU;IAE/B,QAAQ,CAAiB;IAGzB,OAAO,CAAU;IAGjB,UAAU,CAAW;IAGrB,KAAK,CAAW;IAGhB,MAAM,CAAoC;IAG1C,WAAW,CAAW;IAGtB,WAAW,CAAQ;CAC1B,CAAA;AArBY,0BAAO;AAEZ;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,0BAAQ,EAAE,CAAC;;yCACd;AAGzB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACf;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAO,EAAE,CAAC;;2CAC1B;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC;;sCACpB;AAGhB;IADN,IAAA,gBAAI,EAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;;uCACiB;AAG1C;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;4CACX;AAGtB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;8BACA,IAAI;4CAAC;kBApBd,OAAO;IARnB,IAAA,wBAAY,EAAC;QACb,aAAa,EAAE;YACd,UAAU,EAAE,UAAU;SACtB;KACD,CAAC;IACD,IAAA,iBAAK,EAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;IACrC,IAAA,iBAAK,EAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IACnC,IAAA,iBAAK,EAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;GACrB,OAAO,CAqBnB","sourcesContent":["import { index, modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { User } from './user.model';\nimport { Admin } from './admin.model';\nimport { Shop } from './shop.model';\nimport { MediaType, UserRef } from '../../../utilities/enum';\nimport { Rider } from './rider.model';\nimport { Chatroom } from './chat-room.model';\n\nexport class Media extends TimeStamps {\n\t@prop({ required: true })\n\tpublic url!: string;\n\n\t@prop({ required: true, type: String, enum: MediaType })\n\tpublic mediaType: MediaType;\n\n\t@prop()\n\tpublic thumbnailUrl?: string;\n\n\t@prop()\n\tpublic name?: string;\n}\n\n@modelOptions({\n\tschemaOptions: {\n\t\tcollection: 'messages',\n\t},\n})\n@index({ chatroom: 1, createdAt: -1 })\n@index({ sender: 1, senderType: 1 })\n@index({ isRead: 1, chatroom: 1 })\nexport class Message extends TimeStamps {\n\t@prop({ required: true, ref: () => Chatroom })\n\tpublic chatroom!: Ref<Chatroom>;\n\n\t@prop({ required: true, type: String })\n\tpublic content?: string;\n\n\t@prop({ required: true, type: String, enum: UserRef })\n\tpublic senderType!: UserRef;\n\n\t@prop({ type: () => [Media], default: [] })\n\tpublic media!: Media[];\n\n\t@prop({ refPath: 'senderType' })\n\tpublic sender!: Ref<User | Admin | Shop | Rider>;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isDelivered?: boolean;\n\n\t@prop({ type: Date })\n\tpublic deliveredAt?: Date;\n}\n"]}
1
+ {"version":3,"file":"message.model.js","sourceRoot":"/","sources":["libraries/mongo/models/message.model.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,oDAAsE;AACtE,4EAAqE;AAIrE,kDAA6D;AAE7D,uDAA6C;AAE7C,MAAa,KAAK;IAEV,QAAQ,CAAU;IAGlB,SAAS,CAAY;IAGrB,QAAQ,CAAS;IAGjB,YAAY,CAAU;IAGtB,IAAI,CAAU;CACrB;AAfD,sBAeC;AAbO;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;uCACA;AAGlB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAS,EAAE,CAAC;;wCAC5B;AAGrB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;uCACD;AAGjB;IADN,IAAA,gBAAI,GAAE;;2CACsB;AAGtB;IADN,IAAA,gBAAI,GAAE;;mCACc;AAWf,IAAM,OAAO,GAAb,MAAM,OAAQ,SAAQ,2BAAU;IAE/B,QAAQ,CAAiB;IAGzB,OAAO,CAAU;IAGjB,UAAU,CAAW;IAUrB,KAAK,CAAW;IAGhB,MAAM,CAAoC;IAG1C,WAAW,CAAW;IAGtB,WAAW,CAAQ;CAC1B,CAAA;AA5BY,0BAAO;AAEZ;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,0BAAQ,EAAE,CAAC;;yCACd;AAGzB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;;wCACC;AAGjB;IADN,IAAA,gBAAI,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,cAAO,EAAE,CAAC;;2CAC1B;AAUrB;IARN,IAAA,gBAAI,EAAC;QACL,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC;QACnB,OAAO,EAAE,EAAE;QACX,QAAQ,EAAE;YACT,SAAS,EAAE,CAAC,CAAU,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC;YACxC,OAAO,EAAE,mCAAmC;SAC5C;KACD,CAAC;;sCACqB;AAGhB;IADN,IAAA,gBAAI,EAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;;uCACiB;AAG1C;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;;4CACX;AAGtB;IADN,IAAA,gBAAI,EAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;8BACA,IAAI;4CAAC;kBA3Bd,OAAO;IARnB,IAAA,wBAAY,EAAC;QACb,aAAa,EAAE;YACd,UAAU,EAAE,UAAU;SACtB;KACD,CAAC;IACD,IAAA,iBAAK,EAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,CAAC;IACrC,IAAA,iBAAK,EAAC,EAAE,MAAM,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,CAAC;IACnC,IAAA,iBAAK,EAAC,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,CAAC;GACrB,OAAO,CA4BnB","sourcesContent":["import { index, modelOptions, prop, Ref } from '@typegoose/typegoose';\nimport { TimeStamps } from '@typegoose/typegoose/lib/defaultClasses';\nimport { User } from './user.model';\nimport { Admin } from './admin.model';\nimport { Shop } from './shop.model';\nimport { MediaType, UserRef } from '../../../utilities/enum';\nimport { Rider } from './rider.model';\nimport { Chatroom } from './chat-room.model';\n\nexport class Media {\n\t@prop({ required: true })\n\tpublic mediaUrl!: string;\n\n\t@prop({ required: true, type: String, enum: MediaType })\n\tpublic mediaType: MediaType;\n\n\t@prop({ required: true })\n\tpublic mimeType: string;\n\n\t@prop()\n\tpublic thumbnailUrl?: string;\n\n\t@prop()\n\tpublic name?: string;\n}\n\n@modelOptions({\n\tschemaOptions: {\n\t\tcollection: 'messages',\n\t},\n})\n@index({ chatroom: 1, createdAt: -1 })\n@index({ sender: 1, senderType: 1 })\n@index({ isRead: 1, chatroom: 1 })\nexport class Message extends TimeStamps {\n\t@prop({ required: true, ref: () => Chatroom })\n\tpublic chatroom!: Ref<Chatroom>;\n\n\t@prop({ type: String })\n\tpublic content?: string;\n\n\t@prop({ required: true, type: String, enum: UserRef })\n\tpublic senderType!: UserRef;\n\n\t@prop({\n\t\ttype: () => [Media],\n\t\tdefault: [],\n\t\tvalidate: {\n\t\t\tvalidator: (v: Media[]) => v.length <= 4,\n\t\t\tmessage: 'Maximum 4 media items per message',\n\t\t},\n\t})\n\tpublic media!: Media[];\n\n\t@prop({ refPath: 'senderType' })\n\tpublic sender!: Ref<User | Admin | Shop | Rider>;\n\n\t@prop({ type: Boolean, default: false })\n\tpublic isDelivered?: boolean;\n\n\t@prop({ type: Date })\n\tpublic deliveredAt?: Date;\n}\n"]}
@@ -28,11 +28,36 @@ export declare const REGISTRY: {
28
28
  type: import("../../../utilities/enum").UserRef;
29
29
  id: import("mongoose").Types.ObjectId;
30
30
  }>;
31
- content: import("zod").ZodString | import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>;
31
+ content: import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodOptional<import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>>;
32
+ media: import("zod").ZodArray<import("zod").ZodObject<{
33
+ mimeType: import("zod").ZodString | import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>;
34
+ mediaType: import("zod").ZodNativeEnum<typeof import("../../../utilities/enum").MediaType>;
35
+ mediaUrl: import("zod").ZodString | import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>;
36
+ thumbnailUrl: import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodOptional<import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>>;
37
+ name: import("zod").ZodOptional<import("zod").ZodString> | import("zod").ZodOptional<import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>>;
38
+ }, "strip", import("zod").ZodTypeAny, {
39
+ mediaType: import("../../../utilities/enum").MediaType;
40
+ mediaUrl: string;
41
+ mimeType: string;
42
+ name?: string | undefined;
43
+ thumbnailUrl?: string | undefined;
44
+ }, {
45
+ mediaType: import("../../../utilities/enum").MediaType;
46
+ mediaUrl: string;
47
+ mimeType: string;
48
+ name?: string | undefined;
49
+ thumbnailUrl?: string | undefined;
50
+ }>, "many">;
32
51
  chatroomId: import("zod").ZodOptional<import("zod").ZodEffects<import("zod").ZodType<import("mongoose").Types.ObjectId, import("zod").ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>>;
33
52
  createdAt: import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodDate, Date, Date>, Date, Date>;
34
53
  }, "strip", import("zod").ZodTypeAny, {
35
- content: string;
54
+ media: {
55
+ mediaType: import("../../../utilities/enum").MediaType;
56
+ mediaUrl: string;
57
+ mimeType: string;
58
+ name?: string | undefined;
59
+ thumbnailUrl?: string | undefined;
60
+ }[];
36
61
  _id: import("mongoose").Types.ObjectId;
37
62
  createdAt: Date;
38
63
  sender: {
@@ -41,9 +66,16 @@ export declare const REGISTRY: {
41
66
  };
42
67
  senderType: import("../../../utilities/enum").UserRef;
43
68
  senderId: import("mongoose").Types.ObjectId;
69
+ content?: string | undefined;
44
70
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
45
71
  }, {
46
- content: string;
72
+ media: {
73
+ mediaType: import("../../../utilities/enum").MediaType;
74
+ mediaUrl: string;
75
+ mimeType: string;
76
+ name?: string | undefined;
77
+ thumbnailUrl?: string | undefined;
78
+ }[];
47
79
  _id: import("mongoose").Types.ObjectId;
48
80
  createdAt: Date;
49
81
  sender: {
@@ -52,6 +84,7 @@ export declare const REGISTRY: {
52
84
  };
53
85
  senderType: import("../../../utilities/enum").UserRef;
54
86
  senderId: import("mongoose").Types.ObjectId;
87
+ content?: string | undefined;
55
88
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
56
89
  }>;
57
90
  };
@@ -73,8 +106,22 @@ export declare const REGISTRY: {
73
106
  content: string;
74
107
  createdAt: Date;
75
108
  }>;
109
+ media: import("zod").ZodArray<import("zod").ZodObject<{
110
+ mimeType: import("zod").ZodString | import("zod").ZodEffects<import("zod").ZodEffects<import("zod").ZodString, string, string>, string, string>;
111
+ mediaType: import("zod").ZodNativeEnum<typeof import("../../../utilities/enum").MediaType>;
112
+ }, "strip", import("zod").ZodTypeAny, {
113
+ mediaType: import("../../../utilities/enum").MediaType;
114
+ mimeType: string;
115
+ }, {
116
+ mediaType: import("../../../utilities/enum").MediaType;
117
+ mimeType: string;
118
+ }>, "many">;
76
119
  unreadCount: import("zod").ZodNumber;
77
120
  }, "strip", import("zod").ZodTypeAny, {
121
+ media: {
122
+ mediaType: import("../../../utilities/enum").MediaType;
123
+ mimeType: string;
124
+ }[];
78
125
  lastMessage: {
79
126
  content: string;
80
127
  createdAt: Date;
@@ -82,6 +129,10 @@ export declare const REGISTRY: {
82
129
  unreadCount: number;
83
130
  chatroomId: import("mongoose").Types.ObjectId;
84
131
  }, {
132
+ media: {
133
+ mediaType: import("../../../utilities/enum").MediaType;
134
+ mimeType: string;
135
+ }[];
85
136
  lastMessage: {
86
137
  content: string;
87
138
  createdAt: Date;
@@ -1,4 +1,5 @@
1
1
  import z from 'zod';
2
+ import { MediaType } from '../../../utilities/enum';
2
3
  import { DTO } from '../../../utilities/validation';
3
4
  import { BaseSocketEvent } from '../BaseSocketEvent';
4
5
  export declare const ChatlistMessageSendSocketInputSchema: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
@@ -14,8 +15,22 @@ export declare const ChatlistMessageSendSocketOutputSchema: z.ZodObject<{
14
15
  content: string;
15
16
  createdAt: Date;
16
17
  }>;
18
+ media: z.ZodArray<z.ZodObject<{
19
+ mimeType: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
20
+ mediaType: z.ZodNativeEnum<typeof MediaType>;
21
+ }, "strip", z.ZodTypeAny, {
22
+ mediaType: MediaType;
23
+ mimeType: string;
24
+ }, {
25
+ mediaType: MediaType;
26
+ mimeType: string;
27
+ }>, "many">;
17
28
  unreadCount: z.ZodNumber;
18
29
  }, "strip", z.ZodTypeAny, {
30
+ media: {
31
+ mediaType: MediaType;
32
+ mimeType: string;
33
+ }[];
19
34
  lastMessage: {
20
35
  content: string;
21
36
  createdAt: Date;
@@ -23,6 +38,10 @@ export declare const ChatlistMessageSendSocketOutputSchema: z.ZodObject<{
23
38
  unreadCount: number;
24
39
  chatroomId: import("mongoose").Types.ObjectId;
25
40
  }, {
41
+ media: {
42
+ mediaType: MediaType;
43
+ mimeType: string;
44
+ }[];
26
45
  lastMessage: {
27
46
  content: string;
28
47
  createdAt: Date;
@@ -46,8 +65,22 @@ export declare class ChatlistMessageSendSocketEvent extends BaseSocketEvent<type
46
65
  content: string;
47
66
  createdAt: Date;
48
67
  }>;
68
+ media: z.ZodArray<z.ZodObject<{
69
+ mimeType: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
70
+ mediaType: z.ZodNativeEnum<typeof MediaType>;
71
+ }, "strip", z.ZodTypeAny, {
72
+ mediaType: MediaType;
73
+ mimeType: string;
74
+ }, {
75
+ mediaType: MediaType;
76
+ mimeType: string;
77
+ }>, "many">;
49
78
  unreadCount: z.ZodNumber;
50
79
  }, "strip", z.ZodTypeAny, {
80
+ media: {
81
+ mediaType: MediaType;
82
+ mimeType: string;
83
+ }[];
51
84
  lastMessage: {
52
85
  content: string;
53
86
  createdAt: Date;
@@ -55,6 +88,10 @@ export declare class ChatlistMessageSendSocketEvent extends BaseSocketEvent<type
55
88
  unreadCount: number;
56
89
  chatroomId: import("mongoose").Types.ObjectId;
57
90
  }, {
91
+ media: {
92
+ mediaType: MediaType;
93
+ mimeType: string;
94
+ }[];
58
95
  lastMessage: {
59
96
  content: string;
60
97
  createdAt: Date;
@@ -15,6 +15,10 @@ exports.ChatlistMessageSendSocketOutputSchema = zod_1.default.object({
15
15
  content: validation_1.ZodValidation.string(),
16
16
  createdAt: validation_1.ZodValidation.coerce.date(),
17
17
  }),
18
+ media: zod_1.default.array(zod_1.default.object({
19
+ mimeType: validation_1.ZodValidation.string('mimeType'),
20
+ mediaType: validation_1.ZodValidation.enumType(enum_1.MediaType, 'mediaType'),
21
+ })),
18
22
  unreadCount: validation_1.ZodValidation.number(),
19
23
  });
20
24
  class ChatlistMessageSendSocketEvent extends BaseSocketEvent_1.BaseSocketEvent {
@@ -1 +1 @@
1
- {"version":3,"file":"chatlist-message-send.socket.event.js","sourceRoot":"/","sources":["libraries/socket/events/chatlist-message-send.socket.event.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AACpB,kDAAqF;AACrF,8DAAmE;AACnE,wDAAqD;AAExC,QAAA,oCAAoC,GAAG,aAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACpD,QAAA,qCAAqC,GAAG,aAAC,CAAC,MAAM,CAAC;IAC7D,UAAU,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,EAAE;IAC3C,WAAW,EAAE,aAAC,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,0BAAa,CAAC,MAAM,EAAE;QAC/B,SAAS,EAAE,0BAAa,CAAC,MAAM,CAAC,IAAI,EAAE;KACtC,CAAC;IACF,WAAW,EAAE,0BAAa,CAAC,MAAM,EAAE;CACnC,CAAC,CAAC;AAIH,MAAa,8BAA+B,SAAQ,iCAGnD;IACA,MAAM,CAAU,OAAO,GAAG;QACzB,KAAK,EAAE,4CAAoC;QAC3C,MAAM,EAAE,6CAAqC;KAC7C,CAAC;IAEF,YAAY,OAA2C;QACtD,KAAK,CAAC,sBAAe,CAAC,yBAAyB,EAAE,8BAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnG,CAAC;;AAXF,wEAYC","sourcesContent":["import z from 'zod';\nimport { PushNotificationEventType, SocketEventType } from '../../../utilities/enum';\nimport { DTO, ZodValidation } from '../../../utilities/validation';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\n\nexport const ChatlistMessageSendSocketInputSchema = z.object({});\nexport const ChatlistMessageSendSocketOutputSchema = z.object({\n\tchatroomId: ZodValidation.coerce.objectId(),\n\tlastMessage: z.object({\n\t\tcontent: ZodValidation.string(),\n\t\tcreatedAt: ZodValidation.coerce.date(),\n\t}),\n\tunreadCount: ZodValidation.number(),\n});\n\nexport type ChatlistMessageSendSocketOutputDTO = DTO<typeof ChatlistMessageSendSocketOutputSchema>;\n\nexport class ChatlistMessageSendSocketEvent extends BaseSocketEvent<\n\ttypeof ChatlistMessageSendSocketInputSchema,\n\ttypeof ChatlistMessageSendSocketOutputSchema\n> {\n\tstatic readonly schemas = {\n\t\tinput: ChatlistMessageSendSocketInputSchema,\n\t\toutput: ChatlistMessageSendSocketOutputSchema,\n\t};\n\n\tconstructor(payload: ChatlistMessageSendSocketOutputDTO) {\n\t\tsuper(SocketEventType.CHATLIST_MESSAGE_RECEIVED, ChatlistMessageSendSocketEvent.schemas, payload);\n\t}\n}\n"]}
1
+ {"version":3,"file":"chatlist-message-send.socket.event.js","sourceRoot":"/","sources":["libraries/socket/events/chatlist-message-send.socket.event.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AACpB,kDAAqE;AACrE,8DAAmE;AACnE,wDAAqD;AAExC,QAAA,oCAAoC,GAAG,aAAC,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;AACpD,QAAA,qCAAqC,GAAG,aAAC,CAAC,MAAM,CAAC;IAC7D,UAAU,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,EAAE;IAC3C,WAAW,EAAE,aAAC,CAAC,MAAM,CAAC;QACrB,OAAO,EAAE,0BAAa,CAAC,MAAM,EAAE;QAC/B,SAAS,EAAE,0BAAa,CAAC,MAAM,CAAC,IAAI,EAAE;KACtC,CAAC;IACF,KAAK,EAAE,aAAC,CAAC,KAAK,CACb,aAAC,CAAC,MAAM,CAAC;QACR,QAAQ,EAAE,0BAAa,CAAC,MAAM,CAAC,UAAU,CAAC;QAC1C,SAAS,EAAE,0BAAa,CAAC,QAAQ,CAAC,gBAAS,EAAE,WAAW,CAAC;KACzD,CAAC,CACF;IACD,WAAW,EAAE,0BAAa,CAAC,MAAM,EAAE;CACnC,CAAC,CAAC;AAIH,MAAa,8BAA+B,SAAQ,iCAGnD;IACA,MAAM,CAAU,OAAO,GAAG;QACzB,KAAK,EAAE,4CAAoC;QAC3C,MAAM,EAAE,6CAAqC;KAC7C,CAAC;IAEF,YAAY,OAA2C;QACtD,KAAK,CAAC,sBAAe,CAAC,yBAAyB,EAAE,8BAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACnG,CAAC;;AAXF,wEAYC","sourcesContent":["import z from 'zod';\nimport { MediaType, SocketEventType } from '../../../utilities/enum';\nimport { DTO, ZodValidation } from '../../../utilities/validation';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\n\nexport const ChatlistMessageSendSocketInputSchema = z.object({});\nexport const ChatlistMessageSendSocketOutputSchema = z.object({\n\tchatroomId: ZodValidation.coerce.objectId(),\n\tlastMessage: z.object({\n\t\tcontent: ZodValidation.string(),\n\t\tcreatedAt: ZodValidation.coerce.date(),\n\t}),\n\tmedia: z.array(\n\t\tz.object({\n\t\t\tmimeType: ZodValidation.string('mimeType'),\n\t\t\tmediaType: ZodValidation.enumType(MediaType, 'mediaType'),\n\t\t})\n\t),\n\tunreadCount: ZodValidation.number(),\n});\n\nexport type ChatlistMessageSendSocketOutputDTO = DTO<typeof ChatlistMessageSendSocketOutputSchema>;\n\nexport class ChatlistMessageSendSocketEvent extends BaseSocketEvent<\n\ttypeof ChatlistMessageSendSocketInputSchema,\n\ttypeof ChatlistMessageSendSocketOutputSchema\n> {\n\tstatic readonly schemas = {\n\t\tinput: ChatlistMessageSendSocketInputSchema,\n\t\toutput: ChatlistMessageSendSocketOutputSchema,\n\t};\n\n\tconstructor(payload: ChatlistMessageSendSocketOutputDTO) {\n\t\tsuper(SocketEventType.CHATLIST_MESSAGE_RECEIVED, ChatlistMessageSendSocketEvent.schemas, payload);\n\t}\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import z from 'zod';
2
- import { UserRef } from '../../../utilities/enum';
2
+ import { MediaType, UserRef } from '../../../utilities/enum';
3
3
  import { DTO } from '../../../utilities/validation';
4
4
  import { BaseSocketEvent } from '../BaseSocketEvent';
5
5
  import { NotificationSocketEvent } from './notification.socket.event';
@@ -24,11 +24,36 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
24
24
  type: UserRef;
25
25
  id: import("mongoose").Types.ObjectId;
26
26
  }>;
27
- content: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
27
+ content: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
28
+ media: z.ZodArray<z.ZodObject<{
29
+ mimeType: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
30
+ mediaType: z.ZodNativeEnum<typeof MediaType>;
31
+ mediaUrl: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
32
+ thumbnailUrl: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
33
+ name: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
34
+ }, "strip", z.ZodTypeAny, {
35
+ mediaType: MediaType;
36
+ mediaUrl: string;
37
+ mimeType: string;
38
+ name?: string | undefined;
39
+ thumbnailUrl?: string | undefined;
40
+ }, {
41
+ mediaType: MediaType;
42
+ mediaUrl: string;
43
+ mimeType: string;
44
+ name?: string | undefined;
45
+ thumbnailUrl?: string | undefined;
46
+ }>, "many">;
28
47
  chatroomId: z.ZodOptional<z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>>;
29
48
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
30
49
  }, "strip", z.ZodTypeAny, {
31
- content: string;
50
+ media: {
51
+ mediaType: MediaType;
52
+ mediaUrl: string;
53
+ mimeType: string;
54
+ name?: string | undefined;
55
+ thumbnailUrl?: string | undefined;
56
+ }[];
32
57
  _id: import("mongoose").Types.ObjectId;
33
58
  createdAt: Date;
34
59
  sender: {
@@ -37,9 +62,16 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
37
62
  };
38
63
  senderType: UserRef;
39
64
  senderId: import("mongoose").Types.ObjectId;
65
+ content?: string | undefined;
40
66
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
41
67
  }, {
42
- content: string;
68
+ media: {
69
+ mediaType: MediaType;
70
+ mediaUrl: string;
71
+ mimeType: string;
72
+ name?: string | undefined;
73
+ thumbnailUrl?: string | undefined;
74
+ }[];
43
75
  _id: import("mongoose").Types.ObjectId;
44
76
  createdAt: Date;
45
77
  sender: {
@@ -48,6 +80,7 @@ export declare const ChatroomMessageSendOutputSchema: z.ZodObject<{
48
80
  };
49
81
  senderType: UserRef;
50
82
  senderId: import("mongoose").Types.ObjectId;
83
+ content?: string | undefined;
51
84
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
52
85
  }>;
53
86
  export type ChatroomMessageSendSocketOutputDTO = DTO<typeof ChatroomMessageSendOutputSchema>;
@@ -75,11 +108,36 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
75
108
  type: UserRef;
76
109
  id: import("mongoose").Types.ObjectId;
77
110
  }>;
78
- content: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
111
+ content: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
112
+ media: z.ZodArray<z.ZodObject<{
113
+ mimeType: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
114
+ mediaType: z.ZodNativeEnum<typeof MediaType>;
115
+ mediaUrl: z.ZodString | z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>;
116
+ thumbnailUrl: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
117
+ name: z.ZodOptional<z.ZodString> | z.ZodOptional<z.ZodEffects<z.ZodEffects<z.ZodString, string, string>, string, string>>;
118
+ }, "strip", z.ZodTypeAny, {
119
+ mediaType: MediaType;
120
+ mediaUrl: string;
121
+ mimeType: string;
122
+ name?: string | undefined;
123
+ thumbnailUrl?: string | undefined;
124
+ }, {
125
+ mediaType: MediaType;
126
+ mediaUrl: string;
127
+ mimeType: string;
128
+ name?: string | undefined;
129
+ thumbnailUrl?: string | undefined;
130
+ }>, "many">;
79
131
  chatroomId: z.ZodOptional<z.ZodEffects<z.ZodType<import("mongoose").Types.ObjectId, z.ZodTypeDef, import("mongoose").Types.ObjectId>, import("mongoose").Types.ObjectId, import("mongoose").Types.ObjectId>>;
80
132
  createdAt: z.ZodEffects<z.ZodEffects<z.ZodDate, Date, Date>, Date, Date>;
81
133
  }, "strip", z.ZodTypeAny, {
82
- content: string;
134
+ media: {
135
+ mediaType: MediaType;
136
+ mediaUrl: string;
137
+ mimeType: string;
138
+ name?: string | undefined;
139
+ thumbnailUrl?: string | undefined;
140
+ }[];
83
141
  _id: import("mongoose").Types.ObjectId;
84
142
  createdAt: Date;
85
143
  sender: {
@@ -88,9 +146,16 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
88
146
  };
89
147
  senderType: UserRef;
90
148
  senderId: import("mongoose").Types.ObjectId;
149
+ content?: string | undefined;
91
150
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
92
151
  }, {
93
- content: string;
152
+ media: {
153
+ mediaType: MediaType;
154
+ mediaUrl: string;
155
+ mimeType: string;
156
+ name?: string | undefined;
157
+ thumbnailUrl?: string | undefined;
158
+ }[];
94
159
  _id: import("mongoose").Types.ObjectId;
95
160
  createdAt: Date;
96
161
  sender: {
@@ -99,6 +164,7 @@ export declare class ChatroomMessageSendSocketEvent extends BaseSocketEvent<type
99
164
  };
100
165
  senderType: UserRef;
101
166
  senderId: import("mongoose").Types.ObjectId;
167
+ content?: string | undefined;
102
168
  chatroomId?: import("mongoose").Types.ObjectId | undefined;
103
169
  }>;
104
170
  };
@@ -20,7 +20,14 @@ exports.ChatroomMessageSendOutputSchema = zod_1.default.object({
20
20
  id: validation_1.ZodValidation.coerce.objectId('sender.id'),
21
21
  type: validation_1.ZodValidation.enumType(enum_1.UserRef, 'sender.type'),
22
22
  }),
23
- content: validation_1.ZodValidation.string('content', { minLength: 1, maxLength: 1000 }),
23
+ content: validation_1.ZodValidation.string('content', { minLength: 1, maxLength: 1000 }).optional(),
24
+ media: zod_1.default.array(zod_1.default.object({
25
+ mimeType: validation_1.ZodValidation.string('mimeType'),
26
+ mediaType: validation_1.ZodValidation.enumType(enum_1.MediaType, 'mediaType'),
27
+ mediaUrl: validation_1.ZodValidation.string('url'),
28
+ thumbnailUrl: validation_1.ZodValidation.string('thumbnailUrl').optional(),
29
+ name: validation_1.ZodValidation.string('name').optional(),
30
+ })),
24
31
  chatroomId: validation_1.ZodValidation.coerce.objectId('chatroomId').optional(),
25
32
  createdAt: validation_1.ZodValidation.coerce.date(),
26
33
  });
@@ -1 +1 @@
1
- {"version":3,"file":"chatroom-message-send.socket.event.js","sourceRoot":"/","sources":["libraries/socket/events/chatroom-message-send.socket.event.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AACpB,kDAAmE;AACnE,8DAA6E;AAC7E,wDAAqD;AACrD,2EAAsE;AAEzD,QAAA,oCAAoC,GAAG,aAAC,CAAC,MAAM,CAAC;IAC5D,UAAU,EAAE,qBAAQ;CACpB,CAAC,CAAC;AAEU,QAAA,+BAA+B,GAAG,aAAC,CAAC,MAAM,CAAC;IACvD,GAAG,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;IACzC,QAAQ,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;IACnD,UAAU,EAAE,0BAAa,CAAC,QAAQ,CAAC,cAAO,EAAE,YAAY,CAAC;IACzD,MAAM,EAAE,aAAC,CAAC,MAAM,CAAC;QAChB,EAAE,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC9C,IAAI,EAAE,0BAAa,CAAC,QAAQ,CAAC,cAAO,EAAE,aAAa,CAAC;KACpD,CAAC;IACF,OAAO,EAAE,0BAAa,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC3E,UAAU,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE;IAClE,SAAS,EAAE,0BAAa,CAAC,MAAM,CAAC,IAAI,EAAE;CACtC,CAAC,CAAC;AAKH,MAAa,8BAA+B,SAAQ,iCAGnD;IACA,MAAM,CAAU,OAAO,GAAG;QACzB,KAAK,EAAE,4CAAoC;QAC3C,MAAM,EAAE,uCAA+B;KACvC,CAAC;IAEK,YAAY;QAClB,OAAO,IAAI,mDAAuB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAChE,CAAC;IAEM,gBAAgB;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,YAAY,OAA2C;QACtD,KAAK,CAAC,sBAAe,CAAC,qBAAqB,EAAE,8BAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,KAA2D;QAC5E,OAAO,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;;AAvBF,wEAwBC","sourcesContent":["import z from 'zod';\nimport { SocketEventType, UserRef } from '../../../utilities/enum';\nimport { DTO, IdSchema, ZodValidation } from '../../../utilities/validation';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\nimport { NotificationSocketEvent } from './notification.socket.event';\n\nexport const ChatroomMessageSendSocketInputSchema = z.object({\n\tchatroomId: IdSchema,\n});\n\nexport const ChatroomMessageSendOutputSchema = z.object({\n\t_id: ZodValidation.coerce.objectId('_id'),\n\tsenderId: ZodValidation.coerce.objectId('senderId'), // DEPRECATED\n\tsenderType: ZodValidation.enumType(UserRef, 'senderType'), // DEPRECATED\n\tsender: z.object({\n\t\tid: ZodValidation.coerce.objectId('sender.id'),\n\t\ttype: ZodValidation.enumType(UserRef, 'sender.type'),\n\t}),\n\tcontent: ZodValidation.string('content', { minLength: 1, maxLength: 1000 }),\n\tchatroomId: ZodValidation.coerce.objectId('chatroomId').optional(),\n\tcreatedAt: ZodValidation.coerce.date(),\n});\n\nexport type ChatroomMessageSendSocketOutputDTO = DTO<typeof ChatroomMessageSendOutputSchema>;\nexport type ChatroomMessageSendSocketInputDTO = DTO<typeof ChatroomMessageSendSocketInputSchema>;\n\nexport class ChatroomMessageSendSocketEvent extends BaseSocketEvent<\n\ttypeof ChatroomMessageSendSocketInputSchema,\n\ttypeof ChatroomMessageSendOutputSchema\n> {\n\tstatic readonly schemas = {\n\t\tinput: ChatroomMessageSendSocketInputSchema,\n\t\toutput: ChatroomMessageSendOutputSchema,\n\t};\n\n\tpublic notification(): NotificationSocketEvent | null {\n\t\treturn new NotificationSocketEvent({ message: `New message` });\n\t}\n\n\tpublic pushNotification(): NotificationSocketEvent | null {\n\t\treturn null;\n\t}\n\n\tconstructor(payload: ChatroomMessageSendSocketOutputDTO) {\n\t\tsuper(SocketEventType.CHATROOM_MESSAGE_SEND, ChatroomMessageSendSocketEvent.schemas, payload);\n\t}\n\n\tstatic identifier(input: z.infer<typeof ChatroomMessageSendSocketInputSchema>): string {\n\t\treturn input.chatroomId.toString();\n\t}\n}\n"]}
1
+ {"version":3,"file":"chatroom-message-send.socket.event.js","sourceRoot":"/","sources":["libraries/socket/events/chatroom-message-send.socket.event.ts"],"names":[],"mappings":";;;;;;AAAA,8CAAoB;AACpB,kDAA8E;AAC9E,8DAA6E;AAC7E,wDAAqD;AACrD,2EAAsE;AAEzD,QAAA,oCAAoC,GAAG,aAAC,CAAC,MAAM,CAAC;IAC5D,UAAU,EAAE,qBAAQ;CACpB,CAAC,CAAC;AAEU,QAAA,+BAA+B,GAAG,aAAC,CAAC,MAAM,CAAC;IACvD,GAAG,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;IACzC,QAAQ,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,UAAU,CAAC;IACnD,UAAU,EAAE,0BAAa,CAAC,QAAQ,CAAC,cAAO,EAAE,YAAY,CAAC;IACzD,MAAM,EAAE,aAAC,CAAC,MAAM,CAAC;QAChB,EAAE,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC;QAC9C,IAAI,EAAE,0BAAa,CAAC,QAAQ,CAAC,cAAO,EAAE,aAAa,CAAC;KACpD,CAAC;IACF,OAAO,EAAE,0BAAa,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,QAAQ,EAAE;IACtF,KAAK,EAAE,aAAC,CAAC,KAAK,CACb,aAAC,CAAC,MAAM,CAAC;QACR,QAAQ,EAAE,0BAAa,CAAC,MAAM,CAAC,UAAU,CAAC;QAC1C,SAAS,EAAE,0BAAa,CAAC,QAAQ,CAAC,gBAAS,EAAE,WAAW,CAAC;QACzD,QAAQ,EAAE,0BAAa,CAAC,MAAM,CAAC,KAAK,CAAC;QACrC,YAAY,EAAE,0BAAa,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,QAAQ,EAAE;QAC7D,IAAI,EAAE,0BAAa,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE;KAC7C,CAAC,CACF;IACD,UAAU,EAAE,0BAAa,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,EAAE;IAClE,SAAS,EAAE,0BAAa,CAAC,MAAM,CAAC,IAAI,EAAE;CACtC,CAAC,CAAC;AAKH,MAAa,8BAA+B,SAAQ,iCAGnD;IACA,MAAM,CAAU,OAAO,GAAG;QACzB,KAAK,EAAE,4CAAoC;QAC3C,MAAM,EAAE,uCAA+B;KACvC,CAAC;IAEK,YAAY;QAClB,OAAO,IAAI,mDAAuB,CAAC,EAAE,OAAO,EAAE,aAAa,EAAE,CAAC,CAAC;IAChE,CAAC;IAEM,gBAAgB;QACtB,OAAO,IAAI,CAAC;IACb,CAAC;IAED,YAAY,OAA2C;QACtD,KAAK,CAAC,sBAAe,CAAC,qBAAqB,EAAE,8BAA8B,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/F,CAAC;IAED,MAAM,CAAC,UAAU,CAAC,KAA2D;QAC5E,OAAO,KAAK,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC;IACpC,CAAC;;AAvBF,wEAwBC","sourcesContent":["import z from 'zod';\nimport { MediaType, SocketEventType, UserRef } from '../../../utilities/enum';\nimport { DTO, IdSchema, ZodValidation } from '../../../utilities/validation';\nimport { BaseSocketEvent } from '../BaseSocketEvent';\nimport { NotificationSocketEvent } from './notification.socket.event';\n\nexport const ChatroomMessageSendSocketInputSchema = z.object({\n\tchatroomId: IdSchema,\n});\n\nexport const ChatroomMessageSendOutputSchema = z.object({\n\t_id: ZodValidation.coerce.objectId('_id'),\n\tsenderId: ZodValidation.coerce.objectId('senderId'), // DEPRECATED\n\tsenderType: ZodValidation.enumType(UserRef, 'senderType'), // DEPRECATED\n\tsender: z.object({\n\t\tid: ZodValidation.coerce.objectId('sender.id'),\n\t\ttype: ZodValidation.enumType(UserRef, 'sender.type'),\n\t}),\n\tcontent: ZodValidation.string('content', { minLength: 1, maxLength: 1000 }).optional(),\n\tmedia: z.array(\n\t\tz.object({\n\t\t\tmimeType: ZodValidation.string('mimeType'),\n\t\t\tmediaType: ZodValidation.enumType(MediaType, 'mediaType'),\n\t\t\tmediaUrl: ZodValidation.string('url'),\n\t\t\tthumbnailUrl: ZodValidation.string('thumbnailUrl').optional(),\n\t\t\tname: ZodValidation.string('name').optional(),\n\t\t})\n\t),\n\tchatroomId: ZodValidation.coerce.objectId('chatroomId').optional(),\n\tcreatedAt: ZodValidation.coerce.date(),\n});\n\nexport type ChatroomMessageSendSocketOutputDTO = DTO<typeof ChatroomMessageSendOutputSchema>;\nexport type ChatroomMessageSendSocketInputDTO = DTO<typeof ChatroomMessageSendSocketInputSchema>;\n\nexport class ChatroomMessageSendSocketEvent extends BaseSocketEvent<\n\ttypeof ChatroomMessageSendSocketInputSchema,\n\ttypeof ChatroomMessageSendOutputSchema\n> {\n\tstatic readonly schemas = {\n\t\tinput: ChatroomMessageSendSocketInputSchema,\n\t\toutput: ChatroomMessageSendOutputSchema,\n\t};\n\n\tpublic notification(): NotificationSocketEvent | null {\n\t\treturn new NotificationSocketEvent({ message: `New message` });\n\t}\n\n\tpublic pushNotification(): NotificationSocketEvent | null {\n\t\treturn null;\n\t}\n\n\tconstructor(payload: ChatroomMessageSendSocketOutputDTO) {\n\t\tsuper(SocketEventType.CHATROOM_MESSAGE_SEND, ChatroomMessageSendSocketEvent.schemas, payload);\n\t}\n\n\tstatic identifier(input: z.infer<typeof ChatroomMessageSendSocketInputSchema>): string {\n\t\treturn input.chatroomId.toString();\n\t}\n}\n"]}
@@ -22,7 +22,7 @@ Perfect for sharing types between frontend and backend applications.
22
22
 
23
23
  ## Version
24
24
 
25
- Version: 1.1.67
25
+ Version: 1.1.69
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/types",
3
- "version": "1.1.67",
3
+ "version": "1.1.69",
4
4
  "description": "Lyxa type definitions and validation schemas for both frontend and backend",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",
@@ -1,10 +1,11 @@
1
1
  import { z, ZodTypeAny } from 'zod';
2
2
  type ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];
3
- export interface FilterSchemaConfig<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}> {
3
+ export interface FilterSchemaConfig<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []> {
4
4
  selectableFields?: TSelect;
5
5
  populatableFields?: TPopulate;
6
6
  searchableFields?: TSearch;
7
7
  queryableFields?: TQuery;
8
+ sortableFields?: TSort;
8
9
  maxSize?: number;
9
10
  defaultSize?: number;
10
11
  }
@@ -21,10 +22,10 @@ export type PopulateObject<TPath extends string, TSelectFields extends ReadonlyN
21
22
  type PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {
22
23
  [K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;
23
24
  }[keyof TPopulate];
24
- export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}> = {
25
+ export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []> = {
25
26
  size?: number;
26
27
  page?: number;
27
- sort?: Record<string, 1 | -1>;
28
+ sort?: TSort extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSort[number], 1 | -1>> : never;
28
29
  select?: TSelect extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSelect[number], 0 | 1>> : never;
29
30
  populate?: PopulateUnion<TPopulate>[];
30
31
  search?: TSearch extends ReadonlyNonEmptyArray<string> ? {
@@ -35,5 +36,5 @@ export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], T
35
36
  [K in keyof TQuery]?: z.infer<TQuery[K]>;
36
37
  };
37
38
  };
38
- export declare function createFilterSchema<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery>): z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery>>;
39
+ export declare function createFilterSchema<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery, TSort>): z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery, TSort>>;
39
40
  export {};
@@ -4,13 +4,17 @@ exports.createFilterSchema = createFilterSchema;
4
4
  const zod_1 = require("zod");
5
5
  const sortSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(-1)]));
6
6
  function createFilterSchema(config) {
7
- const { selectableFields, populatableFields, searchableFields, queryableFields, maxSize = 100, defaultSize = 10, } = config;
7
+ const { selectableFields, populatableFields, searchableFields, queryableFields, sortableFields, maxSize = 100, defaultSize = 10, } = config;
8
8
  const populateKeys = populatableFields ? Object.keys(populatableFields) : [];
9
9
  const schemaShape = {
10
10
  size: zod_1.z.number().min(1).max(maxSize).optional().default(defaultSize),
11
11
  page: zod_1.z.number().min(1).optional().default(1),
12
- sort: sortSchema.optional(),
13
12
  };
13
+ if (sortableFields?.length) {
14
+ schemaShape.sort = zod_1.z
15
+ .record(zod_1.z.enum([...sortableFields]), zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(-1)]))
16
+ .optional();
17
+ }
14
18
  if (selectableFields?.length) {
15
19
  schemaShape.select = zod_1.z
16
20
  .record(zod_1.z.enum([...selectableFields]), zod_1.z.union([zod_1.z.literal(0), zod_1.z.literal(1)]))
@@ -59,14 +63,7 @@ function createFilterSchema(config) {
59
63
  return zod_1.z.object(schemaShape);
60
64
  }
61
65
  const TicketFilterSchema = createFilterSchema({
62
- selectableFields: [
63
- '_id',
64
- 'ticketId',
65
- 'type',
66
- 'status',
67
- 'createdAt',
68
- 'updatedAt',
69
- ],
66
+ selectableFields: ['_id', 'ticketId', 'type', 'status', 'createdAt', 'updatedAt'],
70
67
  populatableFields: {
71
68
  chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'],
72
69
  client: ['_id', 'name', 'profilePhoto', 'type'],
@@ -74,6 +71,7 @@ const TicketFilterSchema = createFilterSchema({
74
71
  order: ['_id', 'orderId', 'shop', 'total'],
75
72
  },
76
73
  searchableFields: ['ticketId'],
74
+ sortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'],
77
75
  queryableFields: {
78
76
  status: zod_1.z.enum(['OPEN', 'CLOSED', 'PENDING']),
79
77
  type: zod_1.z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),
@@ -81,5 +79,7 @@ const TicketFilterSchema = createFilterSchema({
81
79
  clientType: zod_1.z.enum(['USER', 'SHOP']),
82
80
  },
83
81
  });
84
- const ticket = {};
82
+ const ticket = {
83
+ sort: { createdAt: -1, status: 1 },
84
+ };
85
85
  //# sourceMappingURL=filter-schema.factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-schema.factory.js","sourceRoot":"/","sources":["utilities/validation/filter-schema.factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { z, ZodTypeAny } from 'zod';\n\ntype ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];\n\nexport interface FilterSchemaConfig<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n> {\n\tselectableFields?: TSelect;\n\tpopulatableFields?: TPopulate;\n\tsearchableFields?: TSearch;\n\tqueryableFields?: TQuery;\n\tmaxSize?: number;\n\tdefaultSize?: number;\n}\n\n// Populate object type\nexport type PopulateObject<\n\tTPath extends string,\n\tTSelectFields extends ReadonlyNonEmptyArray<string>\n> = {\n\tpath: TPath;\n\tselect?: Partial<Record<TSelectFields[number], 0 | 1>>;\n\tmatch?: Record<string, any>;\n\toptions?: { sort?: Record<string, 1 | -1>; limit?: number; skip?: number };\n};\n\n// Union of all possible populate objects based on populatableFields\ntype PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {\n\t[K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;\n}[keyof TPopulate];\n\n// DTO type\nexport type FilterDTO<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n> = {\n\tsize?: number;\n\tpage?: number;\n\tsort?: Record<string, 1 | -1>;\n\tselect?: TSelect extends ReadonlyNonEmptyArray<string>\n\t\t? Partial<Record<TSelect[number], 0 | 1>>\n\t\t: never;\n\tpopulate?: PopulateUnion<TPopulate>[];\n\tsearch?: TSearch extends ReadonlyNonEmptyArray<string>\n\t\t? { searchKey: string; searchFields?: TSearch[number][] }\n\t\t: never;\n\tquery?: { [K in keyof TQuery]?: z.infer<TQuery[K]> };\n};\n\nconst sortSchema = z.record(z.string(), z.union([z.literal(1), z.literal(-1)]));\n\nexport function createFilterSchema<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery>) {\n\tconst {\n\t\tselectableFields,\n\t\tpopulatableFields,\n\t\tsearchableFields,\n\t\tqueryableFields,\n\t\tmaxSize = 100,\n\t\tdefaultSize = 10,\n\t} = config;\n\n\tconst populateKeys = populatableFields ? (Object.keys(populatableFields) as (keyof TPopulate)[]) : [];\n\n\tconst schemaShape: Record<string, any> = {\n\t\tsize: z.number().min(1).max(maxSize).optional().default(defaultSize),\n\t\tpage: z.number().min(1).optional().default(1),\n\t\tsort: sortSchema.optional(),\n\t};\n\n\t// Top-level select\n\tif (selectableFields?.length) {\n\t\tschemaShape.select = z\n\t\t\t.record(\n\t\t\t\tz.enum([...selectableFields] as [string, ...string[]]),\n\t\t\t\tz.union([z.literal(0), z.literal(1)]),\n\t\t\t)\n\t\t\t.optional();\n\t}\n\n\t// Populate as array of objects with strict typing per path\n\tif (populateKeys.length) {\n\t\tconst populateSchemas: ZodTypeAny[] = [];\n\n\t\tfor (const path of populateKeys) {\n\t\t\tconst allowedSelects = populatableFields![path] as ReadonlyNonEmptyArray<string>;\n\n\t\t\tconst populateSchema = z.object({\n\t\t\t\tpath: z.literal(path as string),\n\t\t\t\tselect: z\n\t\t\t\t\t.record(z.enum([...allowedSelects] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t\t\t.optional(),\n\t\t\t\tmatch: z.record(z.string(), z.any()).optional(),\n\t\t\t\toptions: z\n\t\t\t\t\t.object({\n\t\t\t\t\t\tsort: sortSchema.optional(),\n\t\t\t\t\t\tlimit: z.number().optional(),\n\t\t\t\t\t\tskip: z.number().optional(),\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t});\n\n\t\t\tpopulateSchemas.push(populateSchema);\n\t\t}\n\n\t\tconst unionSchema =\n\t\t\tpopulateSchemas.length === 1\n\t\t\t\t? populateSchemas[0]\n\t\t\t\t: z.union(populateSchemas as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n\n\t\tschemaShape.populate = z.array(unionSchema).optional();\n\t}\n\n\t// Search\n\tif (searchableFields?.length) {\n\t\tschemaShape.search = z\n\t\t\t.object({\n\t\t\t\tsearchKey: z.string(),\n\t\t\t\tsearchFields: z.array(z.enum([...searchableFields] as [string, ...string[]])).optional(),\n\t\t\t})\n\t\t\t.optional();\n\t}\n\n\t// Query\n\tif (queryableFields && Object.keys(queryableFields).length) {\n\t\tconst queryShape: Record<string, ZodTypeAny> = {};\n\t\tfor (const key in queryableFields) {\n\t\t\tqueryShape[key] = queryableFields[key].optional();\n\t\t}\n\t\tschemaShape.query = z.object(queryShape).optional();\n\t}\n\n\treturn z.object(schemaShape) as z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery>>;\n}\n\n\nconst TicketFilterSchema = createFilterSchema({\n\t// Top-level document fields that can be selected\n\tselectableFields: [\n\t\t'_id',\n\t\t'ticketId',\n\t\t'type',\n\t\t'status',\n\t\t'createdAt',\n\t\t'updatedAt',\n\t] as const,\n\n\t// Each populate path has its own allowed select fields\n\tpopulatableFields: {\n\t\tchatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n\t\tclient: ['_id', 'name', 'profilePhoto', 'type'] as const,\n\t\tadmin: ['_id', 'name', 'profilePhoto'] as const,\n\t\torder: ['_id', 'orderId', 'shop', 'total'] as const,\n\t} as const,\n\n\tsearchableFields: ['ticketId'] as const,\n\n\tqueryableFields: {\n\t\tstatus: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n\t\ttype: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n\t\tclient: z.string(),\n\t\tclientType: z.enum(['USER', 'SHOP']),\n\t},\n});\n\ntype TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n\nconst ticket: TicketFilterDTO = {\n\n}\n\n\n/**\n * EXAMPLE USAGE\n *\n * const TicketFilterSchema = createFilterSchema({\n * // Top-level document fields that can be selected\n * selectableFields: [\n * '_id',\n * 'ticketId',\n * 'type',\n * 'status',\n * 'createdAt',\n * 'updatedAt',\n * ] as const,\n *\n * // Each populate path has its own allowed select fields\n * populatableFields: {\n * chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n * client: ['_id', 'name', 'profilePhoto', 'type'] as const,\n * admin: ['_id', 'name', 'profilePhoto'] as const,\n * order: ['_id', 'orderId', 'shop', 'total'] as const,\n * } as const,\n *\n * searchableFields: ['ticketId'] as const,\n *\n * queryableFields: {\n * status: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n * type: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n * client: z.string(),\n * clientType: z.enum(['USER', 'SHOP']),\n * },\n * });\n *\n * type TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n *\n * // ✅ VALID EXAMPLES\n *\n * // Example 1: Select only top-level fields\n * const filter1: TicketFilterDTO = {\n * select: { ticketId: 1, status: 1, createdAt: 1 },\n * query: { status: 'OPEN' },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 2: Populate client with specific fields\n * const filter2: TicketFilterDTO = {\n * populate: {\n * path: 'client',\n * select: { name: 1, profilePhoto: 1 }, // Uses client's allowed fields\n * },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 3: Populate multiple relations\n * const filter3: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } },\n * { path: 'order', select: { orderId: 1, total: 1 } },\n * { path: 'chatroom', select: { lastMessage: 1, unreadCount: 1 } },\n * ],\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 4: Complex query with search\n * const filter4: TicketFilterDTO = {\n * query: { status: 'OPEN', type: 'ORDER' },\n * search: { searchKey: 'TKT-123', searchFields: ['ticketId'] },\n * populate: { path: 'client', select: { name: 1 } },\n * sort: { createdAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 5: Populate with match and options\n * const filter5: TicketFilterDTO = {\n * populate: {\n * path: 'order',\n * select: { orderId: 1, shop: 1 },\n * match: { status: 'DELIVERED' },\n * options: { sort: { createdAt: -1 }, limit: 10 },\n * },\n * page: 1,\n * size: 20,\n * };\n *\n * // ❌ INVALID EXAMPLES (TypeScript will reject)\n *\n * const invalid1: TicketFilterDTO = {\n * select: { invalidField: 1 }, // ❌ not in selectableFields\n * };\n *\n * const invalid2: TicketFilterDTO = {\n * populate: {\n * path: 'client',\n * select: { email: 1 }, // ❌ email not in client's populatableFields\n * },\n * };\n *\n * const invalid3: TicketFilterDTO = {\n * populate: {\n * path: 'invalidPath', // ❌ path doesn't exist\n * select: { name: 1 },\n * },\n * };\n *\n * const invalid4: TicketFilterDTO = {\n * query: { status: 'INVALID_STATUS' }, // ❌ not in enum\n * }\n */"]}
1
+ {"version":3,"file":"filter-schema.factory.js","sourceRoot":"/","sources":["utilities/validation/filter-schema.factory.ts"],"names":[],"mappings":";;AAsDA,gDA2FC;AAjJD,6BAAoC;AAoDpC,MAAM,UAAU,GAAG,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAEhF,SAAgB,kBAAkB,CAMhC,MAAsE;IACvE,MAAM,EACL,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,cAAc,EACd,OAAO,GAAG,GAAG,EACb,WAAW,GAAG,EAAE,GAChB,GAAG,MAAM,CAAC;IAEX,MAAM,YAAY,GAAG,iBAAiB,CAAC,CAAC,CAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAyB,CAAC,CAAC,CAAC,EAAE,CAAC;IAEtG,MAAM,WAAW,GAAwB;QACxC,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC;QACpE,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;KAC7C,CAAC;IAGF,IAAI,cAAc,EAAE,MAAM,EAAE,CAAC;QAC5B,WAAW,CAAC,IAAI,GAAG,OAAC;aAClB,MAAM,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,cAAc,CAA0B,CAAC,EAAE,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACpG,QAAQ,EAAE,CAAC;IACd,CAAC;IAGD,IAAI,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC9B,WAAW,CAAC,MAAM,GAAG,OAAC;aACpB,MAAM,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,gBAAgB,CAA0B,CAAC,EAAE,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;aACrG,QAAQ,EAAE,CAAC;IACd,CAAC;IAGD,IAAI,YAAY,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,eAAe,GAAiB,EAAE,CAAC;QAEzC,KAAK,MAAM,IAAI,IAAI,YAAY,EAAE,CAAC;YACjC,MAAM,cAAc,GAAG,iBAAkB,CAAC,IAAI,CAAkC,CAAC;YAEjF,MAAM,cAAc,GAAG,OAAC,CAAC,MAAM,CAAC;gBAC/B,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,IAAc,CAAC;gBAC/B,MAAM,EAAE,OAAC;qBACP,MAAM,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,cAAc,CAA0B,CAAC,EAAE,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;qBACnG,QAAQ,EAAE;gBACZ,KAAK,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE;gBAC/C,OAAO,EAAE,OAAC;qBACR,MAAM,CAAC;oBACP,IAAI,EAAE,UAAU,CAAC,QAAQ,EAAE;oBAC3B,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;oBAC5B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;iBAC3B,CAAC;qBACD,QAAQ,EAAE;aACZ,CAAC,CAAC;YAEH,eAAe,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QACtC,CAAC;QAED,MAAM,WAAW,GAChB,eAAe,CAAC,MAAM,KAAK,CAAC;YAC3B,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;YACpB,CAAC,CAAC,OAAC,CAAC,KAAK,CAAC,eAA4D,CAAC,CAAC;QAE1E,WAAW,CAAC,QAAQ,GAAG,OAAC,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;IACxD,CAAC;IAGD,IAAI,gBAAgB,EAAE,MAAM,EAAE,CAAC;QAC9B,WAAW,CAAC,MAAM,GAAG,OAAC;aACpB,MAAM,CAAC;YACP,SAAS,EAAE,OAAC,CAAC,MAAM,EAAE;YACrB,YAAY,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,IAAI,CAAC,CAAC,GAAG,gBAAgB,CAA0B,CAAC,CAAC,CAAC,QAAQ,EAAE;SACxF,CAAC;aACD,QAAQ,EAAE,CAAC;IACd,CAAC;IAGD,IAAI,eAAe,IAAI,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,EAAE,CAAC;QAC5D,MAAM,UAAU,GAA+B,EAAE,CAAC;QAClD,KAAK,MAAM,GAAG,IAAI,eAAe,EAAE,CAAC;YACnC,UAAU,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,CAAC;QACnD,CAAC;QACD,WAAW,CAAC,KAAK,GAAG,OAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrD,CAAC;IAED,OAAO,OAAC,CAAC,MAAM,CAAC,WAAW,CAAqE,CAAC;AAClG,CAAC;AAED,MAAM,kBAAkB,GAAG,kBAAkB,CAAC;IAE7C,gBAAgB,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,CAAU;IAG1F,iBAAiB,EAAE;QAClB,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,aAAa,CAAU;QACxE,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,CAAU;QACxD,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,cAAc,CAAU;QAC/C,KAAK,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAU;KAC1C;IAEV,gBAAgB,EAAE,CAAC,UAAU,CAAU;IAEvC,cAAc,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,QAAQ,CAAU;IAEzE,eAAe,EAAE;QAChB,MAAM,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC7C,IAAI,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,SAAS,EAAE,WAAW,CAAC,CAAC;QAC/C,MAAM,EAAE,OAAC,CAAC,MAAM,EAAE;QAClB,UAAU,EAAE,OAAC,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC;CACD,CAAC,CAAC;AAIH,MAAM,MAAM,GAAoB;IAC/B,IAAI,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE;CAClC,CAAC","sourcesContent":["import { z, ZodTypeAny } from 'zod';\n\ntype ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];\n\nexport interface FilterSchemaConfig<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n> {\n\tselectableFields?: TSelect;\n\tpopulatableFields?: TPopulate;\n\tsearchableFields?: TSearch;\n\tqueryableFields?: TQuery;\n\tsortableFields?: TSort;\n\tmaxSize?: number;\n\tdefaultSize?: number;\n}\n\n// Populate object type\nexport type PopulateObject<TPath extends string, TSelectFields extends ReadonlyNonEmptyArray<string>> = {\n\tpath: TPath;\n\tselect?: Partial<Record<TSelectFields[number], 0 | 1>>;\n\tmatch?: Record<string, any>;\n\toptions?: { sort?: Record<string, 1 | -1>; limit?: number; skip?: number };\n};\n\n// Union of all possible populate objects based on populatableFields\ntype PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {\n\t[K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;\n}[keyof TPopulate];\n\n// DTO type\nexport type FilterDTO<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n> = {\n\tsize?: number;\n\tpage?: number;\n\tsort?: TSort extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSort[number], 1 | -1>> : never;\n\tselect?: TSelect extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSelect[number], 0 | 1>> : never;\n\tpopulate?: PopulateUnion<TPopulate>[];\n\tsearch?: TSearch extends ReadonlyNonEmptyArray<string>\n\t\t? { searchKey: string; searchFields?: TSearch[number][] }\n\t\t: never;\n\tquery?: { [K in keyof TQuery]?: z.infer<TQuery[K]> };\n};\n\nconst sortSchema = z.record(z.string(), z.union([z.literal(1), z.literal(-1)]));\n\nexport function createFilterSchema<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery, TSort>) {\n\tconst {\n\t\tselectableFields,\n\t\tpopulatableFields,\n\t\tsearchableFields,\n\t\tqueryableFields,\n\t\tsortableFields,\n\t\tmaxSize = 100,\n\t\tdefaultSize = 10,\n\t} = config;\n\n\tconst populateKeys = populatableFields ? (Object.keys(populatableFields) as (keyof TPopulate)[]) : [];\n\n\tconst schemaShape: Record<string, any> = {\n\t\tsize: z.number().min(1).max(maxSize).optional().default(defaultSize),\n\t\tpage: z.number().min(1).optional().default(1),\n\t};\n\n\t// Sort with allowed fields\n\tif (sortableFields?.length) {\n\t\tschemaShape.sort = z\n\t\t\t.record(z.enum([...sortableFields] as [string, ...string[]]), z.union([z.literal(1), z.literal(-1)]))\n\t\t\t.optional();\n\t}\n\n\t// Top-level select\n\tif (selectableFields?.length) {\n\t\tschemaShape.select = z\n\t\t\t.record(z.enum([...selectableFields] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t.optional();\n\t}\n\n\t// Populate as array of objects with strict typing per path\n\tif (populateKeys.length) {\n\t\tconst populateSchemas: ZodTypeAny[] = [];\n\n\t\tfor (const path of populateKeys) {\n\t\t\tconst allowedSelects = populatableFields![path] as ReadonlyNonEmptyArray<string>;\n\n\t\t\tconst populateSchema = z.object({\n\t\t\t\tpath: z.literal(path as string),\n\t\t\t\tselect: z\n\t\t\t\t\t.record(z.enum([...allowedSelects] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t\t\t.optional(),\n\t\t\t\tmatch: z.record(z.string(), z.any()).optional(),\n\t\t\t\toptions: z\n\t\t\t\t\t.object({\n\t\t\t\t\t\tsort: sortSchema.optional(),\n\t\t\t\t\t\tlimit: z.number().optional(),\n\t\t\t\t\t\tskip: z.number().optional(),\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t});\n\n\t\t\tpopulateSchemas.push(populateSchema);\n\t\t}\n\n\t\tconst unionSchema =\n\t\t\tpopulateSchemas.length === 1\n\t\t\t\t? populateSchemas[0]\n\t\t\t\t: z.union(populateSchemas as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n\n\t\tschemaShape.populate = z.array(unionSchema).optional();\n\t}\n\n\t// Search\n\tif (searchableFields?.length) {\n\t\tschemaShape.search = z\n\t\t\t.object({\n\t\t\t\tsearchKey: z.string(),\n\t\t\t\tsearchFields: z.array(z.enum([...searchableFields] as [string, ...string[]])).optional(),\n\t\t\t})\n\t\t\t.optional();\n\t}\n\n\t// Query\n\tif (queryableFields && Object.keys(queryableFields).length) {\n\t\tconst queryShape: Record<string, ZodTypeAny> = {};\n\t\tfor (const key in queryableFields) {\n\t\t\tqueryShape[key] = queryableFields[key].optional();\n\t\t}\n\t\tschemaShape.query = z.object(queryShape).optional();\n\t}\n\n\treturn z.object(schemaShape) as z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery, TSort>>;\n}\n\nconst TicketFilterSchema = createFilterSchema({\n\t// Top-level document fields that can be selected\n\tselectableFields: ['_id', 'ticketId', 'type', 'status', 'createdAt', 'updatedAt'] as const,\n\n\t// Each populate path has its own allowed select fields\n\tpopulatableFields: {\n\t\tchatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n\t\tclient: ['_id', 'name', 'profilePhoto', 'type'] as const,\n\t\tadmin: ['_id', 'name', 'profilePhoto'] as const,\n\t\torder: ['_id', 'orderId', 'shop', 'total'] as const,\n\t} as const,\n\n\tsearchableFields: ['ticketId'] as const,\n\n\tsortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'] as const,\n\n\tqueryableFields: {\n\t\tstatus: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n\t\ttype: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n\t\tclient: z.string(),\n\t\tclientType: z.enum(['USER', 'SHOP']),\n\t},\n});\n\ntype TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n\nconst ticket: TicketFilterDTO = {\n\tsort: { createdAt: -1, status: 1 }, // ✅ Only allowed fields with 1 or -1\n};\n\n/**\n * EXAMPLE USAGE\n *\n * const TicketFilterSchema = createFilterSchema({\n * selectableFields: [\n * '_id',\n * 'ticketId',\n * 'type',\n * 'status',\n * 'createdAt',\n * 'updatedAt',\n * ] as const,\n *\n * populatableFields: {\n * chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n * client: ['_id', 'name', 'profilePhoto', 'type'] as const,\n * admin: ['_id', 'name', 'profilePhoto'] as const,\n * order: ['_id', 'orderId', 'shop', 'total'] as const,\n * } as const,\n *\n * searchableFields: ['ticketId'] as const,\n *\n * sortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'] as const,\n *\n * queryableFields: {\n * status: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n * type: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n * client: z.string(),\n * clientType: z.enum(['USER', 'SHOP']),\n * },\n * });\n *\n * type TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n *\n * // ✅ VALID EXAMPLES\n *\n * // Example 1: Sort by allowed fields\n * const filter1: TicketFilterDTO = {\n * sort: { createdAt: -1, status: 1 },\n * query: { status: 'OPEN' },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 2: Populate client with specific fields\n * const filter2: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } }\n * ],\n * sort: { updatedAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 3: Populate multiple relations with sort\n * const filter3: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } },\n * { path: 'order', select: { orderId: 1, total: 1 } },\n * { path: 'chatroom', select: { lastMessage: 1, unreadCount: 1 } },\n * ],\n * sort: { createdAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 4: Complex query with search and sort\n * const filter4: TicketFilterDTO = {\n * query: { status: 'OPEN', type: 'ORDER' },\n * search: { searchKey: 'TKT-123', searchFields: ['ticketId'] },\n * populate: [{ path: 'client', select: { name: 1 } }],\n * sort: { createdAt: -1, ticketId: 1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 5: Populate with match and options\n * const filter5: TicketFilterDTO = {\n * populate: [\n * {\n * path: 'order',\n * select: { orderId: 1, shop: 1 },\n * match: { status: 'DELIVERED' },\n * options: { sort: { createdAt: -1 }, limit: 10 },\n * }\n * ],\n * sort: { updatedAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // ❌ INVALID EXAMPLES (TypeScript will reject)\n *\n * const invalid1: TicketFilterDTO = {\n * sort: { invalidField: 1 }, // ❌ not in sortableFields\n * };\n *\n * const invalid2: TicketFilterDTO = {\n * sort: { createdAt: 2 }, // ❌ must be 1 or -1\n * };\n *\n * const invalid3: TicketFilterDTO = {\n * populate: [\n * {\n * path: 'client',\n * select: { email: 1 }, // ❌ email not in client's populatableFields\n * }\n * ],\n * };\n *\n * const invalid4: TicketFilterDTO = {\n * query: { status: 'INVALID_STATUS' }, // ❌ not in enum\n * }\n */\n"]}
@@ -1,10 +1,11 @@
1
1
  import { z, ZodTypeAny } from 'zod';
2
2
  type ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];
3
- export interface FilterSchemaConfig<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}> {
3
+ export interface FilterSchemaConfig<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []> {
4
4
  selectableFields?: TSelect;
5
5
  populatableFields?: TPopulate;
6
6
  searchableFields?: TSearch;
7
7
  queryableFields?: TQuery;
8
+ sortableFields?: TSort;
8
9
  maxSize?: number;
9
10
  defaultSize?: number;
10
11
  }
@@ -21,10 +22,10 @@ export type PopulateObject<TPath extends string, TSelectFields extends ReadonlyN
21
22
  type PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {
22
23
  [K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;
23
24
  }[keyof TPopulate];
24
- export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}> = {
25
+ export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []> = {
25
26
  size?: number;
26
27
  page?: number;
27
- sort?: Record<string, 1 | -1>;
28
+ sort?: TSort extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSort[number], 1 | -1>> : never;
28
29
  select?: TSelect extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSelect[number], 0 | 1>> : never;
29
30
  populate?: PopulateUnion<TPopulate>[];
30
31
  search?: TSearch extends ReadonlyNonEmptyArray<string> ? {
@@ -35,5 +36,5 @@ export type FilterDTO<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], T
35
36
  [K in keyof TQuery]?: z.infer<TQuery[K]>;
36
37
  };
37
38
  };
38
- export declare function createFilterSchema<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery>): z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery>>;
39
+ export declare function createFilterSchema<TSelect extends ReadonlyNonEmptyArray<string> | [] = [], TPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {}, TSearch extends ReadonlyNonEmptyArray<string> | [] = [], TQuery extends Record<string, ZodTypeAny> = {}, TSort extends ReadonlyNonEmptyArray<string> | [] = []>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery, TSort>): z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery, TSort>>;
39
40
  export {};
@@ -4,13 +4,17 @@ exports.createFilterSchema = createFilterSchema;
4
4
  const zod_1 = require("zod");
5
5
  const sortSchema = zod_1.z.record(zod_1.z.string(), zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(-1)]));
6
6
  function createFilterSchema(config) {
7
- const { selectableFields, populatableFields, searchableFields, queryableFields, maxSize = 100, defaultSize = 10, } = config;
7
+ const { selectableFields, populatableFields, searchableFields, queryableFields, sortableFields, maxSize = 100, defaultSize = 10, } = config;
8
8
  const populateKeys = populatableFields ? Object.keys(populatableFields) : [];
9
9
  const schemaShape = {
10
10
  size: zod_1.z.number().min(1).max(maxSize).optional().default(defaultSize),
11
11
  page: zod_1.z.number().min(1).optional().default(1),
12
- sort: sortSchema.optional(),
13
12
  };
13
+ if (sortableFields?.length) {
14
+ schemaShape.sort = zod_1.z
15
+ .record(zod_1.z.enum([...sortableFields]), zod_1.z.union([zod_1.z.literal(1), zod_1.z.literal(-1)]))
16
+ .optional();
17
+ }
14
18
  if (selectableFields?.length) {
15
19
  schemaShape.select = zod_1.z
16
20
  .record(zod_1.z.enum([...selectableFields]), zod_1.z.union([zod_1.z.literal(0), zod_1.z.literal(1)]))
@@ -59,14 +63,7 @@ function createFilterSchema(config) {
59
63
  return zod_1.z.object(schemaShape);
60
64
  }
61
65
  const TicketFilterSchema = createFilterSchema({
62
- selectableFields: [
63
- '_id',
64
- 'ticketId',
65
- 'type',
66
- 'status',
67
- 'createdAt',
68
- 'updatedAt',
69
- ],
66
+ selectableFields: ['_id', 'ticketId', 'type', 'status', 'createdAt', 'updatedAt'],
70
67
  populatableFields: {
71
68
  chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'],
72
69
  client: ['_id', 'name', 'profilePhoto', 'type'],
@@ -74,6 +71,7 @@ const TicketFilterSchema = createFilterSchema({
74
71
  order: ['_id', 'orderId', 'shop', 'total'],
75
72
  },
76
73
  searchableFields: ['ticketId'],
74
+ sortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'],
77
75
  queryableFields: {
78
76
  status: zod_1.z.enum(['OPEN', 'CLOSED', 'PENDING']),
79
77
  type: zod_1.z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),
@@ -81,5 +79,7 @@ const TicketFilterSchema = createFilterSchema({
81
79
  clientType: zod_1.z.enum(['USER', 'SHOP']),
82
80
  },
83
81
  });
84
- const ticket = {};
82
+ const ticket = {
83
+ sort: { createdAt: -1, status: 1 },
84
+ };
85
85
  //# sourceMappingURL=filter-schema.factory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"filter-schema.factory.js","sourceRoot":"/","sources":["utilities/validation/filter-schema.factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { z, ZodTypeAny } from 'zod';\n\ntype ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];\n\nexport interface FilterSchemaConfig<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n> {\n\tselectableFields?: TSelect;\n\tpopulatableFields?: TPopulate;\n\tsearchableFields?: TSearch;\n\tqueryableFields?: TQuery;\n\tmaxSize?: number;\n\tdefaultSize?: number;\n}\n\n// Populate object type\nexport type PopulateObject<\n\tTPath extends string,\n\tTSelectFields extends ReadonlyNonEmptyArray<string>\n> = {\n\tpath: TPath;\n\tselect?: Partial<Record<TSelectFields[number], 0 | 1>>;\n\tmatch?: Record<string, any>;\n\toptions?: { sort?: Record<string, 1 | -1>; limit?: number; skip?: number };\n};\n\n// Union of all possible populate objects based on populatableFields\ntype PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {\n\t[K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;\n}[keyof TPopulate];\n\n// DTO type\nexport type FilterDTO<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n> = {\n\tsize?: number;\n\tpage?: number;\n\tsort?: Record<string, 1 | -1>;\n\tselect?: TSelect extends ReadonlyNonEmptyArray<string>\n\t\t? Partial<Record<TSelect[number], 0 | 1>>\n\t\t: never;\n\tpopulate?: PopulateUnion<TPopulate>[];\n\tsearch?: TSearch extends ReadonlyNonEmptyArray<string>\n\t\t? { searchKey: string; searchFields?: TSearch[number][] }\n\t\t: never;\n\tquery?: { [K in keyof TQuery]?: z.infer<TQuery[K]> };\n};\n\nconst sortSchema = z.record(z.string(), z.union([z.literal(1), z.literal(-1)]));\n\nexport function createFilterSchema<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery>) {\n\tconst {\n\t\tselectableFields,\n\t\tpopulatableFields,\n\t\tsearchableFields,\n\t\tqueryableFields,\n\t\tmaxSize = 100,\n\t\tdefaultSize = 10,\n\t} = config;\n\n\tconst populateKeys = populatableFields ? (Object.keys(populatableFields) as (keyof TPopulate)[]) : [];\n\n\tconst schemaShape: Record<string, any> = {\n\t\tsize: z.number().min(1).max(maxSize).optional().default(defaultSize),\n\t\tpage: z.number().min(1).optional().default(1),\n\t\tsort: sortSchema.optional(),\n\t};\n\n\t// Top-level select\n\tif (selectableFields?.length) {\n\t\tschemaShape.select = z\n\t\t\t.record(\n\t\t\t\tz.enum([...selectableFields] as [string, ...string[]]),\n\t\t\t\tz.union([z.literal(0), z.literal(1)]),\n\t\t\t)\n\t\t\t.optional();\n\t}\n\n\t// Populate as array of objects with strict typing per path\n\tif (populateKeys.length) {\n\t\tconst populateSchemas: ZodTypeAny[] = [];\n\n\t\tfor (const path of populateKeys) {\n\t\t\tconst allowedSelects = populatableFields![path] as ReadonlyNonEmptyArray<string>;\n\n\t\t\tconst populateSchema = z.object({\n\t\t\t\tpath: z.literal(path as string),\n\t\t\t\tselect: z\n\t\t\t\t\t.record(z.enum([...allowedSelects] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t\t\t.optional(),\n\t\t\t\tmatch: z.record(z.string(), z.any()).optional(),\n\t\t\t\toptions: z\n\t\t\t\t\t.object({\n\t\t\t\t\t\tsort: sortSchema.optional(),\n\t\t\t\t\t\tlimit: z.number().optional(),\n\t\t\t\t\t\tskip: z.number().optional(),\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t});\n\n\t\t\tpopulateSchemas.push(populateSchema);\n\t\t}\n\n\t\tconst unionSchema =\n\t\t\tpopulateSchemas.length === 1\n\t\t\t\t? populateSchemas[0]\n\t\t\t\t: z.union(populateSchemas as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n\n\t\tschemaShape.populate = z.array(unionSchema).optional();\n\t}\n\n\t// Search\n\tif (searchableFields?.length) {\n\t\tschemaShape.search = z\n\t\t\t.object({\n\t\t\t\tsearchKey: z.string(),\n\t\t\t\tsearchFields: z.array(z.enum([...searchableFields] as [string, ...string[]])).optional(),\n\t\t\t})\n\t\t\t.optional();\n\t}\n\n\t// Query\n\tif (queryableFields && Object.keys(queryableFields).length) {\n\t\tconst queryShape: Record<string, ZodTypeAny> = {};\n\t\tfor (const key in queryableFields) {\n\t\t\tqueryShape[key] = queryableFields[key].optional();\n\t\t}\n\t\tschemaShape.query = z.object(queryShape).optional();\n\t}\n\n\treturn z.object(schemaShape) as z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery>>;\n}\n\n\nconst TicketFilterSchema = createFilterSchema({\n\t// Top-level document fields that can be selected\n\tselectableFields: [\n\t\t'_id',\n\t\t'ticketId',\n\t\t'type',\n\t\t'status',\n\t\t'createdAt',\n\t\t'updatedAt',\n\t] as const,\n\n\t// Each populate path has its own allowed select fields\n\tpopulatableFields: {\n\t\tchatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n\t\tclient: ['_id', 'name', 'profilePhoto', 'type'] as const,\n\t\tadmin: ['_id', 'name', 'profilePhoto'] as const,\n\t\torder: ['_id', 'orderId', 'shop', 'total'] as const,\n\t} as const,\n\n\tsearchableFields: ['ticketId'] as const,\n\n\tqueryableFields: {\n\t\tstatus: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n\t\ttype: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n\t\tclient: z.string(),\n\t\tclientType: z.enum(['USER', 'SHOP']),\n\t},\n});\n\ntype TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n\nconst ticket: TicketFilterDTO = {\n\n}\n\n\n/**\n * EXAMPLE USAGE\n *\n * const TicketFilterSchema = createFilterSchema({\n * // Top-level document fields that can be selected\n * selectableFields: [\n * '_id',\n * 'ticketId',\n * 'type',\n * 'status',\n * 'createdAt',\n * 'updatedAt',\n * ] as const,\n *\n * // Each populate path has its own allowed select fields\n * populatableFields: {\n * chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n * client: ['_id', 'name', 'profilePhoto', 'type'] as const,\n * admin: ['_id', 'name', 'profilePhoto'] as const,\n * order: ['_id', 'orderId', 'shop', 'total'] as const,\n * } as const,\n *\n * searchableFields: ['ticketId'] as const,\n *\n * queryableFields: {\n * status: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n * type: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n * client: z.string(),\n * clientType: z.enum(['USER', 'SHOP']),\n * },\n * });\n *\n * type TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n *\n * // ✅ VALID EXAMPLES\n *\n * // Example 1: Select only top-level fields\n * const filter1: TicketFilterDTO = {\n * select: { ticketId: 1, status: 1, createdAt: 1 },\n * query: { status: 'OPEN' },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 2: Populate client with specific fields\n * const filter2: TicketFilterDTO = {\n * populate: {\n * path: 'client',\n * select: { name: 1, profilePhoto: 1 }, // Uses client's allowed fields\n * },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 3: Populate multiple relations\n * const filter3: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } },\n * { path: 'order', select: { orderId: 1, total: 1 } },\n * { path: 'chatroom', select: { lastMessage: 1, unreadCount: 1 } },\n * ],\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 4: Complex query with search\n * const filter4: TicketFilterDTO = {\n * query: { status: 'OPEN', type: 'ORDER' },\n * search: { searchKey: 'TKT-123', searchFields: ['ticketId'] },\n * populate: { path: 'client', select: { name: 1 } },\n * sort: { createdAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 5: Populate with match and options\n * const filter5: TicketFilterDTO = {\n * populate: {\n * path: 'order',\n * select: { orderId: 1, shop: 1 },\n * match: { status: 'DELIVERED' },\n * options: { sort: { createdAt: -1 }, limit: 10 },\n * },\n * page: 1,\n * size: 20,\n * };\n *\n * // ❌ INVALID EXAMPLES (TypeScript will reject)\n *\n * const invalid1: TicketFilterDTO = {\n * select: { invalidField: 1 }, // ❌ not in selectableFields\n * };\n *\n * const invalid2: TicketFilterDTO = {\n * populate: {\n * path: 'client',\n * select: { email: 1 }, // ❌ email not in client's populatableFields\n * },\n * };\n *\n * const invalid3: TicketFilterDTO = {\n * populate: {\n * path: 'invalidPath', // ❌ path doesn't exist\n * select: { name: 1 },\n * },\n * };\n *\n * const invalid4: TicketFilterDTO = {\n * query: { status: 'INVALID_STATUS' }, // ❌ not in enum\n * }\n */"]}
1
+ {"version":3,"file":"filter-schema.factory.js","sourceRoot":"/","sources":["utilities/validation/filter-schema.factory.ts"],"names":[],"mappings":"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","sourcesContent":["import { z, ZodTypeAny } from 'zod';\n\ntype ReadonlyNonEmptyArray<T> = readonly [T, ...T[]];\n\nexport interface FilterSchemaConfig<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n> {\n\tselectableFields?: TSelect;\n\tpopulatableFields?: TPopulate;\n\tsearchableFields?: TSearch;\n\tqueryableFields?: TQuery;\n\tsortableFields?: TSort;\n\tmaxSize?: number;\n\tdefaultSize?: number;\n}\n\n// Populate object type\nexport type PopulateObject<TPath extends string, TSelectFields extends ReadonlyNonEmptyArray<string>> = {\n\tpath: TPath;\n\tselect?: Partial<Record<TSelectFields[number], 0 | 1>>;\n\tmatch?: Record<string, any>;\n\toptions?: { sort?: Record<string, 1 | -1>; limit?: number; skip?: number };\n};\n\n// Union of all possible populate objects based on populatableFields\ntype PopulateUnion<TPopulate extends Record<string, ReadonlyNonEmptyArray<string>>> = {\n\t[K in keyof TPopulate]: PopulateObject<K & string, TPopulate[K]>;\n}[keyof TPopulate];\n\n// DTO type\nexport type FilterDTO<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n> = {\n\tsize?: number;\n\tpage?: number;\n\tsort?: TSort extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSort[number], 1 | -1>> : never;\n\tselect?: TSelect extends ReadonlyNonEmptyArray<string> ? Partial<Record<TSelect[number], 0 | 1>> : never;\n\tpopulate?: PopulateUnion<TPopulate>[];\n\tsearch?: TSearch extends ReadonlyNonEmptyArray<string>\n\t\t? { searchKey: string; searchFields?: TSearch[number][] }\n\t\t: never;\n\tquery?: { [K in keyof TQuery]?: z.infer<TQuery[K]> };\n};\n\nconst sortSchema = z.record(z.string(), z.union([z.literal(1), z.literal(-1)]));\n\nexport function createFilterSchema<\n\tTSelect extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTPopulate extends Record<string, ReadonlyNonEmptyArray<string>> | {} = {},\n\tTSearch extends ReadonlyNonEmptyArray<string> | [] = [],\n\tTQuery extends Record<string, ZodTypeAny> = {},\n\tTSort extends ReadonlyNonEmptyArray<string> | [] = [],\n>(config: FilterSchemaConfig<TSelect, TPopulate, TSearch, TQuery, TSort>) {\n\tconst {\n\t\tselectableFields,\n\t\tpopulatableFields,\n\t\tsearchableFields,\n\t\tqueryableFields,\n\t\tsortableFields,\n\t\tmaxSize = 100,\n\t\tdefaultSize = 10,\n\t} = config;\n\n\tconst populateKeys = populatableFields ? (Object.keys(populatableFields) as (keyof TPopulate)[]) : [];\n\n\tconst schemaShape: Record<string, any> = {\n\t\tsize: z.number().min(1).max(maxSize).optional().default(defaultSize),\n\t\tpage: z.number().min(1).optional().default(1),\n\t};\n\n\t// Sort with allowed fields\n\tif (sortableFields?.length) {\n\t\tschemaShape.sort = z\n\t\t\t.record(z.enum([...sortableFields] as [string, ...string[]]), z.union([z.literal(1), z.literal(-1)]))\n\t\t\t.optional();\n\t}\n\n\t// Top-level select\n\tif (selectableFields?.length) {\n\t\tschemaShape.select = z\n\t\t\t.record(z.enum([...selectableFields] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t.optional();\n\t}\n\n\t// Populate as array of objects with strict typing per path\n\tif (populateKeys.length) {\n\t\tconst populateSchemas: ZodTypeAny[] = [];\n\n\t\tfor (const path of populateKeys) {\n\t\t\tconst allowedSelects = populatableFields![path] as ReadonlyNonEmptyArray<string>;\n\n\t\t\tconst populateSchema = z.object({\n\t\t\t\tpath: z.literal(path as string),\n\t\t\t\tselect: z\n\t\t\t\t\t.record(z.enum([...allowedSelects] as [string, ...string[]]), z.union([z.literal(0), z.literal(1)]))\n\t\t\t\t\t.optional(),\n\t\t\t\tmatch: z.record(z.string(), z.any()).optional(),\n\t\t\t\toptions: z\n\t\t\t\t\t.object({\n\t\t\t\t\t\tsort: sortSchema.optional(),\n\t\t\t\t\t\tlimit: z.number().optional(),\n\t\t\t\t\t\tskip: z.number().optional(),\n\t\t\t\t\t})\n\t\t\t\t\t.optional(),\n\t\t\t});\n\n\t\t\tpopulateSchemas.push(populateSchema);\n\t\t}\n\n\t\tconst unionSchema =\n\t\t\tpopulateSchemas.length === 1\n\t\t\t\t? populateSchemas[0]\n\t\t\t\t: z.union(populateSchemas as [ZodTypeAny, ZodTypeAny, ...ZodTypeAny[]]);\n\n\t\tschemaShape.populate = z.array(unionSchema).optional();\n\t}\n\n\t// Search\n\tif (searchableFields?.length) {\n\t\tschemaShape.search = z\n\t\t\t.object({\n\t\t\t\tsearchKey: z.string(),\n\t\t\t\tsearchFields: z.array(z.enum([...searchableFields] as [string, ...string[]])).optional(),\n\t\t\t})\n\t\t\t.optional();\n\t}\n\n\t// Query\n\tif (queryableFields && Object.keys(queryableFields).length) {\n\t\tconst queryShape: Record<string, ZodTypeAny> = {};\n\t\tfor (const key in queryableFields) {\n\t\t\tqueryShape[key] = queryableFields[key].optional();\n\t\t}\n\t\tschemaShape.query = z.object(queryShape).optional();\n\t}\n\n\treturn z.object(schemaShape) as z.ZodType<FilterDTO<TSelect, TPopulate, TSearch, TQuery, TSort>>;\n}\n\nconst TicketFilterSchema = createFilterSchema({\n\t// Top-level document fields that can be selected\n\tselectableFields: ['_id', 'ticketId', 'type', 'status', 'createdAt', 'updatedAt'] as const,\n\n\t// Each populate path has its own allowed select fields\n\tpopulatableFields: {\n\t\tchatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n\t\tclient: ['_id', 'name', 'profilePhoto', 'type'] as const,\n\t\tadmin: ['_id', 'name', 'profilePhoto'] as const,\n\t\torder: ['_id', 'orderId', 'shop', 'total'] as const,\n\t} as const,\n\n\tsearchableFields: ['ticketId'] as const,\n\n\tsortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'] as const,\n\n\tqueryableFields: {\n\t\tstatus: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n\t\ttype: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n\t\tclient: z.string(),\n\t\tclientType: z.enum(['USER', 'SHOP']),\n\t},\n});\n\ntype TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n\nconst ticket: TicketFilterDTO = {\n\tsort: { createdAt: -1, status: 1 }, // ✅ Only allowed fields with 1 or -1\n};\n\n/**\n * EXAMPLE USAGE\n *\n * const TicketFilterSchema = createFilterSchema({\n * selectableFields: [\n * '_id',\n * 'ticketId',\n * 'type',\n * 'status',\n * 'createdAt',\n * 'updatedAt',\n * ] as const,\n *\n * populatableFields: {\n * chatroom: ['_id', 'lastMessage', 'participants', 'unreadCount'] as const,\n * client: ['_id', 'name', 'profilePhoto', 'type'] as const,\n * admin: ['_id', 'name', 'profilePhoto'] as const,\n * order: ['_id', 'orderId', 'shop', 'total'] as const,\n * } as const,\n *\n * searchableFields: ['ticketId'] as const,\n *\n * sortableFields: ['createdAt', 'updatedAt', 'ticketId', 'status'] as const,\n *\n * queryableFields: {\n * status: z.enum(['OPEN', 'CLOSED', 'PENDING']),\n * type: z.enum(['ORDER', 'GENERAL', 'COMPLAINT']),\n * client: z.string(),\n * clientType: z.enum(['USER', 'SHOP']),\n * },\n * });\n *\n * type TicketFilterDTO = z.infer<typeof TicketFilterSchema>;\n *\n * // ✅ VALID EXAMPLES\n *\n * // Example 1: Sort by allowed fields\n * const filter1: TicketFilterDTO = {\n * sort: { createdAt: -1, status: 1 },\n * query: { status: 'OPEN' },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 2: Populate client with specific fields\n * const filter2: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } }\n * ],\n * sort: { updatedAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 3: Populate multiple relations with sort\n * const filter3: TicketFilterDTO = {\n * populate: [\n * { path: 'client', select: { name: 1, profilePhoto: 1 } },\n * { path: 'order', select: { orderId: 1, total: 1 } },\n * { path: 'chatroom', select: { lastMessage: 1, unreadCount: 1 } },\n * ],\n * sort: { createdAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 4: Complex query with search and sort\n * const filter4: TicketFilterDTO = {\n * query: { status: 'OPEN', type: 'ORDER' },\n * search: { searchKey: 'TKT-123', searchFields: ['ticketId'] },\n * populate: [{ path: 'client', select: { name: 1 } }],\n * sort: { createdAt: -1, ticketId: 1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // Example 5: Populate with match and options\n * const filter5: TicketFilterDTO = {\n * populate: [\n * {\n * path: 'order',\n * select: { orderId: 1, shop: 1 },\n * match: { status: 'DELIVERED' },\n * options: { sort: { createdAt: -1 }, limit: 10 },\n * }\n * ],\n * sort: { updatedAt: -1 },\n * page: 1,\n * size: 20,\n * };\n *\n * // ❌ INVALID EXAMPLES (TypeScript will reject)\n *\n * const invalid1: TicketFilterDTO = {\n * sort: { invalidField: 1 }, // ❌ not in sortableFields\n * };\n *\n * const invalid2: TicketFilterDTO = {\n * sort: { createdAt: 2 }, // ❌ must be 1 or -1\n * };\n *\n * const invalid3: TicketFilterDTO = {\n * populate: [\n * {\n * path: 'client',\n * select: { email: 1 }, // ❌ email not in client's populatableFields\n * }\n * ],\n * };\n *\n * const invalid4: TicketFilterDTO = {\n * query: { status: 'INVALID_STATUS' }, // ❌ not in enum\n * }\n */\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lyxa.ai/core",
3
- "version": "1.1.67",
3
+ "version": "1.1.69",
4
4
  "description": "The Core system of the Lyxa services.",
5
5
  "author": "elie <42282499+Internalizable@users.noreply.github.com>",
6
6
  "license": "MIT",