@dyrected/core 2.5.53 → 2.5.56
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/dist/{app-config-oOarB6Fw.d.cts → app-config-Bxg_DVxv.d.cts} +3 -1
- package/dist/{app-config-oOarB6Fw.d.ts → app-config-Bxg_DVxv.d.ts} +3 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/server.d.cts +1 -1
- package/dist/server.d.ts +1 -1
- package/package.json +1 -1
- package/dist/__tests__/admin-auth.test.d.ts +0 -2
- package/dist/__tests__/admin-auth.test.d.ts.map +0 -1
- package/dist/__tests__/admin-auth.test.js +0 -440
- package/dist/__tests__/admin-auth.test.js.map +0 -1
- package/dist/__tests__/app.test.d.ts +0 -2
- package/dist/__tests__/app.test.d.ts.map +0 -1
- package/dist/__tests__/app.test.js +0 -27
- package/dist/__tests__/app.test.js.map +0 -1
- package/dist/__tests__/config.test.d.ts +0 -2
- package/dist/__tests__/config.test.d.ts.map +0 -1
- package/dist/__tests__/config.test.js +0 -91
- package/dist/__tests__/config.test.js.map +0 -1
- package/dist/__tests__/deleteMany.test.d.ts +0 -2
- package/dist/__tests__/deleteMany.test.d.ts.map +0 -1
- package/dist/__tests__/deleteMany.test.js +0 -75
- package/dist/__tests__/deleteMany.test.js.map +0 -1
- package/dist/__tests__/depth.test.d.ts +0 -2
- package/dist/__tests__/depth.test.d.ts.map +0 -1
- package/dist/__tests__/depth.test.js +0 -81
- package/dist/__tests__/depth.test.js.map +0 -1
- package/dist/__tests__/dynamic-options.test.d.ts +0 -2
- package/dist/__tests__/dynamic-options.test.d.ts.map +0 -1
- package/dist/__tests__/dynamic-options.test.js +0 -132
- package/dist/__tests__/dynamic-options.test.js.map +0 -1
- package/dist/__tests__/email.service.test.d.ts +0 -2
- package/dist/__tests__/email.service.test.d.ts.map +0 -1
- package/dist/__tests__/email.service.test.js +0 -46
- package/dist/__tests__/email.service.test.js.map +0 -1
- package/dist/__tests__/field-inference.test-types.d.ts +0 -24
- package/dist/__tests__/field-inference.test-types.d.ts.map +0 -1
- package/dist/__tests__/field-inference.test-types.js +0 -87
- package/dist/__tests__/field-inference.test-types.js.map +0 -1
- package/dist/__tests__/fixtures/editorial-workflow.d.ts +0 -9
- package/dist/__tests__/fixtures/editorial-workflow.d.ts.map +0 -1
- package/dist/__tests__/fixtures/editorial-workflow.js +0 -12
- package/dist/__tests__/fixtures/editorial-workflow.js.map +0 -1
- package/dist/__tests__/hooks.test.d.ts +0 -2
- package/dist/__tests__/hooks.test.d.ts.map +0 -1
- package/dist/__tests__/hooks.test.js +0 -320
- package/dist/__tests__/hooks.test.js.map +0 -1
- package/dist/__tests__/mocks.d.ts +0 -74
- package/dist/__tests__/mocks.d.ts.map +0 -1
- package/dist/__tests__/mocks.js +0 -159
- package/dist/__tests__/mocks.js.map +0 -1
- package/dist/__tests__/openapi.test.d.ts +0 -2
- package/dist/__tests__/openapi.test.d.ts.map +0 -1
- package/dist/__tests__/openapi.test.js +0 -95
- package/dist/__tests__/openapi.test.js.map +0 -1
- package/dist/__tests__/parse-sort.test.d.ts +0 -2
- package/dist/__tests__/parse-sort.test.d.ts.map +0 -1
- package/dist/__tests__/parse-sort.test.js +0 -24
- package/dist/__tests__/parse-sort.test.js.map +0 -1
- package/dist/__tests__/preferences.test.d.ts +0 -2
- package/dist/__tests__/preferences.test.d.ts.map +0 -1
- package/dist/__tests__/preferences.test.js +0 -168
- package/dist/__tests__/preferences.test.js.map +0 -1
- package/dist/__tests__/router.test.d.ts +0 -2
- package/dist/__tests__/router.test.d.ts.map +0 -1
- package/dist/__tests__/router.test.js +0 -52
- package/dist/__tests__/router.test.js.map +0 -1
- package/dist/__tests__/where.test.d.ts +0 -2
- package/dist/__tests__/where.test.d.ts.map +0 -1
- package/dist/__tests__/where.test.js +0 -105
- package/dist/__tests__/where.test.js.map +0 -1
- package/dist/__tests__/workflow.test.d.ts +0 -2
- package/dist/__tests__/workflow.test.d.ts.map +0 -1
- package/dist/__tests__/workflow.test.js +0 -497
- package/dist/__tests__/workflow.test.js.map +0 -1
- package/dist/app-B2tg7Djj.d.cts +0 -1575
- package/dist/app-B2tg7Djj.d.ts +0 -1575
- package/dist/app-BElen1tP.d.cts +0 -1690
- package/dist/app-BElen1tP.d.ts +0 -1690
- package/dist/app-BOrsS7Tz.d.cts +0 -1771
- package/dist/app-BOrsS7Tz.d.ts +0 -1771
- package/dist/app-Bh4_Opv0.d.cts +0 -1522
- package/dist/app-Bh4_Opv0.d.ts +0 -1522
- package/dist/app-BibuoHQG.d.cts +0 -1764
- package/dist/app-BibuoHQG.d.ts +0 -1764
- package/dist/app-Bv9gaDAN.d.cts +0 -561
- package/dist/app-Bv9gaDAN.d.ts +0 -561
- package/dist/app-BvG3bRc8.d.cts +0 -419
- package/dist/app-BvG3bRc8.d.ts +0 -419
- package/dist/app-C-HgyliB.d.cts +0 -1694
- package/dist/app-C-HgyliB.d.ts +0 -1694
- package/dist/app-C3B9N1KR.d.cts +0 -1522
- package/dist/app-C3B9N1KR.d.ts +0 -1522
- package/dist/app-Cc2mG3zi.d.cts +0 -373
- package/dist/app-Cc2mG3zi.d.ts +0 -373
- package/dist/app-Ctfmo2Re.d.cts +0 -1692
- package/dist/app-Ctfmo2Re.d.ts +0 -1692
- package/dist/app-D0ffogDd.d.cts +0 -1690
- package/dist/app-D0ffogDd.d.ts +0 -1690
- package/dist/app-D2uR47gK.d.cts +0 -1690
- package/dist/app-D2uR47gK.d.ts +0 -1690
- package/dist/app-DDJJa0ep.d.cts +0 -1621
- package/dist/app-DDJJa0ep.d.ts +0 -1621
- package/dist/app-DO1s9YW1.d.cts +0 -1621
- package/dist/app-DO1s9YW1.d.ts +0 -1621
- package/dist/app-DTP3-9PJ.d.cts +0 -561
- package/dist/app-DTP3-9PJ.d.ts +0 -561
- package/dist/app-DZt5nslu.d.cts +0 -374
- package/dist/app-DZt5nslu.d.ts +0 -377
- package/dist/app-DbKDGYTI.d.cts +0 -566
- package/dist/app-DbKDGYTI.d.ts +0 -566
- package/dist/app-Dk3SzV1a.d.cts +0 -374
- package/dist/app-Dk3SzV1a.d.ts +0 -374
- package/dist/app-DnX9mNsh.d.cts +0 -374
- package/dist/app-DnX9mNsh.d.ts +0 -374
- package/dist/app-DqRO-CMi.d.cts +0 -1457
- package/dist/app-DqRO-CMi.d.ts +0 -1457
- package/dist/app-DvaFpOtj.d.cts +0 -398
- package/dist/app-DvaFpOtj.d.ts +0 -398
- package/dist/app-FGzip4XM.d.cts +0 -1563
- package/dist/app-FGzip4XM.d.ts +0 -1563
- package/dist/app-KApbf4XL.d.cts +0 -362
- package/dist/app-KApbf4XL.d.ts +0 -362
- package/dist/app-T0alZAE0.d.cts +0 -383
- package/dist/app-T0alZAE0.d.ts +0 -383
- package/dist/app-aW2FMuYM.d.cts +0 -1759
- package/dist/app-aW2FMuYM.d.ts +0 -1759
- package/dist/app-config-2vF6W56z.d.cts +0 -1335
- package/dist/app-config-2vF6W56z.d.ts +0 -1335
- package/dist/app-config-3XBnu9Xz.d.cts +0 -1379
- package/dist/app-config-3XBnu9Xz.d.ts +0 -1379
- package/dist/app-config-BLMX-9MN.d.cts +0 -1045
- package/dist/app-config-BLMX-9MN.d.ts +0 -1045
- package/dist/app-config-CaEQH0Kb.d.cts +0 -1383
- package/dist/app-config-CaEQH0Kb.d.ts +0 -1383
- package/dist/app-config-DLK6bCaP.d.cts +0 -1390
- package/dist/app-config-DLK6bCaP.d.ts +0 -1390
- package/dist/app-oQt5-9MU.d.cts +0 -1560
- package/dist/app-oQt5-9MU.d.ts +0 -1560
- package/dist/app-rZj1VFer.d.cts +0 -1621
- package/dist/app-rZj1VFer.d.ts +0 -1621
- package/dist/app-wo82JRHl.d.cts +0 -445
- package/dist/app-wo82JRHl.d.ts +0 -445
- package/dist/app.d.ts +0 -21
- package/dist/app.d.ts.map +0 -1
- package/dist/app.js +0 -56
- package/dist/app.js.map +0 -1
- package/dist/auth/jexl.d.ts +0 -10
- package/dist/auth/jexl.d.ts.map +0 -1
- package/dist/auth/jexl.js +0 -22
- package/dist/auth/jexl.js.map +0 -1
- package/dist/auth/password.d.ts +0 -10
- package/dist/auth/password.d.ts.map +0 -1
- package/dist/auth/password.js +0 -28
- package/dist/auth/password.js.map +0 -1
- package/dist/auth/token.d.ts +0 -22
- package/dist/auth/token.d.ts.map +0 -1
- package/dist/auth/token.js +0 -40
- package/dist/auth/token.js.map +0 -1
- package/dist/chunk-22JTWD74.js +0 -1784
- package/dist/chunk-23URSKPI.js +0 -2371
- package/dist/chunk-2JMA3M5S.js +0 -2475
- package/dist/chunk-3FZEUK36.js +0 -2470
- package/dist/chunk-3VUH2MNW.js +0 -1903
- package/dist/chunk-44O2LDPT.js +0 -1513
- package/dist/chunk-45JDQDA2.js +0 -1899
- package/dist/chunk-4C4L6SD2.js +0 -1524
- package/dist/chunk-4EDMZAM5.js +0 -2692
- package/dist/chunk-52T4RCFU.js +0 -1972
- package/dist/chunk-6ZXEGKT6.js +0 -619
- package/dist/chunk-7GGHK75W.js +0 -1835
- package/dist/chunk-ALNQINX7.js +0 -2496
- package/dist/chunk-B6KDKYXB.js +0 -2502
- package/dist/chunk-BEONZV6M.js +0 -1951
- package/dist/chunk-C4GEQ5RP.js +0 -1993
- package/dist/chunk-CQDVPMEU.js +0 -613
- package/dist/chunk-DOJHZ7XN.js +0 -2394
- package/dist/chunk-EH7G3LLL.js +0 -2065
- package/dist/chunk-EXXOPW3I.js +0 -2483
- package/dist/chunk-F4ZC6TXR.js +0 -2065
- package/dist/chunk-FCXE5CVC.js +0 -1528
- package/dist/chunk-FDQYPPG3.js +0 -2698
- package/dist/chunk-FURYJ254.mjs +0 -33
- package/dist/chunk-G2QQLBHW.js +0 -24
- package/dist/chunk-GM4WW6IE.js +0 -66
- package/dist/chunk-GZODLJ3C.js +0 -1861
- package/dist/chunk-IIY3E7Q7.js +0 -1996
- package/dist/chunk-JJN4J5NS.js +0 -2069
- package/dist/chunk-MRUHCNDM.js +0 -1940
- package/dist/chunk-NKDX67AW.js +0 -2698
- package/dist/chunk-NYUB4AHZ.js +0 -1951
- package/dist/chunk-OD4SLW7H.js +0 -1930
- package/dist/chunk-OE5MH3NB.js +0 -2070
- package/dist/chunk-PH36WQYS.js +0 -1875
- package/dist/chunk-PKNFV7KE.js +0 -2469
- package/dist/chunk-SUGK7UYL.js +0 -311
- package/dist/chunk-TIJHR54M.js +0 -1879
- package/dist/chunk-TUUHGLB5.js +0 -2609
- package/dist/chunk-UBTRANFX.js +0 -2476
- package/dist/chunk-VJWUG2XK.js +0 -1951
- package/dist/chunk-W6KURRMW.js +0 -2471
- package/dist/chunk-Y4AYI52W.js +0 -631
- package/dist/chunk-YDOBB7MY.js +0 -1457
- package/dist/chunk-YNJ3YC4N.js +0 -2483
- package/dist/chunk-ZFAOBRHT.js +0 -2709
- package/dist/controllers/admin-auth.controller.d.ts +0 -68
- package/dist/controllers/admin-auth.controller.d.ts.map +0 -1
- package/dist/controllers/admin-auth.controller.js +0 -414
- package/dist/controllers/admin-auth.controller.js.map +0 -1
- package/dist/controllers/auth.controller.d.ts +0 -125
- package/dist/controllers/auth.controller.d.ts.map +0 -1
- package/dist/controllers/auth.controller.js +0 -323
- package/dist/controllers/auth.controller.js.map +0 -1
- package/dist/controllers/collection.controller.d.ts +0 -157
- package/dist/controllers/collection.controller.d.ts.map +0 -1
- package/dist/controllers/collection.controller.js +0 -779
- package/dist/controllers/collection.controller.js.map +0 -1
- package/dist/controllers/global.controller.d.ts +0 -17
- package/dist/controllers/global.controller.d.ts.map +0 -1
- package/dist/controllers/global.controller.js +0 -132
- package/dist/controllers/global.controller.js.map +0 -1
- package/dist/controllers/media.controller.d.ts +0 -38
- package/dist/controllers/media.controller.d.ts.map +0 -1
- package/dist/controllers/media.controller.js +0 -162
- package/dist/controllers/media.controller.js.map +0 -1
- package/dist/controllers/preview.controller.d.ts +0 -37
- package/dist/controllers/preview.controller.d.ts.map +0 -1
- package/dist/controllers/preview.controller.js +0 -48
- package/dist/controllers/preview.controller.js.map +0 -1
- package/dist/index-BKYugiYp.d.cts +0 -1988
- package/dist/index-BKYugiYp.d.ts +0 -1988
- package/dist/index-BSWCiAen.d.cts +0 -1983
- package/dist/index-BSWCiAen.d.ts +0 -1983
- package/dist/index-BfLDb3b0.d.cts +0 -1467
- package/dist/index-BfLDb3b0.d.ts +0 -1467
- package/dist/index-Bi4sX_eC.d.cts +0 -1491
- package/dist/index-Bi4sX_eC.d.ts +0 -1491
- package/dist/index-Bp7PDOYG.d.cts +0 -1750
- package/dist/index-Bp7PDOYG.d.ts +0 -1750
- package/dist/index-ByXooLy-.d.cts +0 -1762
- package/dist/index-ByXooLy-.d.ts +0 -1762
- package/dist/index-C9Vp1DCT.d.cts +0 -1563
- package/dist/index-C9Vp1DCT.d.ts +0 -1563
- package/dist/index-CFezd8p1.d.cts +0 -1986
- package/dist/index-CFezd8p1.d.ts +0 -1986
- package/dist/index-CdQwnbfh.d.cts +0 -1889
- package/dist/index-CdQwnbfh.d.ts +0 -1889
- package/dist/index-D38_E0gf.d.cts +0 -336
- package/dist/index-D38_E0gf.d.ts +0 -336
- package/dist/index-DR2z1rrf.d.cts +0 -1503
- package/dist/index-DR2z1rrf.d.ts +0 -1503
- package/dist/index-DTrpTru7.d.cts +0 -1881
- package/dist/index-DTrpTru7.d.ts +0 -1881
- package/dist/index-DfAmTZXk.d.cts +0 -1749
- package/dist/index-DfAmTZXk.d.ts +0 -1749
- package/dist/index-DfkPT4NR.d.cts +0 -1584
- package/dist/index-DfkPT4NR.d.ts +0 -1584
- package/dist/index-DzUlE5Hc.d.cts +0 -1751
- package/dist/index-DzUlE5Hc.d.ts +0 -1751
- package/dist/index-M_m6dXZV.d.cts +0 -1889
- package/dist/index-M_m6dXZV.d.ts +0 -1889
- package/dist/index-RylhgOwj.d.cts +0 -340
- package/dist/index-RylhgOwj.d.ts +0 -340
- package/dist/index-qhLus8ZO.d.cts +0 -1881
- package/dist/index-qhLus8ZO.d.ts +0 -1881
- package/dist/index-xB1lMg79.d.cts +0 -1456
- package/dist/index-xB1lMg79.d.ts +0 -1456
- package/dist/index.d.mts +0 -417
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/index.mjs +0 -1974
- package/dist/middleware/auth.d.ts +0 -18
- package/dist/middleware/auth.d.ts.map +0 -1
- package/dist/middleware/auth.js +0 -45
- package/dist/middleware/auth.js.map +0 -1
- package/dist/password-ACI2YUGZ.js +0 -8
- package/dist/router.d.ts +0 -8
- package/dist/router.d.ts.map +0 -1
- package/dist/router.js +0 -625
- package/dist/router.js.map +0 -1
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js.map +0 -1
- package/dist/services/audit.service.d.ts +0 -23
- package/dist/services/audit.service.d.ts.map +0 -1
- package/dist/services/audit.service.js +0 -28
- package/dist/services/audit.service.js.map +0 -1
- package/dist/services/defaults.service.d.ts +0 -8
- package/dist/services/defaults.service.d.ts.map +0 -1
- package/dist/services/defaults.service.js +0 -55
- package/dist/services/defaults.service.js.map +0 -1
- package/dist/services/email-template.d.ts +0 -46
- package/dist/services/email-template.d.ts.map +0 -1
- package/dist/services/email-template.js +0 -88
- package/dist/services/email-template.js.map +0 -1
- package/dist/services/email.service.d.ts +0 -33
- package/dist/services/email.service.d.ts.map +0 -1
- package/dist/services/email.service.js +0 -96
- package/dist/services/email.service.js.map +0 -1
- package/dist/services/media.service.d.ts +0 -20
- package/dist/services/media.service.d.ts.map +0 -1
- package/dist/services/media.service.js +0 -49
- package/dist/services/media.service.js.map +0 -1
- package/dist/services/population.service.d.ts +0 -20
- package/dist/services/population.service.d.ts.map +0 -1
- package/dist/services/population.service.js +0 -194
- package/dist/services/population.service.js.map +0 -1
- package/dist/token-7QG5DBME.mjs +0 -10
- package/dist/types/access.d.ts +0 -38
- package/dist/types/access.d.ts.map +0 -1
- package/dist/types/access.js +0 -2
- package/dist/types/access.js.map +0 -1
- package/dist/types/adapters.d.ts +0 -146
- package/dist/types/adapters.d.ts.map +0 -1
- package/dist/types/adapters.js +0 -2
- package/dist/types/adapters.js.map +0 -1
- package/dist/types/admin-auth.d.ts +0 -132
- package/dist/types/admin-auth.d.ts.map +0 -1
- package/dist/types/admin-auth.js +0 -2
- package/dist/types/admin-auth.js.map +0 -1
- package/dist/types/admin.d.ts +0 -65
- package/dist/types/admin.d.ts.map +0 -1
- package/dist/types/admin.js +0 -2
- package/dist/types/admin.js.map +0 -1
- package/dist/types/app-config.d.ts +0 -143
- package/dist/types/app-config.d.ts.map +0 -1
- package/dist/types/app-config.js +0 -2
- package/dist/types/app-config.js.map +0 -1
- package/dist/types/documents.d.ts +0 -65
- package/dist/types/documents.d.ts.map +0 -1
- package/dist/types/documents.js +0 -2
- package/dist/types/documents.js.map +0 -1
- package/dist/types/hooks.d.ts +0 -122
- package/dist/types/hooks.d.ts.map +0 -1
- package/dist/types/hooks.js +0 -2
- package/dist/types/hooks.js.map +0 -1
- package/dist/types/index.d.ts +0 -13
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/index.js +0 -13
- package/dist/types/index.js.map +0 -1
- package/dist/types/request.d.ts +0 -42
- package/dist/types/request.d.ts.map +0 -1
- package/dist/types/request.js +0 -2
- package/dist/types/request.js.map +0 -1
- package/dist/types/schema-config.d.ts +0 -303
- package/dist/types/schema-config.d.ts.map +0 -1
- package/dist/types/schema-config.js +0 -2
- package/dist/types/schema-config.js.map +0 -1
- package/dist/types/schema-core.d.ts +0 -294
- package/dist/types/schema-core.d.ts.map +0 -1
- package/dist/types/schema-core.js +0 -2
- package/dist/types/schema-core.js.map +0 -1
- package/dist/types/schema-inference.d.ts +0 -73
- package/dist/types/schema-inference.d.ts.map +0 -1
- package/dist/types/schema-inference.js +0 -2
- package/dist/types/schema-inference.js.map +0 -1
- package/dist/types/workflows.d.ts +0 -84
- package/dist/types/workflows.d.ts.map +0 -1
- package/dist/types/workflows.js +0 -7
- package/dist/types/workflows.js.map +0 -1
- package/dist/utils/admin-auth.d.ts +0 -5
- package/dist/utils/admin-auth.d.ts.map +0 -1
- package/dist/utils/admin-auth.js +0 -39
- package/dist/utils/admin-auth.js.map +0 -1
- package/dist/utils/config.d.ts +0 -8
- package/dist/utils/config.d.ts.map +0 -1
- package/dist/utils/config.js +0 -238
- package/dist/utils/config.js.map +0 -1
- package/dist/utils/hooks.d.ts +0 -41
- package/dist/utils/hooks.d.ts.map +0 -1
- package/dist/utils/hooks.js +0 -173
- package/dist/utils/hooks.js.map +0 -1
- package/dist/utils/openapi.d.ts +0 -6
- package/dist/utils/openapi.d.ts.map +0 -1
- package/dist/utils/openapi.js +0 -842
- package/dist/utils/openapi.js.map +0 -1
- package/dist/utils/parse-sort.d.ts +0 -7
- package/dist/utils/parse-sort.d.ts.map +0 -1
- package/dist/utils/parse-sort.js +0 -23
- package/dist/utils/parse-sort.js.map +0 -1
- package/dist/utils/parse-where.d.ts +0 -63
- package/dist/utils/parse-where.d.ts.map +0 -1
- package/dist/utils/parse-where.js +0 -196
- package/dist/utils/parse-where.js.map +0 -1
- package/dist/utils/readonly-db.d.ts +0 -9
- package/dist/utils/readonly-db.d.ts.map +0 -1
- package/dist/utils/readonly-db.js +0 -21
- package/dist/utils/readonly-db.js.map +0 -1
- package/dist/utils/setup-prompt.d.ts +0 -11
- package/dist/utils/setup-prompt.d.ts.map +0 -1
- package/dist/utils/setup-prompt.js +0 -863
- package/dist/utils/setup-prompt.js.map +0 -1
- package/dist/utils/swagger.d.ts +0 -11
- package/dist/utils/swagger.d.ts.map +0 -1
- package/dist/utils/swagger.js +0 -62
- package/dist/utils/swagger.js.map +0 -1
- package/dist/utils/upload-validation.d.ts +0 -23
- package/dist/utils/upload-validation.d.ts.map +0 -1
- package/dist/utils/upload-validation.js +0 -44
- package/dist/utils/upload-validation.js.map +0 -1
- package/dist/utils/where-sanitizer.d.ts +0 -10
- package/dist/utils/where-sanitizer.d.ts.map +0 -1
- package/dist/utils/where-sanitizer.js +0 -67
- package/dist/utils/where-sanitizer.js.map +0 -1
- package/dist/where-sanitizer-7Q4JXMX6.js +0 -57
- package/dist/where-sanitizer-DQIWTQZW.js +0 -50
- package/dist/workflows.d.ts +0 -54
- package/dist/workflows.d.ts.map +0 -1
- package/dist/workflows.js +0 -282
- package/dist/workflows.js.map +0 -1
|
@@ -1,779 +0,0 @@
|
|
|
1
|
-
import { PopulationService } from '../services/population.service.js';
|
|
2
|
-
import { DefaultsService } from '../services/defaults.service.js';
|
|
3
|
-
import { AuditService } from '../services/audit.service.js';
|
|
4
|
-
import { hashPassword, verifyPassword } from '../auth/password.js';
|
|
5
|
-
import { runCollectionHooks, executeFieldBeforeChange, executeFieldAfterRead } from '../utils/hooks.js';
|
|
6
|
-
import { createReadonlyDb } from '../utils/readonly-db.js';
|
|
7
|
-
import { validateUpload } from '../utils/upload-validation.js';
|
|
8
|
-
import { evaluateAccess } from '../auth/jexl.js';
|
|
9
|
-
import { getAdminAuthCollection } from '../utils/admin-auth.js';
|
|
10
|
-
import { WORKFLOW_HISTORY_COLLECTION, createWorkflowDocument, canViewWorkflowDraft, initializeWorkflowDocument, materializeWorkflowDocument, saveWorkflowDraft, transitionWorkflow, } from '../workflows.js';
|
|
11
|
-
export class CollectionController {
|
|
12
|
-
collection;
|
|
13
|
-
constructor(collection) {
|
|
14
|
-
this.collection = collection;
|
|
15
|
-
}
|
|
16
|
-
getDelegatedProvider(c) {
|
|
17
|
-
const config = c.get('config');
|
|
18
|
-
const authCollection = getAdminAuthCollection(config);
|
|
19
|
-
if (!authCollection || this.collection.slug !== authCollection.slug) {
|
|
20
|
-
return null;
|
|
21
|
-
}
|
|
22
|
-
return config.adminAuth?.providers?.find((p) => p.members) || null;
|
|
23
|
-
}
|
|
24
|
-
toHookRequestContext(c) {
|
|
25
|
-
return {
|
|
26
|
-
query: c.req.query(),
|
|
27
|
-
headers: c.req.header(),
|
|
28
|
-
raw: c.req.raw,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
async find(c) {
|
|
32
|
-
const config = c.get('config');
|
|
33
|
-
const db = config.db;
|
|
34
|
-
if (!db)
|
|
35
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
36
|
-
const provider = this.getDelegatedProvider(c);
|
|
37
|
-
if (provider && provider.members?.list) {
|
|
38
|
-
const hookReq = this.toHookRequestContext(c);
|
|
39
|
-
const limit = Number(c.req.query('limit')) || 10;
|
|
40
|
-
const page = Number(c.req.query('page')) || 1;
|
|
41
|
-
const sort = c.req.query('sort') || undefined;
|
|
42
|
-
let where = undefined;
|
|
43
|
-
const whereRaw = c.req.query('where');
|
|
44
|
-
if (whereRaw) {
|
|
45
|
-
try {
|
|
46
|
-
where = JSON.parse(decodeURIComponent(whereRaw));
|
|
47
|
-
}
|
|
48
|
-
catch { }
|
|
49
|
-
}
|
|
50
|
-
const paginatedResult = await provider.members.list({ limit, page, sort, where, req: hookReq });
|
|
51
|
-
const mappedDocs = [];
|
|
52
|
-
for (const m of paginatedResult.docs) {
|
|
53
|
-
let localId = m.id;
|
|
54
|
-
const localDoc = await db.find({
|
|
55
|
-
collection: this.collection.slug,
|
|
56
|
-
where: m.id ? { externalSubject: { equals: m.id } } : { email: { equals: m.email } },
|
|
57
|
-
limit: 1,
|
|
58
|
-
});
|
|
59
|
-
if (localDoc.docs[0]) {
|
|
60
|
-
localId = localDoc.docs[0].id;
|
|
61
|
-
}
|
|
62
|
-
mappedDocs.push({
|
|
63
|
-
...m,
|
|
64
|
-
id: localId,
|
|
65
|
-
externalSubject: m.id,
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
return c.json({
|
|
69
|
-
...paginatedResult,
|
|
70
|
-
docs: mappedDocs,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
73
|
-
const readonlyDb = createReadonlyDb(db);
|
|
74
|
-
const limit = Number(c.req.query('limit')) || 10;
|
|
75
|
-
const page = Number(c.req.query('page')) || 1;
|
|
76
|
-
const depth = c.req.query('depth') !== undefined ? Number(c.req.query('depth')) : 2;
|
|
77
|
-
const sort = c.req.query('sort') || undefined;
|
|
78
|
-
const user = c.get('user');
|
|
79
|
-
let where = undefined;
|
|
80
|
-
const whereRaw = c.req.query('where');
|
|
81
|
-
if (whereRaw) {
|
|
82
|
-
try {
|
|
83
|
-
where = JSON.parse(decodeURIComponent(whereRaw));
|
|
84
|
-
}
|
|
85
|
-
catch {
|
|
86
|
-
// Not valid JSON — fall through without a where clause
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
if (where) {
|
|
90
|
-
if (this.collection.admin?.filterable === false) {
|
|
91
|
-
where = undefined;
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
const { sanitizeWhereClause } = await import('../utils/where-sanitizer.js');
|
|
95
|
-
where = sanitizeWhereClause(where, this.collection.fields);
|
|
96
|
-
// If where ends up being an empty object after sanitization, drop it
|
|
97
|
-
if (Object.keys(where).length === 0) {
|
|
98
|
-
where = undefined;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
// Run beforeRead collection hook
|
|
103
|
-
const beforeReadResult = await runCollectionHooks(this.collection.hooks?.beforeRead, {
|
|
104
|
-
req: c.req,
|
|
105
|
-
query: where,
|
|
106
|
-
user,
|
|
107
|
-
db: readonlyDb,
|
|
108
|
-
});
|
|
109
|
-
if (beforeReadResult !== undefined) {
|
|
110
|
-
where = beforeReadResult;
|
|
111
|
-
}
|
|
112
|
-
// Workflow drafts are never visible to unauthenticated readers. The public
|
|
113
|
-
// response is materialized from the last promoted snapshot below.
|
|
114
|
-
if (this.collection.workflow && !canViewWorkflowDraft(this.collection.workflow, user)) {
|
|
115
|
-
where = where
|
|
116
|
-
? { AND: [where, { __published: { exists: true } }] }
|
|
117
|
-
: { __published: { exists: true } };
|
|
118
|
-
}
|
|
119
|
-
let result = await db.find({
|
|
120
|
-
collection: this.collection.slug,
|
|
121
|
-
limit,
|
|
122
|
-
page,
|
|
123
|
-
sort,
|
|
124
|
-
where,
|
|
125
|
-
});
|
|
126
|
-
// Auto-seeding if empty and initialData is provided
|
|
127
|
-
if (result.total === 0 && this.collection.initialData && !where && page === 1) {
|
|
128
|
-
console.log(`[dyrected/core] Auto-seeding collection "${this.collection.slug}" from config.initialData`);
|
|
129
|
-
for (const data of this.collection.initialData) {
|
|
130
|
-
await db.create({ collection: this.collection.slug, data });
|
|
131
|
-
}
|
|
132
|
-
// Re-fetch result after seeding
|
|
133
|
-
result = await db.find({
|
|
134
|
-
collection: this.collection.slug,
|
|
135
|
-
limit,
|
|
136
|
-
page,
|
|
137
|
-
sort,
|
|
138
|
-
where,
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
result.docs = result.docs
|
|
142
|
-
.map((doc) => this.collection.workflow ? materializeWorkflowDocument(doc, this.collection.workflow, user) : doc)
|
|
143
|
-
.filter((doc) => doc !== null);
|
|
144
|
-
// Run afterRead hooks (both collection and field levels)
|
|
145
|
-
const processedDocs = [];
|
|
146
|
-
const readonlyDbForHooks = createReadonlyDb(db);
|
|
147
|
-
for (const doc of result.docs) {
|
|
148
|
-
const docWithDefaults = DefaultsService.apply(this.collection.fields, doc);
|
|
149
|
-
const docWithCollectionHooks = await runCollectionHooks(this.collection.hooks?.afterRead, {
|
|
150
|
-
doc: docWithDefaults,
|
|
151
|
-
req: c.req,
|
|
152
|
-
user,
|
|
153
|
-
db: readonlyDb,
|
|
154
|
-
});
|
|
155
|
-
const docWithFieldHooks = await executeFieldAfterRead(this.collection.fields, docWithCollectionHooks, user, readonlyDb);
|
|
156
|
-
processedDocs.push(docWithFieldHooks);
|
|
157
|
-
}
|
|
158
|
-
result.docs = processedDocs;
|
|
159
|
-
if (depth > 0) {
|
|
160
|
-
const populationService = new PopulationService(db, config.collections);
|
|
161
|
-
result = await populationService.populateResult(result, this.collection.fields, depth);
|
|
162
|
-
}
|
|
163
|
-
return c.json(result);
|
|
164
|
-
}
|
|
165
|
-
async findOne(c) {
|
|
166
|
-
const config = c.get('config');
|
|
167
|
-
const db = config.db;
|
|
168
|
-
if (!db)
|
|
169
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
170
|
-
const provider = this.getDelegatedProvider(c);
|
|
171
|
-
if (provider && (provider.members?.get || provider.members?.list)) {
|
|
172
|
-
const hookReq = this.toHookRequestContext(c);
|
|
173
|
-
const id = c.req.param('id');
|
|
174
|
-
if (!id)
|
|
175
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
176
|
-
const localDoc = await db.findOne({ collection: this.collection.slug, id });
|
|
177
|
-
const externalSubject = localDoc?.externalSubject || id;
|
|
178
|
-
let member = null;
|
|
179
|
-
if (provider.members.get) {
|
|
180
|
-
member = await provider.members.get({ externalSubject, req: hookReq });
|
|
181
|
-
}
|
|
182
|
-
else if (provider.members.list) {
|
|
183
|
-
const listResult = await provider.members.list({ req: hookReq });
|
|
184
|
-
member = listResult.docs.find((m) => m.id === externalSubject) || null;
|
|
185
|
-
}
|
|
186
|
-
if (!member)
|
|
187
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
188
|
-
return c.json({
|
|
189
|
-
...member,
|
|
190
|
-
id: localDoc ? localDoc.id : member.id,
|
|
191
|
-
externalSubject: member.id,
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
const readonlyDb = createReadonlyDb(db);
|
|
195
|
-
const id = c.req.param('id');
|
|
196
|
-
const depth = c.req.query('depth') !== undefined ? Number(c.req.query('depth')) : 10;
|
|
197
|
-
const user = c.get('user');
|
|
198
|
-
if (!id)
|
|
199
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
200
|
-
let doc = await db.findOne({ collection: this.collection.slug, id });
|
|
201
|
-
if (!doc)
|
|
202
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
203
|
-
if (this.collection.workflow) {
|
|
204
|
-
doc = materializeWorkflowDocument(doc, this.collection.workflow, user);
|
|
205
|
-
if (!doc)
|
|
206
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
207
|
-
}
|
|
208
|
-
const docWithDefaults = DefaultsService.apply(this.collection.fields, doc);
|
|
209
|
-
// Run afterRead hooks
|
|
210
|
-
const docWithCollectionHooks = await runCollectionHooks(this.collection.hooks?.afterRead, {
|
|
211
|
-
doc: docWithDefaults,
|
|
212
|
-
req: c.req,
|
|
213
|
-
user,
|
|
214
|
-
db: readonlyDb,
|
|
215
|
-
});
|
|
216
|
-
const docWithFieldHooks = await executeFieldAfterRead(this.collection.fields, docWithCollectionHooks, user, readonlyDb);
|
|
217
|
-
if (depth > 0 && docWithFieldHooks) {
|
|
218
|
-
const populationService = new PopulationService(db, config.collections);
|
|
219
|
-
const populatedDoc = await populationService.populate({
|
|
220
|
-
data: docWithFieldHooks,
|
|
221
|
-
fields: this.collection.fields,
|
|
222
|
-
currentDepth: 0,
|
|
223
|
-
maxDepth: depth,
|
|
224
|
-
});
|
|
225
|
-
return c.json(populatedDoc);
|
|
226
|
-
}
|
|
227
|
-
return c.json(docWithFieldHooks);
|
|
228
|
-
}
|
|
229
|
-
async create(c) {
|
|
230
|
-
const config = c.get('config');
|
|
231
|
-
const db = config.db;
|
|
232
|
-
if (!db)
|
|
233
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
234
|
-
const provider = this.getDelegatedProvider(c);
|
|
235
|
-
if (provider && provider.members?.create) {
|
|
236
|
-
const hookReq = this.toHookRequestContext(c);
|
|
237
|
-
const contentType = c.req.header('Content-Type') || '';
|
|
238
|
-
if (contentType.toLowerCase().includes('multipart/form-data')) {
|
|
239
|
-
return this.upload(c);
|
|
240
|
-
}
|
|
241
|
-
const body = await c.req.json();
|
|
242
|
-
const member = await provider.members.create({ data: body, req: hookReq });
|
|
243
|
-
return c.json({
|
|
244
|
-
...member,
|
|
245
|
-
id: member.id,
|
|
246
|
-
externalSubject: member.id,
|
|
247
|
-
}, 201);
|
|
248
|
-
}
|
|
249
|
-
const readonlyDb = createReadonlyDb(db);
|
|
250
|
-
const contentType = c.req.header('Content-Type') || '';
|
|
251
|
-
if (contentType.toLowerCase().includes('multipart/form-data')) {
|
|
252
|
-
return this.upload(c);
|
|
253
|
-
}
|
|
254
|
-
const body = await c.req.json();
|
|
255
|
-
const user = c.get('user');
|
|
256
|
-
const now = new Date().toISOString();
|
|
257
|
-
let data = {
|
|
258
|
-
...body,
|
|
259
|
-
createdAt: now,
|
|
260
|
-
updatedAt: now,
|
|
261
|
-
createdBy: user?.sub ?? null,
|
|
262
|
-
updatedBy: user?.sub ?? null,
|
|
263
|
-
};
|
|
264
|
-
if (this.collection.workflow) {
|
|
265
|
-
data = initializeWorkflowDocument(data, this.collection.workflow);
|
|
266
|
-
}
|
|
267
|
-
if (this.collection.auth && data.password) {
|
|
268
|
-
data.password = await hashPassword(data.password);
|
|
269
|
-
}
|
|
270
|
-
// Run beforeChange hooks (field-level then collection-level)
|
|
271
|
-
data = await executeFieldBeforeChange(this.collection.fields, data, null, user, readonlyDb);
|
|
272
|
-
data = await runCollectionHooks(this.collection.hooks?.beforeChange, {
|
|
273
|
-
data,
|
|
274
|
-
req: c.req,
|
|
275
|
-
user,
|
|
276
|
-
operation: 'create',
|
|
277
|
-
db: readonlyDb,
|
|
278
|
-
});
|
|
279
|
-
const doc = this.collection.workflow
|
|
280
|
-
? (await createWorkflowDocument({ config, collection: this.collection, data, user })).doc
|
|
281
|
-
: await db.create({ collection: this.collection.slug, data });
|
|
282
|
-
if (this.collection.audit && db) {
|
|
283
|
-
AuditService.log(db, {
|
|
284
|
-
operation: 'create',
|
|
285
|
-
collection: this.collection.slug,
|
|
286
|
-
documentId: doc.id,
|
|
287
|
-
user: user ? { id: user.sub, collection: user.collection, email: user.email } : undefined,
|
|
288
|
-
before: null,
|
|
289
|
-
after: doc,
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
// Run afterChange collection hooks (full db access)
|
|
293
|
-
await runCollectionHooks(this.collection.hooks?.afterChange, {
|
|
294
|
-
doc,
|
|
295
|
-
user,
|
|
296
|
-
req: c.req,
|
|
297
|
-
operation: 'create',
|
|
298
|
-
db,
|
|
299
|
-
}, { isolated: true });
|
|
300
|
-
// Run afterRead hooks on the returned doc
|
|
301
|
-
const responseDoc = this.collection.workflow
|
|
302
|
-
? materializeWorkflowDocument(doc, this.collection.workflow, user)
|
|
303
|
-
: doc;
|
|
304
|
-
const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
|
|
305
|
-
doc: responseDoc,
|
|
306
|
-
req: c.req,
|
|
307
|
-
user,
|
|
308
|
-
db: readonlyDb,
|
|
309
|
-
});
|
|
310
|
-
const finalDoc = await executeFieldAfterRead(this.collection.fields, readDoc, user, readonlyDb);
|
|
311
|
-
return c.json(finalDoc, 201);
|
|
312
|
-
}
|
|
313
|
-
async upload(c) {
|
|
314
|
-
const config = c.get('config');
|
|
315
|
-
const storage = config.storage;
|
|
316
|
-
if (!storage)
|
|
317
|
-
return c.json({ message: 'Storage not configured' }, 500);
|
|
318
|
-
const db = config.db;
|
|
319
|
-
if (!db)
|
|
320
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
321
|
-
const readonlyDb = createReadonlyDb(db);
|
|
322
|
-
const formData = await c.req.formData();
|
|
323
|
-
const file = formData.get('file');
|
|
324
|
-
if (!file)
|
|
325
|
-
return c.json({ message: 'No file uploaded' }, 400);
|
|
326
|
-
// Enforce the collection's upload restrictions (allowedMimeTypes / maxFileSize)
|
|
327
|
-
// before buffering the file into memory.
|
|
328
|
-
const uploadConfig = typeof this.collection.upload === 'object' ? this.collection.upload : undefined;
|
|
329
|
-
const validationError = validateUpload(file, uploadConfig);
|
|
330
|
-
if (validationError) {
|
|
331
|
-
return c.json({ message: validationError.message }, validationError.status);
|
|
332
|
-
}
|
|
333
|
-
const buffer = new Uint8Array(await file.arrayBuffer());
|
|
334
|
-
const siteId = c.get('siteId');
|
|
335
|
-
const workspaceId = c.get('workspaceId');
|
|
336
|
-
const prefix = workspaceId ? `${workspaceId}/${siteId}` : siteId;
|
|
337
|
-
const fileData = await storage.upload({
|
|
338
|
-
filename: file.name,
|
|
339
|
-
buffer,
|
|
340
|
-
mimeType: file.type,
|
|
341
|
-
prefix,
|
|
342
|
-
});
|
|
343
|
-
const otherData = {};
|
|
344
|
-
formData.forEach((value, key) => {
|
|
345
|
-
if (key !== 'file' && typeof value === 'string') {
|
|
346
|
-
otherData[key] = value;
|
|
347
|
-
}
|
|
348
|
-
});
|
|
349
|
-
const user = c.get('user');
|
|
350
|
-
const now = new Date().toISOString();
|
|
351
|
-
let data = {
|
|
352
|
-
...otherData,
|
|
353
|
-
...fileData,
|
|
354
|
-
createdAt: now,
|
|
355
|
-
updatedAt: now,
|
|
356
|
-
createdBy: user?.sub ?? null,
|
|
357
|
-
updatedBy: user?.sub ?? null,
|
|
358
|
-
};
|
|
359
|
-
// Run beforeChange hooks for upload too
|
|
360
|
-
data = await executeFieldBeforeChange(this.collection.fields, data, null, user, readonlyDb);
|
|
361
|
-
data = await runCollectionHooks(this.collection.hooks?.beforeChange, {
|
|
362
|
-
data,
|
|
363
|
-
req: c.req,
|
|
364
|
-
user,
|
|
365
|
-
operation: 'create',
|
|
366
|
-
db: readonlyDb,
|
|
367
|
-
});
|
|
368
|
-
const doc = await db.create({
|
|
369
|
-
collection: this.collection.slug,
|
|
370
|
-
data,
|
|
371
|
-
});
|
|
372
|
-
// Run afterChange hooks for uploads (full db access)
|
|
373
|
-
await runCollectionHooks(this.collection.hooks?.afterChange, {
|
|
374
|
-
doc,
|
|
375
|
-
user,
|
|
376
|
-
req: c.req,
|
|
377
|
-
operation: 'create',
|
|
378
|
-
db,
|
|
379
|
-
}, { isolated: true });
|
|
380
|
-
// Run afterRead hooks
|
|
381
|
-
const responseDoc = this.collection.workflow
|
|
382
|
-
? materializeWorkflowDocument(doc, this.collection.workflow, user)
|
|
383
|
-
: doc;
|
|
384
|
-
const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
|
|
385
|
-
doc: responseDoc,
|
|
386
|
-
req: c.req,
|
|
387
|
-
user,
|
|
388
|
-
db: readonlyDb,
|
|
389
|
-
});
|
|
390
|
-
const finalDoc = await executeFieldAfterRead(this.collection.fields, readDoc, user, readonlyDb);
|
|
391
|
-
return c.json(finalDoc, 201);
|
|
392
|
-
}
|
|
393
|
-
async update(c) {
|
|
394
|
-
const config = c.get('config');
|
|
395
|
-
const db = config.db;
|
|
396
|
-
if (!db)
|
|
397
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
398
|
-
const provider = this.getDelegatedProvider(c);
|
|
399
|
-
if (provider && provider.members?.update) {
|
|
400
|
-
const hookReq = this.toHookRequestContext(c);
|
|
401
|
-
const id = c.req.param('id');
|
|
402
|
-
if (!id)
|
|
403
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
404
|
-
const body = await c.req.json();
|
|
405
|
-
const localDoc = await db.findOne({ collection: this.collection.slug, id });
|
|
406
|
-
const externalSubject = localDoc?.externalSubject || id;
|
|
407
|
-
const member = await provider.members.update({ externalSubject, data: body, req: hookReq });
|
|
408
|
-
return c.json({
|
|
409
|
-
...member,
|
|
410
|
-
id: localDoc ? localDoc.id : member.id,
|
|
411
|
-
externalSubject: member.id,
|
|
412
|
-
});
|
|
413
|
-
}
|
|
414
|
-
const readonlyDb = createReadonlyDb(db);
|
|
415
|
-
const id = c.req.param('id');
|
|
416
|
-
if (!id)
|
|
417
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
418
|
-
const body = await c.req.json();
|
|
419
|
-
const user = c.get('user');
|
|
420
|
-
// Strip auth-only fields from general updates — use /change-password for that
|
|
421
|
-
let data = { ...body };
|
|
422
|
-
if (this.collection.auth) {
|
|
423
|
-
delete data.password;
|
|
424
|
-
delete data.oldPassword;
|
|
425
|
-
delete data.confirmPassword;
|
|
426
|
-
}
|
|
427
|
-
Object.assign(data, {
|
|
428
|
-
updatedAt: new Date().toISOString(),
|
|
429
|
-
updatedBy: user?.sub ?? null,
|
|
430
|
-
});
|
|
431
|
-
const originalDoc = await db.findOne({ collection: this.collection.slug, id });
|
|
432
|
-
if (!originalDoc)
|
|
433
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
434
|
-
let before = null;
|
|
435
|
-
if (this.collection.audit) {
|
|
436
|
-
before = originalDoc;
|
|
437
|
-
}
|
|
438
|
-
// Run beforeChange hooks (field-level then collection-level)
|
|
439
|
-
data = await executeFieldBeforeChange(this.collection.fields, data, originalDoc, user, readonlyDb);
|
|
440
|
-
data = await runCollectionHooks(this.collection.hooks?.beforeChange, {
|
|
441
|
-
data,
|
|
442
|
-
doc: originalDoc,
|
|
443
|
-
req: c.req,
|
|
444
|
-
user,
|
|
445
|
-
operation: 'update',
|
|
446
|
-
db: readonlyDb,
|
|
447
|
-
});
|
|
448
|
-
const doc = this.collection.workflow
|
|
449
|
-
? (await saveWorkflowDraft({ config, collection: this.collection, id, originalDoc, data, user })).doc
|
|
450
|
-
: await db.update({ collection: this.collection.slug, id, data });
|
|
451
|
-
if (this.collection.audit && db) {
|
|
452
|
-
AuditService.log(db, {
|
|
453
|
-
operation: 'update',
|
|
454
|
-
collection: this.collection.slug,
|
|
455
|
-
documentId: id,
|
|
456
|
-
user: user ? { id: user.sub, collection: user.collection, email: user.email } : undefined,
|
|
457
|
-
before,
|
|
458
|
-
after: doc,
|
|
459
|
-
});
|
|
460
|
-
}
|
|
461
|
-
// Run afterChange collection hooks (full db access)
|
|
462
|
-
await runCollectionHooks(this.collection.hooks?.afterChange, {
|
|
463
|
-
doc,
|
|
464
|
-
previousDoc: originalDoc,
|
|
465
|
-
user,
|
|
466
|
-
req: c.req,
|
|
467
|
-
operation: 'update',
|
|
468
|
-
db,
|
|
469
|
-
}, { isolated: true });
|
|
470
|
-
// Run afterRead hooks
|
|
471
|
-
const readDoc = await runCollectionHooks(this.collection.hooks?.afterRead, {
|
|
472
|
-
doc,
|
|
473
|
-
req: c.req,
|
|
474
|
-
user,
|
|
475
|
-
db: readonlyDb,
|
|
476
|
-
});
|
|
477
|
-
const finalDoc = await executeFieldAfterRead(this.collection.fields, readDoc, user, readonlyDb);
|
|
478
|
-
return c.json(finalDoc);
|
|
479
|
-
}
|
|
480
|
-
async transition(c) {
|
|
481
|
-
const config = c.get('config');
|
|
482
|
-
if (!config.db)
|
|
483
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
484
|
-
if (!this.collection.workflow)
|
|
485
|
-
return c.json({ message: 'Workflows are not enabled for this collection' }, 404);
|
|
486
|
-
const id = c.req.param('id');
|
|
487
|
-
const transitionName = c.req.param('transition');
|
|
488
|
-
const body = await c.req.json().catch(() => ({}));
|
|
489
|
-
try {
|
|
490
|
-
const doc = await transitionWorkflow({
|
|
491
|
-
config,
|
|
492
|
-
collection: this.collection,
|
|
493
|
-
id: id,
|
|
494
|
-
transitionName: transitionName,
|
|
495
|
-
expectedRevision: body.expectedRevision,
|
|
496
|
-
comment: body.comment,
|
|
497
|
-
user: c.get('user'),
|
|
498
|
-
req: { query: c.req.query(), headers: c.req.header(), raw: c.req.raw },
|
|
499
|
-
});
|
|
500
|
-
return c.json(materializeWorkflowDocument(doc, this.collection.workflow, c.get('user')));
|
|
501
|
-
}
|
|
502
|
-
catch (error) {
|
|
503
|
-
const status = typeof error.statusCode === 'number'
|
|
504
|
-
? error.statusCode
|
|
505
|
-
: 500;
|
|
506
|
-
return c.json({ error: true, message: error instanceof Error ? error.message : String(error) }, status);
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
async workflowHistory(c) {
|
|
510
|
-
const config = c.get('config');
|
|
511
|
-
if (!config.db)
|
|
512
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
513
|
-
if (!this.collection.workflow)
|
|
514
|
-
return c.json({ message: 'Workflows are not enabled for this collection' }, 404);
|
|
515
|
-
const documentId = c.req.param('id');
|
|
516
|
-
if (!documentId)
|
|
517
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
518
|
-
const document = await config.db.findOne({ collection: this.collection.slug, id: documentId });
|
|
519
|
-
if (!document)
|
|
520
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
521
|
-
const readAccess = this.collection.access?.read;
|
|
522
|
-
if (readAccess !== undefined && readAccess !== null) {
|
|
523
|
-
const args = { user: c.get('user'), req: c.req, doc: document };
|
|
524
|
-
const result = typeof readAccess === 'function'
|
|
525
|
-
? await readAccess(args)
|
|
526
|
-
: await evaluateAccess(readAccess, args);
|
|
527
|
-
let allowed = result === true;
|
|
528
|
-
if (result && typeof result === 'object') {
|
|
529
|
-
const match = await config.db.find({
|
|
530
|
-
collection: this.collection.slug,
|
|
531
|
-
where: { AND: [{ id: { equals: documentId } }, result] },
|
|
532
|
-
limit: 1,
|
|
533
|
-
});
|
|
534
|
-
allowed = match.total > 0;
|
|
535
|
-
}
|
|
536
|
-
if (!allowed)
|
|
537
|
-
return c.json({ error: true, message: `Access denied: read on ${this.collection.slug}` }, 403);
|
|
538
|
-
}
|
|
539
|
-
const result = await config.db.find({
|
|
540
|
-
collection: WORKFLOW_HISTORY_COLLECTION,
|
|
541
|
-
where: { collection: { equals: this.collection.slug }, documentId: { equals: documentId } },
|
|
542
|
-
sort: '-createdAt',
|
|
543
|
-
limit: Math.min(Number(c.req.query('limit')) || 50, 100),
|
|
544
|
-
});
|
|
545
|
-
return c.json(result);
|
|
546
|
-
}
|
|
547
|
-
/**
|
|
548
|
-
* POST /api/collections/:slug/:id/change-password
|
|
549
|
-
*
|
|
550
|
-
* Dedicated endpoint for password changes. Requires the caller to supply:
|
|
551
|
-
* { oldPassword, newPassword, confirmPassword }
|
|
552
|
-
*
|
|
553
|
-
* Rules:
|
|
554
|
-
* - Only the account owner or an admin may change the password.
|
|
555
|
-
* - Non-admin callers MUST provide a valid oldPassword.
|
|
556
|
-
* - newPassword and confirmPassword must match.
|
|
557
|
-
*/
|
|
558
|
-
async changePassword(c) {
|
|
559
|
-
const config = c.get('config');
|
|
560
|
-
const db = config.db;
|
|
561
|
-
if (!db)
|
|
562
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
563
|
-
if (!this.collection.auth) {
|
|
564
|
-
return c.json({ message: 'This collection does not support authentication' }, 400);
|
|
565
|
-
}
|
|
566
|
-
const id = c.req.param('id');
|
|
567
|
-
if (!id)
|
|
568
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
569
|
-
const user = c.get('user');
|
|
570
|
-
if (!user)
|
|
571
|
-
return c.json({ message: 'Authentication required' }, 401);
|
|
572
|
-
const body = await c.req.json().catch(() => null);
|
|
573
|
-
const { oldPassword, newPassword, confirmPassword } = body ?? {};
|
|
574
|
-
if (!newPassword) {
|
|
575
|
-
return c.json({ message: 'newPassword is required' }, 400);
|
|
576
|
-
}
|
|
577
|
-
if (newPassword !== confirmPassword) {
|
|
578
|
-
return c.json({ message: 'Passwords do not match' }, 400);
|
|
579
|
-
}
|
|
580
|
-
if (newPassword.length < 8) {
|
|
581
|
-
return c.json({ message: 'Password must be at least 8 characters' }, 400);
|
|
582
|
-
}
|
|
583
|
-
const isAdmin = Array.isArray(user.roles) && user.roles.includes('admin');
|
|
584
|
-
const isSelf = user.sub === id;
|
|
585
|
-
if (!isAdmin && !isSelf) {
|
|
586
|
-
return c.json({ message: 'You are not authorised to change this password' }, 403);
|
|
587
|
-
}
|
|
588
|
-
// Non-admins must verify their current password
|
|
589
|
-
if (!isAdmin) {
|
|
590
|
-
if (!oldPassword) {
|
|
591
|
-
return c.json({ message: 'Current password is required' }, 400);
|
|
592
|
-
}
|
|
593
|
-
const existing = await db.findOne({ collection: this.collection.slug, id });
|
|
594
|
-
if (!existing)
|
|
595
|
-
return c.json({ message: 'User not found' }, 404);
|
|
596
|
-
const valid = await verifyPassword(oldPassword, existing.password);
|
|
597
|
-
if (!valid) {
|
|
598
|
-
return c.json({ message: 'Invalid current password' }, 400);
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
const hashed = await hashPassword(newPassword);
|
|
602
|
-
const doc = await db.update({
|
|
603
|
-
collection: this.collection.slug,
|
|
604
|
-
id,
|
|
605
|
-
data: {
|
|
606
|
-
password: hashed,
|
|
607
|
-
updatedAt: new Date().toISOString(),
|
|
608
|
-
updatedBy: user.sub,
|
|
609
|
-
},
|
|
610
|
-
});
|
|
611
|
-
if (this.collection.audit) {
|
|
612
|
-
AuditService.log(db, {
|
|
613
|
-
operation: 'update',
|
|
614
|
-
collection: this.collection.slug,
|
|
615
|
-
documentId: id,
|
|
616
|
-
user: { id: user.sub, collection: user.collection, email: user.email },
|
|
617
|
-
before: null,
|
|
618
|
-
after: { id },
|
|
619
|
-
});
|
|
620
|
-
}
|
|
621
|
-
return c.json({ success: true, message: 'Password updated successfully' });
|
|
622
|
-
}
|
|
623
|
-
async delete(c) {
|
|
624
|
-
const config = c.get('config');
|
|
625
|
-
const db = config.db;
|
|
626
|
-
if (!db)
|
|
627
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
628
|
-
const provider = this.getDelegatedProvider(c);
|
|
629
|
-
if (provider && provider.members?.delete) {
|
|
630
|
-
const hookReq = this.toHookRequestContext(c);
|
|
631
|
-
const id = c.req.param('id');
|
|
632
|
-
if (!id)
|
|
633
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
634
|
-
const localDoc = await db.findOne({ collection: this.collection.slug, id });
|
|
635
|
-
const externalSubject = localDoc?.externalSubject || id;
|
|
636
|
-
await provider.members.delete({ externalSubject, req: hookReq });
|
|
637
|
-
return c.json({ message: 'Deleted' });
|
|
638
|
-
}
|
|
639
|
-
const readonlyDb = createReadonlyDb(db);
|
|
640
|
-
const id = c.req.param('id');
|
|
641
|
-
if (!id)
|
|
642
|
-
return c.json({ message: 'Missing ID' }, 400);
|
|
643
|
-
const user = c.get('user');
|
|
644
|
-
const doc = await db.findOne({ collection: this.collection.slug, id });
|
|
645
|
-
if (!doc)
|
|
646
|
-
return c.json({ message: 'Not Found' }, 404);
|
|
647
|
-
let before = null;
|
|
648
|
-
if (this.collection.audit) {
|
|
649
|
-
before = doc;
|
|
650
|
-
}
|
|
651
|
-
// Run beforeDelete collection hook
|
|
652
|
-
await runCollectionHooks(this.collection.hooks?.beforeDelete, {
|
|
653
|
-
id,
|
|
654
|
-
doc,
|
|
655
|
-
user,
|
|
656
|
-
req: c.req,
|
|
657
|
-
db: readonlyDb,
|
|
658
|
-
});
|
|
659
|
-
await db.delete({ collection: this.collection.slug, id });
|
|
660
|
-
if (this.collection.audit && db) {
|
|
661
|
-
AuditService.log(db, {
|
|
662
|
-
operation: 'delete',
|
|
663
|
-
collection: this.collection.slug,
|
|
664
|
-
documentId: id,
|
|
665
|
-
user: user ? { id: user.sub, collection: user.collection, email: user.email } : undefined,
|
|
666
|
-
before,
|
|
667
|
-
after: null,
|
|
668
|
-
});
|
|
669
|
-
}
|
|
670
|
-
// Run afterDelete collection hook (full db access)
|
|
671
|
-
await runCollectionHooks(this.collection.hooks?.afterDelete, {
|
|
672
|
-
id,
|
|
673
|
-
doc,
|
|
674
|
-
user,
|
|
675
|
-
req: c.req,
|
|
676
|
-
db,
|
|
677
|
-
}, { isolated: true });
|
|
678
|
-
return c.json({ message: 'Deleted' });
|
|
679
|
-
}
|
|
680
|
-
async deleteMany(c) {
|
|
681
|
-
const config = c.get('config');
|
|
682
|
-
const db = config.db;
|
|
683
|
-
if (!db)
|
|
684
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
685
|
-
const readonlyDb = createReadonlyDb(db);
|
|
686
|
-
const user = c.get('user');
|
|
687
|
-
// ids may arrive as a query-string array (?ids[]=a&ids[]=b) or JSON body
|
|
688
|
-
let ids = [];
|
|
689
|
-
try {
|
|
690
|
-
const body = await c.req.json().catch(() => null);
|
|
691
|
-
if (body?.ids && Array.isArray(body.ids)) {
|
|
692
|
-
ids = body.ids;
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
catch {
|
|
696
|
-
// fall through to query-string
|
|
697
|
-
}
|
|
698
|
-
if (!ids.length) {
|
|
699
|
-
const raw = c.req.queries('ids') ?? c.req.queries('ids[]') ?? [];
|
|
700
|
-
ids = raw.filter(Boolean);
|
|
701
|
-
}
|
|
702
|
-
if (!ids.length)
|
|
703
|
-
return c.json({ message: 'No IDs provided' }, 400);
|
|
704
|
-
const deleted = [];
|
|
705
|
-
const failed = [];
|
|
706
|
-
for (const id of ids) {
|
|
707
|
-
try {
|
|
708
|
-
const doc = await db.findOne({ collection: this.collection.slug, id });
|
|
709
|
-
if (!doc) {
|
|
710
|
-
failed.push({ id, error: 'Not Found' });
|
|
711
|
-
continue;
|
|
712
|
-
}
|
|
713
|
-
let before = null;
|
|
714
|
-
if (this.collection.audit) {
|
|
715
|
-
before = doc;
|
|
716
|
-
}
|
|
717
|
-
// Run beforeDelete hooks
|
|
718
|
-
await runCollectionHooks(this.collection.hooks?.beforeDelete, {
|
|
719
|
-
id,
|
|
720
|
-
doc,
|
|
721
|
-
user,
|
|
722
|
-
req: c.req,
|
|
723
|
-
db: readonlyDb,
|
|
724
|
-
});
|
|
725
|
-
await db.delete({ collection: this.collection.slug, id });
|
|
726
|
-
deleted.push(id);
|
|
727
|
-
if (this.collection.audit) {
|
|
728
|
-
AuditService.log(db, {
|
|
729
|
-
operation: 'delete',
|
|
730
|
-
collection: this.collection.slug,
|
|
731
|
-
documentId: id,
|
|
732
|
-
user: user ? { id: user.sub, collection: user.collection, email: user.email } : undefined,
|
|
733
|
-
before,
|
|
734
|
-
after: null,
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
// Run afterDelete hooks (full db access)
|
|
738
|
-
await runCollectionHooks(this.collection.hooks?.afterDelete, {
|
|
739
|
-
id,
|
|
740
|
-
doc,
|
|
741
|
-
user,
|
|
742
|
-
req: c.req,
|
|
743
|
-
db,
|
|
744
|
-
}, { isolated: true });
|
|
745
|
-
}
|
|
746
|
-
catch (err) {
|
|
747
|
-
failed.push({ id, error: err?.message ?? 'Unknown error' });
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
return c.json({
|
|
751
|
-
message: `Deleted ${deleted.length} document(s)`,
|
|
752
|
-
deleted,
|
|
753
|
-
...(failed.length ? { failed } : {}),
|
|
754
|
-
});
|
|
755
|
-
}
|
|
756
|
-
async seed(c) {
|
|
757
|
-
const config = c.get('config');
|
|
758
|
-
const db = config.db;
|
|
759
|
-
if (!db)
|
|
760
|
-
return c.json({ message: 'Database not configured' }, 500);
|
|
761
|
-
const body = await c.req.json();
|
|
762
|
-
const initialData = body.data;
|
|
763
|
-
if (!initialData || !Array.isArray(initialData)) {
|
|
764
|
-
return c.json({ message: 'Invalid initial data' }, 400);
|
|
765
|
-
}
|
|
766
|
-
const result = await db.find({ collection: this.collection.slug, limit: 1 });
|
|
767
|
-
if (result.total > 0) {
|
|
768
|
-
return c.json({ message: 'Collection is not empty, skipping seed' });
|
|
769
|
-
}
|
|
770
|
-
console.log(`[dyrected/core] Auto-seeding collection: ${this.collection.slug}`);
|
|
771
|
-
const createdDocs = [];
|
|
772
|
-
for (const data of initialData) {
|
|
773
|
-
const doc = await db.create({ collection: this.collection.slug, data });
|
|
774
|
-
createdDocs.push(doc);
|
|
775
|
-
}
|
|
776
|
-
return c.json({ message: 'Seed successful', count: createdDocs.length }, 201);
|
|
777
|
-
}
|
|
778
|
-
}
|
|
779
|
-
//# sourceMappingURL=collection.controller.js.map
|