@solidxai/core 0.1.11-beta.9 → 0.1.12-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +456 -0
- package/dist/controllers/authentication.controller.d.ts +1 -1
- package/dist/controllers/chatter-message.controller.d.ts +0 -2
- package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
- package/dist/controllers/chatter-message.controller.js +0 -16
- package/dist/controllers/chatter-message.controller.js.map +1 -1
- package/dist/controllers/datasource-introspection.controller.d.ts +8 -0
- package/dist/controllers/datasource-introspection.controller.d.ts.map +1 -1
- package/dist/controllers/media.controller.js +0 -2
- package/dist/controllers/media.controller.js.map +1 -1
- package/dist/guards/access-token.guard.d.ts +5 -1
- package/dist/guards/access-token.guard.d.ts.map +1 -1
- package/dist/guards/access-token.guard.js +31 -3
- package/dist/guards/access-token.guard.js.map +1 -1
- package/dist/guards/authentication.guard.d.ts +1 -0
- package/dist/guards/authentication.guard.d.ts.map +1 -1
- package/dist/guards/authentication.guard.js +16 -1
- package/dist/guards/authentication.guard.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
- package/dist/helpers/bootstrap.helper.js +3 -1
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/helpers/environment.helper.d.ts +0 -1
- package/dist/helpers/environment.helper.d.ts.map +1 -1
- package/dist/helpers/environment.helper.js +0 -4
- package/dist/helpers/environment.helper.js.map +1 -1
- package/dist/helpers/model-metadata-helper.service.d.ts +1 -2
- package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
- package/dist/helpers/model-metadata-helper.service.js +2 -6
- package/dist/helpers/model-metadata-helper.service.js.map +1 -1
- package/dist/helpers/module-metadata-helper.service.js +1 -1
- package/dist/helpers/module-metadata-helper.service.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +19 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/helpers/solid-registry.d.ts +1 -2
- package/dist/helpers/solid-registry.d.ts.map +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/interfaces/active-user-data.interface.d.ts +1 -0
- package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
- package/dist/interfaces/active-user-data.interface.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/repository/scheduled-job.repository.d.ts +2 -2
- package/dist/repository/scheduled-job.repository.d.ts.map +1 -1
- package/dist/repository/scheduled-job.repository.js +3 -6
- package/dist/repository/scheduled-job.repository.js.map +1 -1
- package/dist/repository/security-rule.repository.d.ts +2 -2
- package/dist/repository/security-rule.repository.d.ts.map +1 -1
- package/dist/repository/security-rule.repository.js +3 -6
- package/dist/repository/security-rule.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +18 -1
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +62 -34
- package/dist/services/active-session-storage.service.d.ts +10 -0
- package/dist/services/active-session-storage.service.d.ts.map +1 -0
- package/dist/services/active-session-storage.service.js +41 -0
- package/dist/services/active-session-storage.service.js.map +1 -0
- package/dist/services/authentication.service.d.ts +8 -3
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +61 -16
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +2 -0
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +25 -2
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +5 -7
- package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +7 -0
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +1 -0
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/datasource-introspection.service.d.ts +10 -0
- package/dist/services/datasource-introspection.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection.service.js +109 -17
- package/dist/services/datasource-introspection.service.js.map +1 -1
- package/dist/services/menu-item-metadata.service.d.ts.map +1 -1
- package/dist/services/menu-item-metadata.service.js +1 -0
- package/dist/services/menu-item-metadata.service.js.map +1 -1
- package/dist/services/model-metadata.service.d.ts +2 -0
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +49 -16
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +0 -28
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/refresh-token-ids-storage.service.d.ts +6 -1
- package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
- package/dist/services/refresh-token-ids-storage.service.js +0 -2
- package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +230 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +116 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/solid-ts-morph.service.d.ts +6 -0
- package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
- package/dist/services/solid-ts-morph.service.js +43 -0
- package/dist/services/solid-ts-morph.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +2 -0
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/audit.subscriber.d.ts.map +1 -1
- package/dist/subscribers/audit.subscriber.js +2 -8
- package/dist/subscribers/audit.subscriber.js.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.d.ts +0 -8
- package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
- package/dist/subscribers/computed-entity-field.subscriber.js +3 -36
- package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.d.ts.map +1 -1
- package/dist/subscribers/created-by-updated-by.subscriber.js.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.d.ts.map +1 -1
- package/dist/subscribers/field-metadata.subscriber.js.map +1 -1
- package/dist/subscribers/scheduled-job.subscriber.d.ts.map +1 -1
- package/dist/subscribers/scheduled-job.subscriber.js +2 -3
- package/dist/subscribers/scheduled-job.subscriber.js.map +1 -1
- package/dist/subscribers/security-rule.subscriber.d.ts.map +1 -1
- package/dist/subscribers/security-rule.subscriber.js +3 -5
- package/dist/subscribers/security-rule.subscriber.js.map +1 -1
- package/package.json +1 -1
- package/src/controllers/chatter-message.controller.ts +7 -7
- package/src/controllers/media.controller.ts +1 -1
- package/src/guards/access-token.guard.ts +43 -3
- package/src/guards/authentication.guard.ts +22 -1
- package/src/helpers/bootstrap.helper.ts +9 -3
- package/src/helpers/environment.helper.ts +0 -11
- package/src/helpers/model-metadata-helper.service.ts +2 -7
- package/src/helpers/module-metadata-helper.service.ts +1 -1
- package/src/helpers/solid-core-error-codes-provider.service.ts +20 -1
- package/src/helpers/solid-registry.ts +1 -7
- package/src/index.ts +1 -1
- package/src/interfaces/active-user-data.interface.ts +6 -0
- package/src/interfaces.ts +1 -0
- package/src/repository/scheduled-job.repository.ts +4 -10
- package/src/repository/security-rule.repository.ts +4 -10
- package/src/seeders/module-metadata-seeder.service.ts +23 -2
- package/src/seeders/seed-data/solid-core-metadata.json +62 -34
- package/src/services/active-session-storage.service.ts +24 -0
- package/src/services/authentication.service.ts +76 -15
- package/src/services/chatter-message.service.ts +32 -2
- package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +5 -11
- package/src/services/crud-helper.service.ts +7 -0
- package/src/services/crud.service.ts +1 -0
- package/src/services/datasource-introspection.service.ts +176 -16
- package/src/services/menu-item-metadata.service.ts +2 -1
- package/src/services/model-metadata.service.ts +63 -22
- package/src/services/module-metadata.service.ts +0 -36
- package/src/services/refresh-token-ids-storage.service.ts +9 -8
- package/src/services/settings/default-settings-provider.service.ts +116 -1
- package/src/services/solid-ts-morph.service.ts +61 -1
- package/src/solid-core.module.ts +2 -0
- package/src/subscribers/audit.subscriber.ts +2 -11
- package/src/subscribers/computed-entity-field.subscriber.ts +6 -63
- package/src/subscribers/created-by-updated-by.subscriber.ts +0 -3
- package/src/subscribers/field-metadata.subscriber.ts +0 -3
- package/src/subscribers/scheduled-job.subscriber.ts +2 -3
- package/src/subscribers/security-rule.subscriber.ts +3 -8
- package/dist/helpers/nodemon-heartbeat.d.ts +0 -5
- package/dist/helpers/nodemon-heartbeat.d.ts.map +0 -1
- package/dist/helpers/nodemon-heartbeat.js +0 -67
- package/dist/helpers/nodemon-heartbeat.js.map +0 -1
- package/src/helpers/nodemon-heartbeat.ts +0 -59
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAA2D;AAC3D,4FAAuF;AACvF,4DAAuD;AACvD,8DAA2D;AAG3D,sEAA8D;AAC9D,iFAA6E;AAC7E,4FAAiF;AACjF,MAAM,qBAAqB,GAAG,uBAAuB,CAAC;AAG/C,IAAM,eAAe,uBAArB,MAAM,eAAe;IAGxB,YACqB,gBAAqD,EACrD,aAA4B,EAC5B,qBAA4C,EAC5C,0BAAsD;QAHtD,qBAAgB,GAAhB,gBAAgB,CAAqC;QACrD,kBAAa,GAAb,aAAa,CAAe;QAC5B,0BAAqB,GAArB,qBAAqB,CAAuB;QAC5C,+BAA0B,GAA1B,0BAA0B,CAA4B;QAN1D,WAAM,GAAG,IAAI,eAAM,CAAC,iBAAe,CAAC,IAAI,CAAC,CAAC;QAenD,WAAM,GAAG,IAAI,OAAO,EAA4B,CAAC;IARrD,CAAC;IAEL,gBAAgB,CAAC,UAAsB;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAKO,OAAO,CAAC,KAA2B,EAAE,OAA0B;QACnE,MAAM,EAAE,GAAG,KAAK,CAAC,WAAW,CAAC;QAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC;QACtC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAClB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAC7B,CAAC;IAEO,gBAAgB,CAAC,QAAwB;QAC7C,OAAO,IAAI,CAAC,aAAa,CAAC,gBAAgB,CAAC,IAAA,0BAAU,EAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC1E,CAAC;IAEO,YAAY;QAChB,OAAO,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,EAAE,GAAG,IAAI,IAAI,CAAC;IACnE,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAuB;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO;QACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YAChB,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;YAC9B,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,IAAI;YAClC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,KAAK,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;YAC3B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE;SAC9B,CAAC,CAAC;IACP,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAuB;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO;QACnD,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,IAAI,KAAK,CAAC,cAAc,EAAE,EAAE,IAAK,KAAa,CAAC,QAAQ,IAAI,IAAI,CAAC;QACjG,IAAI,MAAM,GAAG,KAAK,CAAC,cAAc,IAAI,IAAI,CAAC;QAC1C,IAAI,KAAK,GAAG,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC;QACjC,MAAM,kBAAkB,GAAG,CAAC,KAAK,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;QAEjF,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,oCAAoC,CAAC,KAAK,EAAE,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAEzG,IAAI,WAAW,EAAE,CAAC;YACd,MAAM,GAAG,WAAW,CAAC,MAAM,CAAC;YAC5B,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC;QAC9B,CAAC;QAED,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YAChB,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;YAC9B,QAAQ,EAAE,QAAQ;YAClB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,KAAK,EAAE,KAAK;YAGZ,MAAM,EAAE,MAAM;YACd,kBAAkB,EAAE,kBAAkB;YACtC,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE;SAC9B,CAAC,CAAC;IACP,CAAC;IAMO,KAAK,CAAC,oCAAoC,CAAC,KAAuB,EAAE,QAAuB,EAAE,kBAA4B;QAI7H,MAAM,GAAG,GAAG,IAAA,iCAAY,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC;QAC7D,MAAM,mBAAmB,GAAG,CAAC,MAAM,IAAI,CAAC,0BAA0B,CAAC,kBAAkB,CAAC,IAAA,0BAAU,EAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAA,iCAAY,GAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAC/K,KAAK,CAAC,mBAAmB;YACzB,KAAK,CAAC,IAAI,KAAK,UAAU;YACzB,KAAK,CAAC,YAAY,KAAK,aAAa,CACvC,CAAC;QAEF,IAAI,CAAC,QAAQ,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAChD,OAAO,IAAI,CAAC;QAChB,CAAC;QAED,MAAM,SAAS,GAA4B,EAAE,CAAC;QAE9C,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;YAChC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;QACjC,CAAC,CAAC,CAAC;QAEH,MAAM,cAAc,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,qBAAqB,CAAC,IAAI,IAAI,CAAC;QAErE,MAAM,aAAa,GAAG,MAAM,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAa,CAAC,CAAC,OAAO,CAAC;YAChF,KAAK,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAS;YAC9B,SAAS,EAAE,SAAgB;SAC9B,CAAC,CAAC;QAEH,IAAI,cAAc,IAAI,aAAa,EAAE,CAAC;YAClC,mBAAmB,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;gBAChC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACpD,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;oBACxD,CAAC,CAAC,EAAE,CAAC;gBAET,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBACnD,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;oBACvD,CAAC,CAAC,EAAE,CAAC;gBAET,IAAI,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;uBACnF,CAAC,kBAAkB,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC9C,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACxC,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC;QACD,OAAO;YACH,MAAM,EAAE,cAAc,IAAI,KAAK,CAAC,cAAc,IAAI,IAAI;YACtD,KAAK,EAAE,aAAa,IAAI,KAAK,CAAC,MAAM,IAAI,IAAI;SAC/C,CAAC;IACN,CAAC;IACD,KAAK,CAAC,WAAW,CAAC,KAAuB;QACrC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,CAAC;YAAE,OAAO;QACnD,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;YAChB,SAAS,EAAE,QAAQ;YACnB,SAAS,EAAE,KAAK,CAAC,QAAQ,CAAC,IAAI;YAC9B,QAAQ,EAAE,KAAK,CAAC,cAAc,EAAE,EAAE,IAAI,IAAI;YAC1C,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACpC,MAAM,EAAE,KAAK,CAAC,cAAc;YAC5B,MAAM,EAAE,IAAI,CAAC,YAAY,EAAE;SAC9B,CAAC,CAAC;IACP,CAAC;IAGD,KAAK,CAAC,sBAAsB,CAAC,KAA2B;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAE/B,IAAI,IAAA,iCAAY,GAAE,EAAE,CAAC;YACjB,YAAY,CAAC,GAAG,EAAE,CAAC,KAAK,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;YACvD,OAAO;QACX,CAAC;QAED,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,wBAAwB,CAAC,KAA2B;QAEhD,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;IAEO,KAAK,CAAC,iBAAiB,CAAC,KAA0B;QACtD,IAAI,CAAC;YAED,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CACpC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,EAAE,uBAAuB,CAAC,CAAC,CAC5F,CAAC;YAEF,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;gBAC1B,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;oBAC/B,IAAI,CAAC,MAAM,CAAC,KAAK,CACb,qCAAqC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,EAAE,EAC9E,MAAM,CAAC,MAAM,CAChB,CAAC;gBACN,CAAC;YACL,CAAC,CAAC,CAAC;QACP,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;IACL,CAAC;CACJ,CAAA;AAjLY,0CAAe;0BAAf,eAAe;IAD3B,IAAA,mBAAU,EAAC,EAAE,KAAK,EAAE,cAAK,CAAC,SAAS,EAAE,CAAC;qCAKI,4CAAgB;QACnB,8BAAa;QACL,+CAAqB;QAChB,0DAA0B;GAPlE,eAAe,CAiL3B","sourcesContent":["import { Injectable, Logger, Scope } from '@nestjs/common';\nimport { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\nimport { lowerFirst } from 'src/helpers/string.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\nimport { AuditQueuePayload } from 'src/interfaces';\nimport { isEmbeddedDb } from 'src/helpers/environment.helper';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport { PublisherFactory } from 'src/services/queues/publisher-factory.service';\nconst AUDIT_BEFORE_SNAPSHOT = '__auditBeforeSnapshot';\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class AuditSubscriber implements EntitySubscriberInterface {\n private readonly logger = new Logger(AuditSubscriber.name);\n private dataSource: DataSource;\n constructor(\n private readonly publisherFactory: PublisherFactory<AuditQueuePayload>,\n private readonly solidRegistry: SolidRegistry,\n private readonly requestContextService: RequestContextService,\n private readonly modelMetadataHelperService: ModelMetadataHelperService,\n ) { }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n // Per-transaction buffer (auto-GC when queryRunner is gone)\n private perTxn = new WeakMap<any, AuditQueuePayload[]>();\n\n private enqueue(event: { queryRunner: any }, payload: AuditQueuePayload) {\n const qr = event.queryRunner;\n const arr = this.perTxn.get(qr) ?? [];\n arr.push(payload);\n this.perTxn.set(qr, arr);\n }\n\n private shouldTrackAudit(metadata: EntityMetadata): boolean {\n return this.solidRegistry.isAuditableModel(lowerFirst(metadata.name));\n }\n\n private activeUserId(): number | null {\n return this.requestContextService.getActiveUser()?.sub ?? null;\n }\n\n async afterInsert(event: InsertEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n this.enqueue(event, {\n eventType: 'insert',\n modelName: event.metadata.name,\n entityId: event.entity?.id ?? null,\n occurredAt: new Date().toISOString(),\n after: event.entity ?? null,\n userId: this.activeUserId(),\n });\n }\n\n async afterUpdate(event: UpdateEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n const entityId = event.entity?.id ?? event.databaseEntity?.id ?? (event as any).entityId ?? null;\n let before = event.databaseEntity ?? null;\n let after = event.entity ?? null;\n const updatedColumnNames = (event.updatedColumns ?? []).map(c => c.propertyName);\n\n const auditResult = await this.prepareManyToManyAuditUpdateSnapshot(event, entityId, updatedColumnNames);\n\n if (auditResult) {\n before = auditResult.before;\n after = auditResult.after;\n }\n\n this.enqueue(event, {\n eventType: 'update',\n modelName: event.metadata.name,\n entityId: entityId,\n occurredAt: new Date().toISOString(),\n after: after,\n // databaseEntity is only populated when the entity was fetched first (save() path).\n // QueryBuilder update() leaves this undefined; postAuditMessageOnUpdate guards for it.\n before: before,\n updatedColumnNames: updatedColumnNames,\n userId: this.activeUserId(),\n });\n }\n\n /**\n * Resolves before/after snapshots for audit-enabled many-to-many relations\n * and updates changed relation field names for audit tracking.\n */\n private async prepareManyToManyAuditUpdateSnapshot(event: UpdateEvent<any>, entityId: number | null, updatedColumnNames: string[]): Promise<{ before: any; after: any } | null> {\n\n // On embedded PGlite, pass the transaction's manager so the query runs\n // on the active connection. On regular Postgres, use the default DataSource.\n const mgr = isEmbeddedDb() ? event.manager : this.dataSource;\n const auditRelationFields = (await this.modelMetadataHelperService.loadFieldHierarchy(lowerFirst(event.metadata.name), isEmbeddedDb() ? event.manager : undefined)).filter(field =>\n field.enableAuditTracking &&\n field.type === 'relation' &&\n field.relationType !== 'one-to-many'\n );\n\n if (!entityId || auditRelationFields.length === 0) {\n return null;\n }\n\n const relations: Record<string, boolean> = {};\n\n auditRelationFields.forEach(field => {\n relations[field.name] = true;\n });\n\n const relationBefore = event.entity?.[AUDIT_BEFORE_SNAPSHOT] ?? null;\n\n const relationAfter = await mgr.getRepository(event.metadata.target as any).findOne({\n where: { id: entityId } as any,\n relations: relations as any,\n });\n\n if (relationBefore && relationAfter) {\n auditRelationFields.forEach(field => {\n const oldIds = Array.isArray(relationBefore[field.name])\n ? relationBefore[field.name].map(item => item.id).sort()\n : [];\n\n const newIds = Array.isArray(relationAfter[field.name])\n ? relationAfter[field.name].map(item => item.id).sort()\n : [];\n\n if ((oldIds.length !== newIds.length || JSON.stringify(oldIds) !== JSON.stringify(newIds))\n && !updatedColumnNames.includes(field.name)) {\n updatedColumnNames.push(field.name);\n }\n });\n }\n return {\n before: relationBefore ?? event.databaseEntity ?? null,\n after: relationAfter ?? event.entity ?? null,\n };\n }\n async afterRemove(event: RemoveEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n this.enqueue(event, {\n eventType: 'delete',\n modelName: event.metadata.name,\n entityId: event.databaseEntity?.id ?? null,\n occurredAt: new Date().toISOString(),\n before: event.databaseEntity,\n userId: this.activeUserId(),\n });\n }\n\n // --------- transaction lifecycle ----------\n async afterTransactionCommit(event: { queryRunner: any }) {\n const batch = this.perTxn.get(event.queryRunner) ?? [];\n this.perTxn.delete(event.queryRunner);\n\n if (batch.length === 0) return;\n\n if (isEmbeddedDb()) {\n setImmediate(() => void this.publishAuditBatch(batch));\n return;\n }\n\n await this.publishAuditBatch(batch);\n }\n\n afterTransactionRollback(event: { queryRunner: any }) {\n // Drop buffered payloads; the write never happened.\n this.perTxn.delete(event.queryRunner);\n }\n\n private async publishAuditBatch(batch: AuditQueuePayload[]) {\n try {\n // allSettled: publish in parallel; a single failure does not block the rest.\n const results = await Promise.allSettled(\n batch.map(payload => this.publisherFactory.publish({ payload }, 'ChatterQueuePublisher'))\n );\n\n results.forEach((result, i) => {\n if (result.status === 'rejected') {\n this.logger.error(\n `Failed to publish audit event for ${batch[i].modelName}#${batch[i].entityId}`,\n result.reason,\n );\n }\n });\n } catch (error) {\n this.logger.error('Failed to publish audit batch', error);\n }\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"audit.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/audit.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger, Scope } from '@nestjs/common';\nimport { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\nimport { lowerFirst } from 'src/helpers/string.helper';\nimport { SolidRegistry } from 'src/helpers/solid-registry';\nimport { DataSource, EntityMetadata, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from 'typeorm';\nimport { AuditQueuePayload } from 'src/interfaces';\nimport { RequestContextService } from 'src/services/request-context.service';\nimport { PublisherFactory } from 'src/services/queues/publisher-factory.service';\nconst AUDIT_BEFORE_SNAPSHOT = '__auditBeforeSnapshot';\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class AuditSubscriber implements EntitySubscriberInterface {\n private readonly logger = new Logger(AuditSubscriber.name);\n private dataSource: DataSource;\n constructor(\n private readonly publisherFactory: PublisherFactory<AuditQueuePayload>,\n private readonly solidRegistry: SolidRegistry,\n private readonly requestContextService: RequestContextService,\n private readonly modelMetadataHelperService: ModelMetadataHelperService,\n ) { }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n // Per-transaction buffer (auto-GC when queryRunner is gone)\n private perTxn = new WeakMap<any, AuditQueuePayload[]>();\n\n private enqueue(event: { queryRunner: any }, payload: AuditQueuePayload) {\n const qr = event.queryRunner;\n const arr = this.perTxn.get(qr) ?? [];\n arr.push(payload);\n this.perTxn.set(qr, arr);\n }\n\n private shouldTrackAudit(metadata: EntityMetadata): boolean {\n return this.solidRegistry.isAuditableModel(lowerFirst(metadata.name));\n }\n\n private activeUserId(): number | null {\n return this.requestContextService.getActiveUser()?.sub ?? null;\n }\n\n async afterInsert(event: InsertEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n this.enqueue(event, {\n eventType: 'insert',\n modelName: event.metadata.name,\n entityId: event.entity?.id ?? null,\n occurredAt: new Date().toISOString(),\n after: event.entity ?? null,\n userId: this.activeUserId(),\n });\n }\n\n async afterUpdate(event: UpdateEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n const entityId = event.entity?.id ?? event.databaseEntity?.id ?? (event as any).entityId ?? null;\n let before = event.databaseEntity ?? null;\n let after = event.entity ?? null;\n const updatedColumnNames = (event.updatedColumns ?? []).map(c => c.propertyName);\n\n const auditResult = await this.prepareManyToManyAuditUpdateSnapshot(event, entityId, updatedColumnNames);\n\n if (auditResult) {\n before = auditResult.before;\n after = auditResult.after;\n }\n\n this.enqueue(event, {\n eventType: 'update',\n modelName: event.metadata.name,\n entityId: entityId,\n occurredAt: new Date().toISOString(),\n after: after,\n // databaseEntity is only populated when the entity was fetched first (save() path).\n // QueryBuilder update() leaves this undefined; postAuditMessageOnUpdate guards for it.\n before: before,\n updatedColumnNames: updatedColumnNames,\n userId: this.activeUserId(),\n });\n }\n\n /**\n * Resolves before/after snapshots for audit-enabled many-to-many relations\n * and updates changed relation field names for audit tracking.\n */\n private async prepareManyToManyAuditUpdateSnapshot(event: UpdateEvent<any>, entityId: number | null, updatedColumnNames: string[]): Promise<{ before: any; after: any } | null> {\n\n const auditRelationFields = (await this.modelMetadataHelperService.loadFieldHierarchy(lowerFirst(event.metadata.name))).filter(field =>\n field.enableAuditTracking &&\n field.type === 'relation' &&\n field.relationType !== 'one-to-many'\n );\n\n if (!entityId || auditRelationFields.length === 0) {\n return null;\n }\n\n const relations: Record<string, boolean> = {};\n\n auditRelationFields.forEach(field => {\n relations[field.name] = true;\n });\n\n const relationBefore = event.entity?.[AUDIT_BEFORE_SNAPSHOT] ?? null;\n\n const relationAfter = await this.dataSource.getRepository(event.metadata.target as any).findOne({\n where: { id: entityId } as any,\n relations: relations as any,\n });\n\n if (relationBefore && relationAfter) {\n auditRelationFields.forEach(field => {\n const oldIds = Array.isArray(relationBefore[field.name])\n ? relationBefore[field.name].map(item => item.id).sort()\n : [];\n\n const newIds = Array.isArray(relationAfter[field.name])\n ? relationAfter[field.name].map(item => item.id).sort()\n : [];\n\n if ((oldIds.length !== newIds.length || JSON.stringify(oldIds) !== JSON.stringify(newIds))\n && !updatedColumnNames.includes(field.name)) {\n updatedColumnNames.push(field.name);\n }\n });\n }\n return {\n before: relationBefore ?? event.databaseEntity ?? null,\n after: relationAfter ?? event.entity ?? null,\n };\n }\n async afterRemove(event: RemoveEvent<any>) {\n if (!this.shouldTrackAudit(event.metadata)) return;\n this.enqueue(event, {\n eventType: 'delete',\n modelName: event.metadata.name,\n entityId: event.databaseEntity?.id ?? null,\n occurredAt: new Date().toISOString(),\n before: event.databaseEntity,\n userId: this.activeUserId(),\n });\n }\n\n // --------- transaction lifecycle ----------\n async afterTransactionCommit(event: { queryRunner: any }) {\n const batch = this.perTxn.get(event.queryRunner) ?? [];\n this.perTxn.delete(event.queryRunner);\n\n if (batch.length === 0) return;\n\n await this.publishAuditBatch(batch);\n }\n\n afterTransactionRollback(event: { queryRunner: any }) {\n // Drop buffered payloads; the write never happened.\n this.perTxn.delete(event.queryRunner);\n }\n\n private async publishAuditBatch(batch: AuditQueuePayload[]) {\n try {\n // allSettled: publish in parallel; a single failure does not block the rest.\n const results = await Promise.allSettled(\n batch.map(payload => this.publisherFactory.publish({ payload }, 'ChatterQueuePublisher'))\n );\n\n results.forEach((result, i) => {\n if (result.status === 'rejected') {\n this.logger.error(\n `Failed to publish audit event for ${batch[i].modelName}#${batch[i].entityId}`,\n result.reason,\n );\n }\n });\n } catch (error) {\n this.logger.error('Failed to publish audit batch', error);\n }\n }\n}\n"]}
|
|
@@ -9,7 +9,6 @@ export declare class ComputedEntityFieldSubscriber implements EntitySubscriberIn
|
|
|
9
9
|
private readonly publisherFactory;
|
|
10
10
|
private readonly logger;
|
|
11
11
|
private dataSource;
|
|
12
|
-
private perTxn;
|
|
13
12
|
constructor(solidRegistry: SolidRegistry, publisherFactory: PublisherFactory<ComputedFieldEvaluationPayload>);
|
|
14
13
|
bindToDataSource(dataSource: DataSource): void;
|
|
15
14
|
beforeInsert(event: InsertEvent<any>): Promise<any>;
|
|
@@ -18,13 +17,6 @@ export declare class ComputedEntityFieldSubscriber implements EntitySubscriberIn
|
|
|
18
17
|
afterUpdate(event: UpdateEvent<any>): void;
|
|
19
18
|
afterRemove(event: RemoveEvent<any>): void;
|
|
20
19
|
private handlePostEventJobs;
|
|
21
|
-
afterTransactionCommit(event: {
|
|
22
|
-
queryRunner: any;
|
|
23
|
-
}): Promise<void>;
|
|
24
|
-
afterTransactionRollback(event: {
|
|
25
|
-
queryRunner: any;
|
|
26
|
-
}): void;
|
|
27
|
-
private flushBatch;
|
|
28
20
|
private handleComputedFieldEvaluation;
|
|
29
21
|
private getComputedFieldsForEvaluation;
|
|
30
22
|
private evaluateComputedField;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed-entity-field.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/computed-entity-field.subscriber.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"computed-entity-field.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/computed-entity-field.subscriber.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAuB,MAAM,4BAA4B,CAAC;AAEvG,OAAO,EAAE,gBAAgB,EAAE,MAAM,+CAA+C,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAGvG,MAAM,WAAW,8BAA+B,SAAQ,qBAAqB;IACzE,cAAc,EAAE,GAAG,CAAC;CACvB;AAED,qBACa,6BAA8B,YAAW,yBAAyB;IAKvE,OAAO,CAAC,QAAQ,CAAC,aAAa;IAE9B,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IANrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAC5D,OAAO,CAAC,UAAU,CAAa;gBAGV,aAAa,EAAE,aAAa,EAE5B,gBAAgB,EAAE,gBAAgB,CAAC,8BAA8B,CAAC;IAIvF,gBAAgB,CAAC,UAAU,EAAE,UAAU;IAKjC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAMnD,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC;IAMzD,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAMnC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAMnC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAQnC,OAAO,CAAC,mBAAmB;YAwBb,6BAA6B;IAgB3C,OAAO,CAAC,8BAA8B;YASxB,qBAAqB;IAWnC,OAAO,CAAC,4BAA4B;YAetB,eAAe;IAY7B,OAAO,CAAC,iCAAiC;IAQzC,OAAO,CAAC,aAAa;IAWrB,OAAO,CAAC,oBAAoB;CA0B/B"}
|
|
@@ -16,7 +16,6 @@ exports.ComputedEntityFieldSubscriber = void 0;
|
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
17
|
const common_1 = require("@nestjs/common");
|
|
18
18
|
const create_field_metadata_dto_1 = require("../dtos/create-field-metadata.dto");
|
|
19
|
-
const environment_helper_1 = require("../helpers/environment.helper");
|
|
20
19
|
const solid_registry_1 = require("../helpers/solid-registry");
|
|
21
20
|
const publisher_factory_service_1 = require("../services/queues/publisher-factory.service");
|
|
22
21
|
let ComputedEntityFieldSubscriber = class ComputedEntityFieldSubscriber {
|
|
@@ -24,7 +23,6 @@ let ComputedEntityFieldSubscriber = class ComputedEntityFieldSubscriber {
|
|
|
24
23
|
this.solidRegistry = solidRegistry;
|
|
25
24
|
this.publisherFactory = publisherFactory;
|
|
26
25
|
this.logger = new common_1.Logger(this.constructor.name);
|
|
27
|
-
this.perTxn = new WeakMap();
|
|
28
26
|
}
|
|
29
27
|
bindToDataSource(dataSource) {
|
|
30
28
|
this.dataSource = dataSource;
|
|
@@ -55,42 +53,14 @@ let ComputedEntityFieldSubscriber = class ComputedEntityFieldSubscriber {
|
|
|
55
53
|
const eventContext = this.sanitizeEventContext(event, 'afterRemove');
|
|
56
54
|
this.handlePostEventJobs(event, event.databaseEntity, create_field_metadata_dto_1.ComputedFieldTriggerOperation.afterRemove, modelName, eventContext);
|
|
57
55
|
}
|
|
58
|
-
handlePostEventJobs(
|
|
56
|
+
handlePostEventJobs(_event, entity, currentOperation, modelName, eventContext) {
|
|
59
57
|
if (!entity)
|
|
60
58
|
return;
|
|
61
59
|
const computedFieldsTobeEvaluated = this.getComputedFieldsForEvaluation(this.solidRegistry.getComputedFieldMetadata(), currentOperation, modelName);
|
|
62
60
|
if (computedFieldsTobeEvaluated.length === 0)
|
|
63
61
|
return;
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
const arr = this.perTxn.get(qr) ?? [];
|
|
67
|
-
for (const computedField of computedFieldsTobeEvaluated) {
|
|
68
|
-
arr.push({
|
|
69
|
-
computedField: this.attachContext(computedField, eventContext),
|
|
70
|
-
databaseEntity: entity,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
this.perTxn.set(qr, arr);
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
for (const computedField of computedFieldsTobeEvaluated) {
|
|
77
|
-
this.enqueueComputedFieldEvaluationJob(this.attachContext(computedField, eventContext), entity);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
async afterTransactionCommit(event) {
|
|
82
|
-
const batch = this.perTxn.get(event.queryRunner) ?? [];
|
|
83
|
-
this.perTxn.delete(event.queryRunner);
|
|
84
|
-
if (batch.length === 0)
|
|
85
|
-
return;
|
|
86
|
-
setImmediate(() => void this.flushBatch(batch));
|
|
87
|
-
}
|
|
88
|
-
afterTransactionRollback(event) {
|
|
89
|
-
this.perTxn.delete(event.queryRunner);
|
|
90
|
-
}
|
|
91
|
-
async flushBatch(batch) {
|
|
92
|
-
for (const { computedField, databaseEntity } of batch) {
|
|
93
|
-
this.enqueueComputedFieldEvaluationJob(computedField, databaseEntity);
|
|
62
|
+
for (const computedField of computedFieldsTobeEvaluated) {
|
|
63
|
+
this.enqueueComputedFieldEvaluationJob(this.attachContext(computedField, eventContext), entity);
|
|
94
64
|
}
|
|
95
65
|
}
|
|
96
66
|
async handleComputedFieldEvaluation(entity, currentOperation, modelName, eventContext) {
|
|
@@ -141,10 +111,8 @@ let ComputedEntityFieldSubscriber = class ComputedEntityFieldSubscriber {
|
|
|
141
111
|
}
|
|
142
112
|
}
|
|
143
113
|
enqueueComputedFieldEvaluationJob(computedField, databaseEntity) {
|
|
144
|
-
const { manager: _manager, ...serializableEventContext } = computedField.eventContext ?? {};
|
|
145
114
|
const payload = {
|
|
146
115
|
...computedField,
|
|
147
|
-
eventContext: serializableEventContext,
|
|
148
116
|
databaseEntity,
|
|
149
117
|
};
|
|
150
118
|
this.publisherFactory.publish({ payload }, 'ComputedFieldEvaluationPublisher');
|
|
@@ -166,7 +134,6 @@ let ComputedEntityFieldSubscriber = class ComputedEntityFieldSubscriber {
|
|
|
166
134
|
const base = {
|
|
167
135
|
metadataName: event.metadata?.name,
|
|
168
136
|
eventType: eventType,
|
|
169
|
-
...((0, environment_helper_1.isEmbeddedDb)() ? { manager: event.manager } : {}),
|
|
170
137
|
};
|
|
171
138
|
if ("entityId" in event && event.entityId) {
|
|
172
139
|
base.entityId = event.entityId;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"computed-entity-field.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/computed-entity-field.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase } from 'lodash';\nimport { forwardRef, Inject, Injectable, InternalServerErrorException, Logger, Scope } from \"@nestjs/common\";\nimport { ComputedFieldTriggerOperation } from \"src/dtos/create-field-metadata.dto\";\nimport { isEmbeddedDb } from \"src/helpers/environment.helper\";\nimport { ComputedFieldMetadata, SolidRegistry, TypeOrmEventContext } from \"src/helpers/solid-registry\";\nimport { IEntityPreComputeFieldProvider } from \"src/interfaces\";\nimport { PublisherFactory } from \"src/services/queues/publisher-factory.service\";\nimport { DataSource, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from \"typeorm\";\n\n// Create an interface i.e ComputedFieldEvaluationPayload which has same fields as the ComputedFieldMetadata and an additional field for the database entity\nexport interface ComputedFieldEvaluationPayload extends ComputedFieldMetadata {\n databaseEntity: any;\n}\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class ComputedEntityFieldSubscriber implements EntitySubscriberInterface {\n private readonly logger = new Logger(this.constructor.name);\n private dataSource: DataSource;\n\n // Per-transaction buffer for post-event evaluation jobs. Entries are\n // flushed in afterTransactionCommit so the publish (which uses the\n // default DataSource) never races the in-flight transaction's connection.\n // On PGlite (pool size 1), the flush is deferred via setImmediate to\n // ensure the transaction's connection has been released first.\n private perTxn = new WeakMap<any, { computedField: ComputedFieldMetadata<any>; databaseEntity: any }[]>();\n\n constructor(\n private readonly solidRegistry: SolidRegistry,\n @Inject(forwardRef(() => PublisherFactory))\n private readonly publisherFactory: PublisherFactory<ComputedFieldEvaluationPayload>\n ) {\n }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n async beforeInsert(event: InsertEvent<any>): Promise<any> {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'beforeInsert');\n await this.handleComputedFieldEvaluation(event.entity, ComputedFieldTriggerOperation.beforeInsert, modelName, eventContext);\n }\n\n async beforeUpdate(event: UpdateEvent<any>): Promise<any> {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'beforeUpdate');\n await this.handleComputedFieldEvaluation(event.entity, ComputedFieldTriggerOperation.beforeUpdate, modelName, eventContext);\n }\n\n afterInsert(event: InsertEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterInsert');\n this.handlePostEventJobs(event, event.entity, ComputedFieldTriggerOperation.afterInsert, modelName, eventContext);\n }\n\n afterUpdate(event: UpdateEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? event.databaseEntity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterUpdate');\n this.handlePostEventJobs(event, event.entity, ComputedFieldTriggerOperation.afterUpdate, modelName, eventContext);\n }\n\n afterRemove(event: RemoveEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? event.databaseEntity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterRemove');\n this.handlePostEventJobs(event, event.databaseEntity, ComputedFieldTriggerOperation.afterRemove, modelName, eventContext);\n }\n\n //FIXME: Need to add support for beforeRemove, beforeSoftRemove, afterSoftRemove, beforeRecover, afterRecover\n\n // --------- post-event dispatch (pglite vs non-pglite) ----------\n\n /**\n * On embedded PGlite (pool size 1): buffer payloads on the queryRunner and\n * flush in afterTransactionCommit (deferred via setImmediate) so the publish\n * never tries to get a second connection while the transaction is active.\n *\n * On regular Postgres: fire-and-forget publish immediately (original behaviour),\n * since the pool has spare connections.\n */\n private handlePostEventJobs(\n event: InsertEvent<any> | UpdateEvent<any> | RemoveEvent<any>,\n entity: any,\n currentOperation: ComputedFieldTriggerOperation,\n modelName: string,\n eventContext?: TypeOrmEventContext,\n ) {\n if (!entity) return;\n\n const computedFieldsTobeEvaluated = this.getComputedFieldsForEvaluation(\n this.solidRegistry.getComputedFieldMetadata(),\n currentOperation,\n modelName\n );\n if (computedFieldsTobeEvaluated.length === 0) return;\n\n if (isEmbeddedDb()) {\n const qr = event.queryRunner;\n const arr = this.perTxn.get(qr) ?? [];\n for (const computedField of computedFieldsTobeEvaluated) {\n arr.push({\n computedField: this.attachContext(computedField, eventContext),\n databaseEntity: entity,\n });\n }\n this.perTxn.set(qr, arr);\n } else {\n for (const computedField of computedFieldsTobeEvaluated) {\n this.enqueueComputedFieldEvaluationJob(\n this.attachContext(computedField, eventContext),\n entity,\n );\n }\n }\n }\n\n // --------- transaction lifecycle (pglite only) ----------\n async afterTransactionCommit(event: { queryRunner: any }) {\n const batch = this.perTxn.get(event.queryRunner) ?? [];\n this.perTxn.delete(event.queryRunner);\n if (batch.length === 0) return;\n\n // Deferred via setImmediate so the transaction's connection is released\n // back to the (size-1) pool before the publish tries to acquire it.\n setImmediate(() => void this.flushBatch(batch));\n }\n\n afterTransactionRollback(event: { queryRunner: any }) {\n this.perTxn.delete(event.queryRunner);\n }\n\n private async flushBatch(batch: { computedField: ComputedFieldMetadata<any>; databaseEntity: any }[]) {\n for (const { computedField, databaseEntity } of batch) {\n this.enqueueComputedFieldEvaluationJob(computedField, databaseEntity);\n }\n }\n\n private async handleComputedFieldEvaluation(entity: any, currentOperation: ComputedFieldTriggerOperation, modelName: string, eventContext?: TypeOrmEventContext): Promise<void> {\n if (!entity) {\n return;\n }\n const computedFieldsTobeEvaluated = this.getComputedFieldsForEvaluation(\n this.solidRegistry.getComputedFieldMetadata(),\n currentOperation,\n modelName\n );\n for (const computedField of computedFieldsTobeEvaluated) {\n await this.evaluateComputedField(this.attachContext(computedField, eventContext), entity, currentOperation);\n }\n }\n\n // Based on the current model name and current operation, identify all the computed providers that need to be evaluated\n // Pass the database entity and the context to the provider of type IEntityComputedFieldProvider\n private getComputedFieldsForEvaluation(computedFieldMetadata: ComputedFieldMetadata[] = [], currentOperation: ComputedFieldTriggerOperation, currentModelName: string) {\n return computedFieldMetadata.filter(\n (computedField) => computedField.computedFieldTriggerConfig.some(\n (trigger) => trigger.operations.includes(currentOperation) &&\n trigger.modelName === currentModelName\n )\n );\n }\n\n private async evaluateComputedField(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any, currentOperation: ComputedFieldTriggerOperation) {\n // Skip pre-compute on insert when the payload already supplies the target field value.\n if (this.shouldSkipPreComputeOnInsert(computedFieldMetadata, entity, currentOperation)) {\n return;\n }\n const computedValue = await this.preComputeValue(computedFieldMetadata, entity);\n if (computedValue) {\n entity[computedFieldMetadata.fieldName] = computedValue; //TODO: This line here is just for backward compatibility, once the pre compute interface is change to return void, we will get rid of it.\n }\n }\n\n private shouldSkipPreComputeOnInsert(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any, currentOperation: ComputedFieldTriggerOperation): boolean {\n if (currentOperation !== ComputedFieldTriggerOperation.beforeInsert) {\n return false;\n }\n if (!entity) {\n return false;\n }\n const fieldName = computedFieldMetadata.fieldName;\n if (!fieldName) {\n return false;\n }\n const hasValue = Object.prototype.hasOwnProperty.call(entity, fieldName) && entity[fieldName] !== undefined && entity[fieldName] !== null;\n return hasValue;\n }\n\n private async preComputeValue(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any) {\n try {\n const provider = this.solidRegistry.getComputedFieldProvider(computedFieldMetadata.computedFieldValueProviderName);\n // Get the instance of the provider and assert it is of type IEntityComputedFieldProvider\n const providerInstance = provider.instance as IEntityPreComputeFieldProvider<any, any, any>; // IEntityComputedFieldProvider\n const computedValue = await providerInstance.preComputeValue(entity, computedFieldMetadata); //FIXME There should some way to check/assert if the provider actually has a postComputeAndSaveValue\n return computedValue; //TODO: This line here is just for backward compatibility, once the pre compute interface is change to return void, we will get rid of it.\n } catch (error: any) {\n throw new InternalServerErrorException(`Error evaluating computed field ${computedFieldMetadata.fieldName} for model ${computedFieldMetadata.modelName} for triggered entity ${entity.constructor.name}: ${error.message}`);\n }\n }\n\n private enqueueComputedFieldEvaluationJob(computedField: ComputedFieldMetadata<any>, databaseEntity: any) {\n const { manager: _manager, ...serializableEventContext } = computedField.eventContext ?? {};\n const payload = {\n ...computedField,\n eventContext: serializableEventContext,\n databaseEntity,\n };\n this.publisherFactory.publish({ payload }, 'ComputedFieldEvaluationPublisher');\n }\n\n private attachContext<T extends ComputedFieldMetadata<any>>(computedField: T, eventContext?: any): T {\n if (!eventContext) return computedField;\n return {\n ...computedField,\n computedFieldValueProviderCtxt: {\n ...(computedField.computedFieldValueProviderCtxt || {}),\n },\n eventContext,\n };\n }\n\n private sanitizeEventContext(event: InsertEvent<any> | UpdateEvent<any> | RemoveEvent<any>, eventType: string): TypeOrmEventContext {\n if (!event) return undefined;\n const base: TypeOrmEventContext = {\n metadataName: event.metadata?.name,\n eventType: eventType,\n // Only pass the transaction's EntityManager for embedded DB (PGlite),\n // where a second pooled connection mid-transaction would deadlock.\n // On regular Postgres, providers use their injected EntityManager.\n ...(isEmbeddedDb() ? { manager: event.manager } : {}),\n };\n if (\"entityId\" in event && event.entityId) {\n base.entityId = event.entityId;\n } else if (event.entity && (event.entity as any).id != null) {\n base.entityId = (event.entity as any).id;\n } else if (\"databaseEntity\" in event && (event.databaseEntity as any)?.id != null) {\n base.entityId = (event.databaseEntity as any).id;\n }\n if (\"updatedColumns\" in event && event.updatedColumns) {\n base.updatedColumns = event.updatedColumns.map((c: any) => c.propertyName);\n }\n if (\"updatedRelations\" in event && event.updatedRelations) {\n base.updatedRelations = event.updatedRelations.map((r: any) => r.propertyName);\n }\n if (event.entity) base.entity = event.entity;\n if (\"databaseEntity\" in event && event.databaseEntity) {\n base.databaseEntity = event.databaseEntity;\n }\n return base;\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"computed-entity-field.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/computed-entity-field.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { camelCase } from 'lodash';\nimport { forwardRef, Inject, Injectable, InternalServerErrorException, Logger, Scope } from \"@nestjs/common\";\nimport { ComputedFieldTriggerOperation } from \"src/dtos/create-field-metadata.dto\";\nimport { ComputedFieldMetadata, SolidRegistry, TypeOrmEventContext } from \"src/helpers/solid-registry\";\nimport { IEntityPreComputeFieldProvider } from \"src/interfaces\";\nimport { PublisherFactory } from \"src/services/queues/publisher-factory.service\";\nimport { DataSource, EntitySubscriberInterface, InsertEvent, RemoveEvent, UpdateEvent } from \"typeorm\";\n\n// Create an interface i.e ComputedFieldEvaluationPayload which has same fields as the ComputedFieldMetadata and an additional field for the database entity\nexport interface ComputedFieldEvaluationPayload extends ComputedFieldMetadata {\n databaseEntity: any;\n}\n\n@Injectable({ scope: Scope.TRANSIENT })\nexport class ComputedEntityFieldSubscriber implements EntitySubscriberInterface {\n private readonly logger = new Logger(this.constructor.name);\n private dataSource: DataSource;\n\n constructor(\n private readonly solidRegistry: SolidRegistry,\n @Inject(forwardRef(() => PublisherFactory))\n private readonly publisherFactory: PublisherFactory<ComputedFieldEvaluationPayload>\n ) {\n }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n async beforeInsert(event: InsertEvent<any>): Promise<any> {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'beforeInsert');\n await this.handleComputedFieldEvaluation(event.entity, ComputedFieldTriggerOperation.beforeInsert, modelName, eventContext);\n }\n\n async beforeUpdate(event: UpdateEvent<any>): Promise<any> {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'beforeUpdate');\n await this.handleComputedFieldEvaluation(event.entity, ComputedFieldTriggerOperation.beforeUpdate, modelName, eventContext);\n }\n\n afterInsert(event: InsertEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterInsert');\n this.handlePostEventJobs(event, event.entity, ComputedFieldTriggerOperation.afterInsert, modelName, eventContext);\n }\n\n afterUpdate(event: UpdateEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? event.databaseEntity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterUpdate');\n this.handlePostEventJobs(event, event.entity, ComputedFieldTriggerOperation.afterUpdate, modelName, eventContext);\n }\n\n afterRemove(event: RemoveEvent<any>) {\n const modelName = camelCase(event.metadata?.name ?? event.entity?.constructor?.name ?? event.databaseEntity?.constructor?.name ?? '');\n const eventContext = this.sanitizeEventContext(event, 'afterRemove');\n this.handlePostEventJobs(event, event.databaseEntity, ComputedFieldTriggerOperation.afterRemove, modelName, eventContext);\n }\n\n //FIXME: Need to add support for beforeRemove, beforeSoftRemove, afterSoftRemove, beforeRecover, afterRecover\n\n private handlePostEventJobs(\n _event: InsertEvent<any> | UpdateEvent<any> | RemoveEvent<any>,\n entity: any,\n currentOperation: ComputedFieldTriggerOperation,\n modelName: string,\n eventContext?: TypeOrmEventContext,\n ) {\n if (!entity) return;\n\n const computedFieldsTobeEvaluated = this.getComputedFieldsForEvaluation(\n this.solidRegistry.getComputedFieldMetadata(),\n currentOperation,\n modelName\n );\n if (computedFieldsTobeEvaluated.length === 0) return;\n\n for (const computedField of computedFieldsTobeEvaluated) {\n this.enqueueComputedFieldEvaluationJob(\n this.attachContext(computedField, eventContext),\n entity,\n );\n }\n }\n\n private async handleComputedFieldEvaluation(entity: any, currentOperation: ComputedFieldTriggerOperation, modelName: string, eventContext?: TypeOrmEventContext): Promise<void> {\n if (!entity) {\n return;\n }\n const computedFieldsTobeEvaluated = this.getComputedFieldsForEvaluation(\n this.solidRegistry.getComputedFieldMetadata(),\n currentOperation,\n modelName\n );\n for (const computedField of computedFieldsTobeEvaluated) {\n await this.evaluateComputedField(this.attachContext(computedField, eventContext), entity, currentOperation);\n }\n }\n\n // Based on the current model name and current operation, identify all the computed providers that need to be evaluated\n // Pass the database entity and the context to the provider of type IEntityComputedFieldProvider\n private getComputedFieldsForEvaluation(computedFieldMetadata: ComputedFieldMetadata[] = [], currentOperation: ComputedFieldTriggerOperation, currentModelName: string) {\n return computedFieldMetadata.filter(\n (computedField) => computedField.computedFieldTriggerConfig.some(\n (trigger) => trigger.operations.includes(currentOperation) &&\n trigger.modelName === currentModelName\n )\n );\n }\n\n private async evaluateComputedField(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any, currentOperation: ComputedFieldTriggerOperation) {\n // Skip pre-compute on insert when the payload already supplies the target field value.\n if (this.shouldSkipPreComputeOnInsert(computedFieldMetadata, entity, currentOperation)) {\n return;\n }\n const computedValue = await this.preComputeValue(computedFieldMetadata, entity);\n if (computedValue) {\n entity[computedFieldMetadata.fieldName] = computedValue; //TODO: This line here is just for backward compatibility, once the pre compute interface is change to return void, we will get rid of it.\n }\n }\n\n private shouldSkipPreComputeOnInsert(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any, currentOperation: ComputedFieldTriggerOperation): boolean {\n if (currentOperation !== ComputedFieldTriggerOperation.beforeInsert) {\n return false;\n }\n if (!entity) {\n return false;\n }\n const fieldName = computedFieldMetadata.fieldName;\n if (!fieldName) {\n return false;\n }\n const hasValue = Object.prototype.hasOwnProperty.call(entity, fieldName) && entity[fieldName] !== undefined && entity[fieldName] !== null;\n return hasValue;\n }\n\n private async preComputeValue(computedFieldMetadata: ComputedFieldMetadata<any>, entity: any) {\n try {\n const provider = this.solidRegistry.getComputedFieldProvider(computedFieldMetadata.computedFieldValueProviderName);\n // Get the instance of the provider and assert it is of type IEntityComputedFieldProvider\n const providerInstance = provider.instance as IEntityPreComputeFieldProvider<any, any, any>; // IEntityComputedFieldProvider\n const computedValue = await providerInstance.preComputeValue(entity, computedFieldMetadata); //FIXME There should some way to check/assert if the provider actually has a postComputeAndSaveValue\n return computedValue; //TODO: This line here is just for backward compatibility, once the pre compute interface is change to return void, we will get rid of it.\n } catch (error: any) {\n throw new InternalServerErrorException(`Error evaluating computed field ${computedFieldMetadata.fieldName} for model ${computedFieldMetadata.modelName} for triggered entity ${entity.constructor.name}: ${error.message}`);\n }\n }\n\n private enqueueComputedFieldEvaluationJob(computedField: ComputedFieldMetadata<any>, databaseEntity: any) {\n const payload = {\n ...computedField,\n databaseEntity,\n };\n this.publisherFactory.publish({ payload }, 'ComputedFieldEvaluationPublisher');\n }\n\n private attachContext<T extends ComputedFieldMetadata<any>>(computedField: T, eventContext?: any): T {\n if (!eventContext) return computedField;\n return {\n ...computedField,\n computedFieldValueProviderCtxt: {\n ...(computedField.computedFieldValueProviderCtxt || {}),\n },\n eventContext,\n };\n }\n\n private sanitizeEventContext(event: InsertEvent<any> | UpdateEvent<any> | RemoveEvent<any>, eventType: string): TypeOrmEventContext {\n if (!event) return undefined;\n const base: TypeOrmEventContext = {\n metadataName: event.metadata?.name,\n eventType: eventType,\n };\n if (\"entityId\" in event && event.entityId) {\n base.entityId = event.entityId;\n } else if (event.entity && (event.entity as any).id != null) {\n base.entityId = (event.entity as any).id;\n } else if (\"databaseEntity\" in event && (event.databaseEntity as any)?.id != null) {\n base.entityId = (event.databaseEntity as any).id;\n }\n if (\"updatedColumns\" in event && event.updatedColumns) {\n base.updatedColumns = event.updatedColumns.map((c: any) => c.propertyName);\n }\n if (\"updatedRelations\" in event && event.updatedRelations) {\n base.updatedRelations = event.updatedRelations.map((r: any) => r.propertyName);\n }\n if (event.entity) base.entity = event.entity;\n if (\"databaseEntity\" in event && event.databaseEntity) {\n base.databaseEntity = event.databaseEntity;\n }\n return base;\n }\n\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"created-by-updated-by.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/created-by-updated-by.subscriber.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1F,qBAEa,4BAA6B,YAAW,yBAAyB;IAItE,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAJ1C,OAAO,CAAC,UAAU,CAAa;gBAGV,iBAAiB,EAAE,UAAU,EAC7B,qBAAqB,EAAE,qBAAqB;IAKjE,gBAAgB,CAAC,UAAU,EAAE,UAAU;IAKjC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAIpC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;YAI5B,cAAc;
|
|
1
|
+
{"version":3,"file":"created-by-updated-by.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/created-by-updated-by.subscriber.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,sCAAsC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1F,qBAEa,4BAA6B,YAAW,yBAAyB;IAItE,OAAO,CAAC,QAAQ,CAAC,iBAAiB;IAClC,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IAJ1C,OAAO,CAAC,UAAU,CAAa;gBAGV,iBAAiB,EAAE,UAAU,EAC7B,qBAAqB,EAAE,qBAAqB;IAKjE,gBAAgB,CAAC,UAAU,EAAE,UAAU;IAKjC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;IAIpC,YAAY,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,CAAC;YAI5B,cAAc;CAmC/B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"created-by-updated-by.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/created-by-updated-by.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmD;AACnD,6CAAmD;AACnD,iFAA6E;AAC7E,qCAA0F;AAInF,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IAErC,YAEqB,iBAA6B,EAC7B,qBAA4C;QAD5C,sBAAiB,GAAjB,iBAAiB,CAAY;QAC7B,0BAAqB,GAArB,qBAAqB,CAAuB;IAGjE,CAAC;IAED,gBAAgB,CAAC,UAAsB;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAuB;QACtC,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAuB;QACtC,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,KAA0C,EAAE,QAAiB;QACtF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACX,CAAC;QAED,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QACzE,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;
|
|
1
|
+
{"version":3,"file":"created-by-updated-by.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/created-by-updated-by.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAAmD;AACnD,6CAAmD;AACnD,iFAA6E;AAC7E,qCAA0F;AAInF,IAAM,4BAA4B,GAAlC,MAAM,4BAA4B;IAErC,YAEqB,iBAA6B,EAC7B,qBAA4C;QAD5C,sBAAiB,GAAjB,iBAAiB,CAAY;QAC7B,0BAAqB,GAArB,qBAAqB,CAAuB;IAGjE,CAAC;IAED,gBAAgB,CAAC,UAAsB;QACnC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAuB;QACtC,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,KAAuB;QACtC,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;IAC5C,CAAC;IAEO,KAAK,CAAC,cAAc,CAAC,KAA0C,EAAE,QAAiB;QACtF,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAChB,OAAO;QACX,CAAC;QAED,MAAM,qBAAqB,GAAG,IAAI,CAAC,qBAAqB,CAAC,aAAa,EAAE,CAAC;QACzE,IAAI,CAAC,qBAAqB,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;QAWD,IAAI,QAAQ,EAAE,CAAC;YACX,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,qBAAqB,EAAE,GAAG,CAAC;YACpD,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,qBAAqB,EAAE,GAAG,CAAC;QACxD,CAAC;aACI,CAAC;YACF,KAAK,CAAC,MAAM,CAAC,SAAS,GAAG,qBAAqB,EAAE,GAAG,CAAC;QACxD,CAAC;IACL,CAAC;CASJ,CAAA;AA1DY,oEAA4B;uCAA5B,4BAA4B;IAFxC,IAAA,mBAAU,EAAC,EAAE,KAAK,EAAE,cAAK,CAAC,SAAS,EAAE,CAAC;IAK9B,WAAA,IAAA,0BAAgB,GAAE,CAAA;qCACiB,oBAAU;QACN,+CAAqB;GALxD,4BAA4B,CA0DxC","sourcesContent":["import { Injectable, Scope } from \"@nestjs/common\";\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport { RequestContextService } from \"src/services/request-context.service\";\nimport { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable({ scope: Scope.TRANSIENT })\n// @EventSubscriber()\nexport class CreatedByUpdatedBySubscriber implements EntitySubscriberInterface {\n private dataSource: DataSource;\n constructor(\n @InjectDataSource()\n private readonly defaultDataSource: DataSource,\n private readonly requestContextService: RequestContextService,\n ) {\n // this.dataSource.subscribers.push(this);\n }\n\n bindToDataSource(dataSource: DataSource) {\n this.dataSource = dataSource;\n this.dataSource.subscribers.push(this);\n }\n\n async beforeInsert(event: InsertEvent<any>) {\n await this.stampUserField(event, true);\n }\n\n async beforeUpdate(event: UpdateEvent<any>) {\n await this.stampUserField(event, false);\n }\n\n private async stampUserField(event: InsertEvent<any> | UpdateEvent<any>, isInsert: boolean) {\n if (!event.entity) {\n return;\n }\n // Get the current active user details from the request context\n const activeUserOrUndefined = this.requestContextService.getActiveUser();\n if (!activeUserOrUndefined) {\n return;\n }\n\n // const loadedUser = await this.loadUser(activeUserOrUndefined as unknown as ActiveUserData);\n // if (isInsert) {\n // event.entity.createdBy = loadedUser?.id;\n // event.entity.updatedBy = loadedUser?.id; // For insert, we set both createdBy and updatedBy to the same user\n // }\n // else {\n // event.entity.updatedBy = loadedUser?.id;\n // }\n\n if (isInsert) {\n event.entity.createdBy = activeUserOrUndefined?.sub;\n event.entity.updatedBy = activeUserOrUndefined?.sub; // For insert, we set both createdBy and updatedBy to the same user\n }\n else {\n event.entity.updatedBy = activeUserOrUndefined?.sub;\n }\n }\n\n // private async loadUser(activeUser: ActiveUserData): Promise<User> {\n // const userRepo = this.defaultDataSource.getRepository(User); // Assuming 'User' is the entity name for users in your application\n // const loadedUser = await userRepo.findOne({\n // where: { id: activeUser.sub }, // Assuming 'sub' is the user ID in the JWT token\n // });\n // return loadedUser;;\n // }\n}"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-metadata.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/field-metadata.subscriber.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAgC,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,qBACa,uBAAwB,YAAW,yBAAyB,CAAC,aAAa,CAAC;IAKpF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAJ7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAIhD,UAAU,EAAE,UAAU;IAKzC,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"field-metadata.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/field-metadata.subscriber.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAgC,WAAW,EAAE,MAAM,SAAS,CAAC;AAC3G,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAGlE,qBACa,uBAAwB,YAAW,yBAAyB,CAAC,aAAa,CAAC;IAKpF,OAAO,CAAC,QAAQ,CAAC,UAAU;IAJ7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA4C;gBAIhD,UAAU,EAAE,UAAU;IAKzC,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CA6BpE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"field-metadata.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/field-metadata.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAuE;AACvE,6CAAmD;AAEnD,qCAA2G;AAC3G,6EAAkE;AAI3D,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAGlC,YAEE,UAAuC;QAAtB,eAAU,GAAV,UAAU,CAAY;QAJxB,WAAM,GAAG,IAAI,eAAM,CAAC,yBAAuB,CAAC,IAAI,CAAC,CAAC;QAMjE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,QAAQ;QACN,OAAO,qCAAa,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAiC;
|
|
1
|
+
{"version":3,"file":"field-metadata.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/field-metadata.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2CAAuE;AACvE,6CAAmD;AAEnD,qCAA2G;AAC3G,6EAAkE;AAI3D,IAAM,uBAAuB,+BAA7B,MAAM,uBAAuB;IAGlC,YAEE,UAAuC;QAAtB,eAAU,GAAV,UAAU,CAAY;QAJxB,WAAM,GAAG,IAAI,eAAM,CAAC,yBAAuB,CAAC,IAAI,CAAC,CAAC;QAMjE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,QAAQ;QACN,OAAO,qCAAa,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAiC;IA4BnD,CAAC;CACF,CAAA;AA3CY,0DAAuB;kCAAvB,uBAAuB;IADnC,IAAA,mBAAU,GAAE;IAKR,WAAA,IAAA,0BAAgB,GAAE,CAAA;qCACU,oBAAU;GAL9B,uBAAuB,CA2CnC","sourcesContent":["import { Injectable, Logger, NotFoundException } from '@nestjs/common';\nimport { InjectDataSource } from '@nestjs/typeorm';\nimport { ModelMetadataHelperService } from 'src/helpers/model-metadata-helper.service';\nimport { DataSource, EntitySubscriberInterface, EventSubscriber, InsertEvent, UpdateEvent } from 'typeorm';\nimport { FieldMetadata } from '../entities/field-metadata.entity';\n\n// @EventSubscriber()\n@Injectable()\nexport class FieldMetadataSubscriber implements EntitySubscriberInterface<FieldMetadata> {\n private readonly logger = new Logger(FieldMetadataSubscriber.name);\n\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return FieldMetadata;\n }\n\n async afterUpdate(event: UpdateEvent<FieldMetadata>): Promise<void> {\n // If a field of type relation.many-to-one is marked for removal, and this field had an inverse relation created \n // It means there is a field of type relation.one-to-many in the co-model, which needs to be removed\n // if (event.entity && event.entity.isMarkedForRemoval && event.entity.type === 'relation' && event.entity.relationType === 'many-to-one' && event.entity.relationCreateInverse === true) {\n // const relationCoModelSingularName = event.entity.relationCoModelSingularName;\n // const relationCoModelFieldName = event.entity.relationCoModelFieldName;\n\n // // Load the field metadata for the co-model.\n // const coModelFieldMetadata = await this.dataSource\n // .getRepository(FieldMetadata)\n // .findOne({\n // where: {\n // name: relationCoModelFieldName,\n // type: 'relation',\n // relationType: 'one-to-many',\n // model: {\n // singularName: relationCoModelSingularName\n // }\n // },\n // });\n\n // // Mark the co-model isMarkedForRemoval field for removal.\n // if (coModelFieldMetadata) {\n // coModelFieldMetadata.isMarkedForRemoval = true;\n // await this.dataSource.getRepository(FieldMetadata).save(coModelFieldMetadata);\n // this.logger.debug(`Marked field ${coModelFieldMetadata.name} in model ${relationCoModelSingularName} for removal.`);\n // }\n // }\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduled-job.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"scheduled-job.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EACL,UAAU,EAEV,yBAAyB,EACzB,WAAW,EACX,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,qBACa,sBACX,YAAW,yBAAyB,CAAC,YAAY,CAAC;IAW5B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC/C,OAAO,CAAC,QAAQ,CAAC,2BAA2B;IAC5C,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAZnC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;IAGlE,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAIlC;gBAGqC,UAAU,EAAE,UAAU,EAC1C,2BAA2B,EAAE,2BAA2B,EACxD,gBAAgB,EAAE,sBAAsB;IAK3D,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;IAQ5C,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;IAqB5C,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;YAIpC,cAAc;YAkDd,cAAc;CA0D7B"}
|
|
@@ -52,7 +52,6 @@ const typeorm_1 = require("@nestjs/typeorm");
|
|
|
52
52
|
const fs = __importStar(require("fs/promises"));
|
|
53
53
|
const module_metadata_entity_1 = require("../entities/module-metadata.entity");
|
|
54
54
|
const scheduled_job_entity_1 = require("../entities/scheduled-job.entity");
|
|
55
|
-
const environment_helper_1 = require("../helpers/environment.helper");
|
|
56
55
|
const module_metadata_helper_service_1 = require("../helpers/module-metadata-helper.service");
|
|
57
56
|
const scheduled_job_repository_1 = require("../repository/scheduled-job.repository");
|
|
58
57
|
const typeorm_2 = require("typeorm");
|
|
@@ -102,7 +101,7 @@ let ScheduledJobSubscriber = ScheduledJobSubscriber_1 = class ScheduledJobSubscr
|
|
|
102
101
|
this.logger.error(`Module metadata not found for scheduled job with ID ${jobEntity?.id}`);
|
|
103
102
|
return;
|
|
104
103
|
}
|
|
105
|
-
const moduleMetadataRepo =
|
|
104
|
+
const moduleMetadataRepo = this.dataSource.getRepository(module_metadata_entity_1.ModuleMetadata);
|
|
106
105
|
const populatedModuleMetadata = await moduleMetadataRepo.findOne({
|
|
107
106
|
where: { id: moduleMetadata.id },
|
|
108
107
|
});
|
|
@@ -151,7 +150,7 @@ let ScheduledJobSubscriber = ScheduledJobSubscriber_1 = class ScheduledJobSubscr
|
|
|
151
150
|
}
|
|
152
151
|
const jobName = jobEntity.scheduleName;
|
|
153
152
|
const existingIndex = metaData.scheduledJobs.findIndex((job) => job.scheduleName === jobName);
|
|
154
|
-
const jobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob
|
|
153
|
+
const jobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob);
|
|
155
154
|
const { moduleId, lastRunAt, nextRunAt, ...dtoToWrite } = jobDto;
|
|
156
155
|
if (existingIndex !== -1) {
|
|
157
156
|
metaData.scheduledJobs[existingIndex] = dtoToWrite;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scheduled-job.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from \"fs/promises\";\nimport { CreateScheduledJobDto } from \"src/dtos/create-scheduled-job.dto\";\nimport { ModuleMetadata } from \"src/entities/module-metadata.entity\";\nimport { ScheduledJob } from \"src/entities/scheduled-job.entity\";\nimport { isEmbeddedDb } from \"src/helpers/environment.helper\";\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { ScheduledJobRepository } from \"src/repository/scheduled-job.repository\";\nimport {\n DataSource,\n EntityManager,\n EntitySubscriberInterface,\n InsertEvent,\n RemoveEvent,\n UpdateEvent,\n} from \"typeorm\";\n\n@Injectable()\nexport class ScheduledJobSubscriber\n implements EntitySubscriberInterface<ScheduledJob> {\n private readonly logger = new Logger(ScheduledJobSubscriber.name);\n\n /** Fields that, when changed (and only these changed), should NOT trigger metadata update. */\n private readonly ignoredUpdateFields: Array<keyof ScheduledJob | string> = [\n \"lastRunAt\",\n \"nextRunAt\",\n \"updatedAt\",\n ];\n\n constructor(\n @InjectDataSource() private readonly dataSource: DataSource,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n private readonly scheduledJobRepo: ScheduledJobRepository\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return ScheduledJob;\n }\n\n async afterInsert(event: InsertEvent<ScheduledJob>) {\n if (!event.entity) {\n this.logger.debug('No schedule Job entity found in the afterInsert method');\n return;\n }\n await this.updateMetadata(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<ScheduledJob>) {\n if (!event.databaseEntity) {\n this.logger.debug('No schedule Job entity found in the afterUpdate method');\n return;\n }\n\n // get hold of the changed field names \n const changedProps = (event.updatedColumns ?? []).map((c) => c.propertyName);\n\n // Decide whether to skip: only skip when *all* changed fields are in the ignore list\n const onlyIgnoredChanged = changedProps.every((p) => this.ignoredUpdateFields.includes(p));\n\n if (onlyIgnoredChanged) {\n this.logger.debug(`Skipping metadata update for ScheduledJob#${(event.databaseEntity as ScheduledJob).id}; only ignored fields changed: ${changedProps.join(\", \")}`\n );\n return;\n }\n\n await this.updateMetadata(event.databaseEntity, event.queryRunner.manager);\n }\n\n async afterRemove(event: RemoveEvent<ScheduledJob>) {\n await this.removeMetadata(event);\n }\n\n private async removeMetadata(event: RemoveEvent<ScheduledJob>) {\n const jobEntity = event.entity;\n const moduleMetadata = jobEntity?.module;\n\n if (!moduleMetadata) {\n this.logger.error(\n `Module metadata not found for scheduled job with ID ${jobEntity?.id}`\n );\n return;\n }\n\n const moduleMetadataRepo = (isEmbeddedDb() ? event.queryRunner.manager : this.dataSource).getRepository(ModuleMetadata);\n const populatedModuleMetadata = await moduleMetadataRepo.findOne({\n where: { id: moduleMetadata.id },\n });\n\n if (!populatedModuleMetadata) {\n this.logger.error(\n `Could not find ModuleMetadata with ID ${moduleMetadata.id}`\n );\n return;\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedModuleMetadata.name\n );\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n if (existingIndex !== -1) {\n metaData.scheduledJobs.splice(existingIndex, 1);\n this.logger.log(`Removed scheduled job ${jobName} from metadata`);\n }\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n\n private async updateMetadata(jobEntity: ScheduledJob, entityManager: EntityManager) {\n // populate the job with its relation\n const populatedScheduleJob = await entityManager.findOne(ScheduledJob, {\n where: { id: jobEntity.id },\n relations: ['module'],\n });\n\n if (!populatedScheduleJob) {\n throw new Error(`ScheduleJob not found for id ${jobEntity.id}`);\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedScheduleJob.module?.name\n );\n\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n\n // Ensure scheduledJobs exists\n if (!metaData.scheduledJobs) {\n metaData.scheduledJobs = [];\n }\n\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n // Insert or update job in metadata\n const jobDto: CreateScheduledJobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob as ScheduledJob, isEmbeddedDb() ? entityManager : undefined);\n // Strip out bookkeeping/runtime fields before persisting to metadata JSON.\n const {\n moduleId,\n lastRunAt,\n nextRunAt,\n ...dtoToWrite\n } = jobDto;\n if (existingIndex !== -1) {\n metaData.scheduledJobs[existingIndex] = dtoToWrite;\n this.logger.log(`Updated scheduled job ${jobName} in metadata`);\n } else {\n metaData.scheduledJobs.push(dtoToWrite);\n this.logger.log(`Added scheduled job ${jobName} to metadata`);\n }\n\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"scheduled-job.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/scheduled-job.subscriber.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from \"@nestjs/common\";\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from \"fs/promises\";\nimport { CreateScheduledJobDto } from \"src/dtos/create-scheduled-job.dto\";\nimport { ModuleMetadata } from \"src/entities/module-metadata.entity\";\nimport { ScheduledJob } from \"src/entities/scheduled-job.entity\";\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { ScheduledJobRepository } from \"src/repository/scheduled-job.repository\";\nimport {\n DataSource,\n EntityManager,\n EntitySubscriberInterface,\n InsertEvent,\n RemoveEvent,\n UpdateEvent,\n} from \"typeorm\";\n\n@Injectable()\nexport class ScheduledJobSubscriber\n implements EntitySubscriberInterface<ScheduledJob> {\n private readonly logger = new Logger(ScheduledJobSubscriber.name);\n\n /** Fields that, when changed (and only these changed), should NOT trigger metadata update. */\n private readonly ignoredUpdateFields: Array<keyof ScheduledJob | string> = [\n \"lastRunAt\",\n \"nextRunAt\",\n \"updatedAt\",\n ];\n\n constructor(\n @InjectDataSource() private readonly dataSource: DataSource,\n private readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n private readonly scheduledJobRepo: ScheduledJobRepository\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return ScheduledJob;\n }\n\n async afterInsert(event: InsertEvent<ScheduledJob>) {\n if (!event.entity) {\n this.logger.debug('No schedule Job entity found in the afterInsert method');\n return;\n }\n await this.updateMetadata(event.entity, event.queryRunner.manager);\n }\n\n async afterUpdate(event: UpdateEvent<ScheduledJob>) {\n if (!event.databaseEntity) {\n this.logger.debug('No schedule Job entity found in the afterUpdate method');\n return;\n }\n\n // get hold of the changed field names \n const changedProps = (event.updatedColumns ?? []).map((c) => c.propertyName);\n\n // Decide whether to skip: only skip when *all* changed fields are in the ignore list\n const onlyIgnoredChanged = changedProps.every((p) => this.ignoredUpdateFields.includes(p));\n\n if (onlyIgnoredChanged) {\n this.logger.debug(`Skipping metadata update for ScheduledJob#${(event.databaseEntity as ScheduledJob).id}; only ignored fields changed: ${changedProps.join(\", \")}`\n );\n return;\n }\n\n await this.updateMetadata(event.databaseEntity, event.queryRunner.manager);\n }\n\n async afterRemove(event: RemoveEvent<ScheduledJob>) {\n await this.removeMetadata(event);\n }\n\n private async removeMetadata(event: RemoveEvent<ScheduledJob>) {\n const jobEntity = event.entity;\n const moduleMetadata = jobEntity?.module;\n\n if (!moduleMetadata) {\n this.logger.error(\n `Module metadata not found for scheduled job with ID ${jobEntity?.id}`\n );\n return;\n }\n\n const moduleMetadataRepo = this.dataSource.getRepository(ModuleMetadata);\n const populatedModuleMetadata = await moduleMetadataRepo.findOne({\n where: { id: moduleMetadata.id },\n });\n\n if (!populatedModuleMetadata) {\n this.logger.error(\n `Could not find ModuleMetadata with ID ${moduleMetadata.id}`\n );\n return;\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedModuleMetadata.name\n );\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n if (existingIndex !== -1) {\n metaData.scheduledJobs.splice(existingIndex, 1);\n this.logger.log(`Removed scheduled job ${jobName} from metadata`);\n }\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n\n private async updateMetadata(jobEntity: ScheduledJob, entityManager: EntityManager) {\n // populate the job with its relation\n const populatedScheduleJob = await entityManager.findOne(ScheduledJob, {\n where: { id: jobEntity.id },\n relations: ['module'],\n });\n\n if (!populatedScheduleJob) {\n throw new Error(`ScheduleJob not found for id ${jobEntity.id}`);\n }\n const filePath =\n await this.moduleMetadataHelperService.getModuleMetadataFilePath(\n populatedScheduleJob.module?.name\n );\n\n try {\n await fs.access(filePath);\n } catch {\n this.logger.error(`Metadata file not found: ${filePath}`);\n return;\n }\n\n const metaData =\n await this.moduleMetadataHelperService.getModuleMetadataConfiguration(\n filePath\n );\n\n // Ensure scheduledJobs exists\n if (!metaData.scheduledJobs) {\n metaData.scheduledJobs = [];\n }\n\n // Remove, update or insert logic\n const jobName = jobEntity.scheduleName;\n const existingIndex = metaData.scheduledJobs.findIndex(\n (job) => job.scheduleName === jobName\n );\n // Insert or update job in metadata\n const jobDto: CreateScheduledJobDto = await this.scheduledJobRepo.toDto(populatedScheduleJob as ScheduledJob);\n // Strip out bookkeeping/runtime fields before persisting to metadata JSON.\n const {\n moduleId,\n lastRunAt,\n nextRunAt,\n ...dtoToWrite\n } = jobDto;\n if (existingIndex !== -1) {\n metaData.scheduledJobs[existingIndex] = dtoToWrite;\n this.logger.log(`Updated scheduled job ${jobName} in metadata`);\n } else {\n metaData.scheduledJobs.push(dtoToWrite);\n this.logger.log(`Added scheduled job ${jobName} to metadata`);\n }\n\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n this.logger.log(`Updated scheduledJobs in ${filePath}`);\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-rule.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"security-rule.subscriber.d.ts","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACjE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4CAA4C,CAAC;AACzF,OAAO,EAAE,sBAAsB,EAAE,MAAM,yCAAyC,CAAC;AACjF,OAAO,EAAE,UAAU,EAAE,yBAAyB,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE1F,qBACa,sBAAuB,YAAW,yBAAyB,CAAC,YAAY,CAAC;IAI9E,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,QAAQ,CAAC,2BAA2B,EAAE,2BAA2B;IACjE,QAAQ,CAAC,gBAAgB,EAAE,sBAAsB;IALrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2C;gBAG7C,UAAU,EAAE,UAAU,EAC9B,2BAA2B,EAAE,2BAA2B,EACxD,gBAAgB,EAAE,sBAAsB;IAKrD,QAAQ;IAIF,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;IAI5C,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC;IAI5C,iBAAiB,CAAC,KAAK,EAAE,WAAW,CAAC,YAAY,CAAC,GAAG,WAAW,CAAC,YAAY,CAAC;CAiDvF"}
|
|
@@ -53,7 +53,6 @@ const fs = __importStar(require("fs/promises"));
|
|
|
53
53
|
const constants_1 = require("../constants");
|
|
54
54
|
const model_metadata_entity_1 = require("../entities/model-metadata.entity");
|
|
55
55
|
const security_rule_entity_1 = require("../entities/security-rule.entity");
|
|
56
|
-
const environment_helper_1 = require("../helpers/environment.helper");
|
|
57
56
|
const module_metadata_helper_service_1 = require("../helpers/module-metadata-helper.service");
|
|
58
57
|
const security_rule_repository_1 = require("../repository/security-rule.repository");
|
|
59
58
|
const typeorm_2 = require("typeorm");
|
|
@@ -81,8 +80,7 @@ let SecurityRuleSubscriber = SecurityRuleSubscriber_1 = class SecurityRuleSubscr
|
|
|
81
80
|
this.logger.error(`Model metadata not found for security rule with id ${event.entity.id}`);
|
|
82
81
|
return;
|
|
83
82
|
}
|
|
84
|
-
const
|
|
85
|
-
const modelMetadataRepo = mgr.getRepository(model_metadata_entity_1.ModelMetadata);
|
|
83
|
+
const modelMetadataRepo = this.dataSource.getRepository(model_metadata_entity_1.ModelMetadata);
|
|
86
84
|
const populatedModelMetadata = await modelMetadataRepo.findOne({
|
|
87
85
|
where: {
|
|
88
86
|
id: modelMetadata.id
|
|
@@ -105,12 +103,12 @@ let SecurityRuleSubscriber = SecurityRuleSubscriber_1 = class SecurityRuleSubscr
|
|
|
105
103
|
const metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);
|
|
106
104
|
if (metaData.securityRules) {
|
|
107
105
|
const securityRuleIndex = metaData.securityRules?.findIndex((ruleFromFile) => ruleFromFile.name === securityRule.name);
|
|
108
|
-
const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule
|
|
106
|
+
const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule);
|
|
109
107
|
metaData.securityRules[securityRuleIndex] = { ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) };
|
|
110
108
|
}
|
|
111
109
|
else {
|
|
112
110
|
const securityRules = [];
|
|
113
|
-
const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule
|
|
111
|
+
const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule);
|
|
114
112
|
securityRules.push({ ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) });
|
|
115
113
|
metaData.securityRules = securityRules;
|
|
116
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-rule.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,6CAAmD;AACnD,gDAAkC;AAClC,4CAAuD;AACvD,6EAAmE;AACnE,2EAAiE;AACjE,
|
|
1
|
+
{"version":3,"file":"security-rule.subscriber.js","sourceRoot":"","sources":["../../src/subscribers/security-rule.subscriber.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,6CAAmD;AACnD,gDAAkC;AAClC,4CAAuD;AACvD,6EAAmE;AACnE,2EAAiE;AACjE,8FAAyF;AACzF,qFAAiF;AACjF,qCAA0F;AAGnF,IAAM,sBAAsB,8BAA5B,MAAM,sBAAsB;IAE/B,YAEI,UAAuC,EAC9B,2BAAwD,EACxD,gBAAwC;QAFhC,eAAU,GAAV,UAAU,CAAY;QAC9B,gCAA2B,GAA3B,2BAA2B,CAA6B;QACxD,qBAAgB,GAAhB,gBAAgB,CAAwB;QALpC,WAAM,GAAG,IAAI,eAAM,CAAC,wBAAsB,CAAC,IAAI,CAAC,CAAC;QAO9D,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,QAAQ;QACJ,OAAO,mCAAY,CAAC;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAgC;QAC9C,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,KAAgC;QAC9C,MAAM,IAAI,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,iBAAiB,CAAC,KAA4D;QAChF,MAAM,YAAY,GAAG,KAAK,CAAC,MAAsB,CAAC;QAClD,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC;QACjD,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,sDAAsD,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3F,OAAO;QACX,CAAC;QAED,MAAM,iBAAiB,GAAG,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,qCAAa,CAAC,CAAC;QACvE,MAAM,sBAAsB,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC;YAC3D,KAAK,EAAE;gBACH,EAAE,EAAE,aAAa,CAAC,EAAE;aACvB;YACD,SAAS,EAAE;gBACP,MAAM,EAAE,IAAI;aACf;SACJ,CAAC,CAAC;QAGH,IAAI,sBAAsB,CAAC,MAAM,CAAC,IAAI,KAAK,kCAAsB,EAAE,CAAC;YAChE,OAAO;QACX,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,yBAAyB,CAAC,sBAAsB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtH,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC9B,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YAElB,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,2BAA2B,QAAQ,EAAE,CAAC,CAAC;YACzD,OAAO;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,2BAA2B,CAAC,8BAA8B,CAAC,QAAQ,CAAC,CAAC;QAEjG,IAAI,QAAQ,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,iBAAiB,GAAG,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,YAA8B,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,KAAK,YAAY,CAAC,IAAI,CAAC,CAAC;YACzI,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,WAAW,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;YACvG,QAAQ,CAAC,aAAa,CAAC,iBAAiB,CAAC,GAAG,EAAE,GAAG,WAAW,EAAE,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,CAAC,EAAE,CAAA;QACnI,CAAC;aACI,CAAC;YACF,MAAM,aAAa,GAAG,EAAE,CAAA;YACxB,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,WAAW,EAAE,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;YACvG,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,WAAW,EAAE,kBAAkB,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAA;YACvG,QAAQ,CAAC,aAAa,GAAG,aAAa,CAAA;QAC1C,CAAC;QAED,MAAM,cAAc,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QACzD,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IACjD,CAAC;CAEJ,CAAA;AAxEY,wDAAsB;iCAAtB,sBAAsB;IADlC,IAAA,mBAAU,GAAE;IAIJ,WAAA,IAAA,0BAAgB,GAAE,CAAA;qCACU,oBAAU;QACD,4DAA2B;QACtC,iDAAsB;GAN5C,sBAAsB,CAwElC","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport { InjectDataSource } from \"@nestjs/typeorm\";\nimport * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await\nimport { SOLID_CORE_MODULE_NAME } from 'src/constants';\nimport { ModelMetadata } from 'src/entities/model-metadata.entity';\nimport { SecurityRule } from 'src/entities/security-rule.entity';\nimport { ModuleMetadataHelperService } from \"src/helpers/module-metadata-helper.service\";\nimport { SecurityRuleRepository } from 'src/repository/security-rule.repository';\nimport { DataSource, EntitySubscriberInterface, InsertEvent, UpdateEvent } from \"typeorm\";\n\n@Injectable()\nexport class SecurityRuleSubscriber implements EntitySubscriberInterface<SecurityRule> {\n private readonly logger = new Logger(SecurityRuleSubscriber.name);\n constructor(\n @InjectDataSource()\n private readonly dataSource: DataSource,\n readonly moduleMetadataHelperService: ModuleMetadataHelperService,\n readonly securityRuleRepo: SecurityRuleRepository,\n ) {\n this.dataSource.subscribers.push(this);\n }\n\n listenTo() {\n return SecurityRule;\n }\n\n async afterInsert(event: InsertEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async afterUpdate(event: UpdateEvent<SecurityRule>) {\n await this.saveSecurityRules(event);\n }\n\n async saveSecurityRules(event: UpdateEvent<SecurityRule> | InsertEvent<SecurityRule>) {\n const securityRule = event.entity as SecurityRule;\n const modelMetadata = event.entity.modelMetadata;\n if (!modelMetadata) {\n this.logger.error(`Model metadata not found for security rule with id ${event.entity.id}`);\n return;\n }\n\n const modelMetadataRepo = this.dataSource.getRepository(ModelMetadata);\n const populatedModelMetadata = await modelMetadataRepo.findOne({\n where: {\n id: modelMetadata.id\n },\n relations: {\n module: true,\n }\n });\n\n // Ignore further processing if the module is solid core module, since solid core security rules cannot be seeded from the UI\n if (populatedModelMetadata.module.name === SOLID_CORE_MODULE_NAME) {\n return;\n }\n\n const filePath = await this.moduleMetadataHelperService.getModuleMetadataFilePath(populatedModelMetadata.module.name);\n try {\n await fs.access(filePath);\n } catch (error: any) {\n // FIXME - Should we actually delete the security rule here, if the file is not found?\n this.logger.error(`File not found at path: ${filePath}`);\n return;\n }\n const metaData = await this.moduleMetadataHelperService.getModuleMetadataConfiguration(filePath);\n\n if (metaData.securityRules) {\n const securityRuleIndex = metaData.securityRules?.findIndex((ruleFromFile: { name: string }) => ruleFromFile.name === securityRule.name);\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n metaData.securityRules[securityRuleIndex] = { ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) }\n }\n else {\n const securityRules = []\n const { id, roleId, modelMetadataId, ...requiredDto } = await this.securityRuleRepo.toDto(securityRule)\n securityRules.push({ ...requiredDto, securityRuleConfig: JSON.parse(securityRule.securityRuleConfig) })\n metaData.securityRules = securityRules\n }\n // Write the updated object back to the file\n const updatedContent = JSON.stringify(metaData, null, 2);\n await fs.writeFile(filePath, updatedContent);\n }\n\n}"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solidxai/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.12-beta.0",
|
|
4
4
|
"description": "This module is a NestJS module containing all the required core providers required by a Solid application",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -20,12 +20,12 @@ enum ShowSoftDeleted {
|
|
|
20
20
|
export class ChatterMessageController {
|
|
21
21
|
constructor(private readonly service: ChatterMessageService) {}
|
|
22
22
|
|
|
23
|
-
@ApiBearerAuth("jwt")
|
|
24
|
-
@Post()
|
|
25
|
-
@UseInterceptors(AnyFilesInterceptor())
|
|
26
|
-
create(@Body() createDto: CreateChatterMessageDto, @UploadedFiles() files: Array<Express.Multer.File>) {
|
|
27
|
-
|
|
28
|
-
}
|
|
23
|
+
// @ApiBearerAuth("jwt")
|
|
24
|
+
// @Post()
|
|
25
|
+
// @UseInterceptors(AnyFilesInterceptor())
|
|
26
|
+
// create(@Body() createDto: CreateChatterMessageDto, @UploadedFiles() files: Array<Express.Multer.File>) {
|
|
27
|
+
// return this.service.create(createDto, files);
|
|
28
|
+
// }
|
|
29
29
|
|
|
30
30
|
// @ApiBearerAuth("jwt")
|
|
31
31
|
// @Post('/bulk')
|
|
@@ -61,7 +61,7 @@ export class ChatterMessageController {
|
|
|
61
61
|
// return this.service.recover(id);
|
|
62
62
|
// }
|
|
63
63
|
|
|
64
|
-
@
|
|
64
|
+
@ApiBearerAuth("jwt")
|
|
65
65
|
@Get('/getChatterMessages/:entityId/:entityName')
|
|
66
66
|
@ApiQuery({ name: 'showSoftDeleted', required: false, enum: ShowSoftDeleted })
|
|
67
67
|
@ApiQuery({ name: 'limit', required: false, type: Number })
|
|
@@ -47,7 +47,7 @@ export class MediaController {
|
|
|
47
47
|
return this.service.update(id, updateDto, files, true);
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
@Public()
|
|
50
|
+
// @Public()
|
|
51
51
|
// @SkipThrottle({ short: false, login: true, burst: true, sustained: true }) //Enable the short throttle only
|
|
52
52
|
@ApiBearerAuth("jwt")
|
|
53
53
|
@Post('/upload')
|