@solidxai/core 0.1.2 → 0.1.5-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/.claude/settings.local.json +8 -0
- package/dist/commands/run-tests.command.d.ts +37 -0
- package/dist/commands/run-tests.command.d.ts.map +1 -0
- package/dist/commands/run-tests.command.js +345 -0
- package/dist/commands/run-tests.command.js.map +1 -0
- package/dist/commands/test-data.command.d.ts +6 -6
- package/dist/commands/test-data.command.d.ts.map +1 -1
- package/dist/commands/test-data.command.js +25 -25
- package/dist/commands/test-data.command.js.map +1 -1
- package/dist/commands/test.command.d.ts +5 -0
- package/dist/commands/test.command.d.ts.map +1 -0
- package/dist/commands/test.command.js +26 -0
- package/dist/commands/test.command.js.map +1 -0
- package/dist/constants/error-messages.d.ts +1 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +1 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/constants.d.ts +3 -3
- package/dist/constants.d.ts.map +1 -1
- package/dist/constants.js +12 -12
- package/dist/constants.js.map +1 -1
- package/dist/controllers/otp-authentication.controller.d.ts +1 -4
- package/dist/controllers/otp-authentication.controller.d.ts.map +1 -1
- package/dist/controllers/otp-authentication.controller.js +1 -1
- package/dist/controllers/role-metadata.controller.d.ts +1 -0
- package/dist/controllers/role-metadata.controller.d.ts.map +1 -1
- package/dist/controllers/role-metadata.controller.js +15 -0
- package/dist/controllers/role-metadata.controller.js.map +1 -1
- package/dist/controllers/service.controller.d.ts +0 -9
- package/dist/controllers/service.controller.d.ts.map +1 -1
- package/dist/controllers/service.controller.js +0 -45
- package/dist/controllers/service.controller.js.map +1 -1
- package/dist/dtos/basic-filters.dto.d.ts.map +1 -1
- package/dist/dtos/basic-filters.dto.js.map +1 -1
- package/dist/dtos/create-email-template.dto.d.ts.map +1 -1
- package/dist/dtos/create-email-template.dto.js.map +1 -1
- package/dist/dtos/create-list-of-values.dto.d.ts.map +1 -1
- package/dist/dtos/create-list-of-values.dto.js.map +1 -1
- package/dist/dtos/create-menu-item-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-menu-item-metadata.dto.js.map +1 -1
- package/dist/dtos/create-role-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-role-metadata.dto.js.map +1 -1
- package/dist/dtos/create-scheduled-job.dto.d.ts.map +1 -1
- package/dist/dtos/create-scheduled-job.dto.js.map +1 -1
- package/dist/dtos/create-security-rule.dto.d.ts.map +1 -1
- package/dist/dtos/create-security-rule.dto.js.map +1 -1
- package/dist/dtos/create-sms-template.dto.d.ts.map +1 -1
- package/dist/dtos/create-sms-template.dto.js.map +1 -1
- package/dist/dtos/create-user.dto.d.ts +1 -0
- package/dist/dtos/create-user.dto.d.ts.map +1 -1
- package/dist/dtos/create-user.dto.js +2 -1
- package/dist/dtos/create-user.dto.js.map +1 -1
- package/dist/dtos/create-view-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-view-metadata.dto.js.map +1 -1
- package/dist/dtos/otp-sign-in.dto.d.ts +1 -1
- package/dist/dtos/otp-sign-in.dto.d.ts.map +1 -1
- package/dist/dtos/otp-sign-in.dto.js +2 -2
- package/dist/dtos/otp-sign-in.dto.js.map +1 -1
- package/dist/dtos/otp-sign-up.dto.d.ts +2 -2
- package/dist/dtos/otp-sign-up.dto.d.ts.map +1 -1
- package/dist/dtos/otp-sign-up.dto.js +2 -2
- package/dist/dtos/otp-sign-up.dto.js.map +1 -1
- package/dist/dtos/resolve-s3-url.dto.d.ts +2 -5
- package/dist/dtos/resolve-s3-url.dto.d.ts.map +1 -1
- package/dist/dtos/resolve-s3-url.dto.js +1 -13
- package/dist/dtos/resolve-s3-url.dto.js.map +1 -1
- package/dist/dtos/sign-up.dto.d.ts.map +1 -1
- package/dist/dtos/sign-up.dto.js.map +1 -1
- package/dist/dtos/update-email-template.dto.d.ts.map +1 -1
- package/dist/dtos/update-email-template.dto.js.map +1 -1
- package/dist/dtos/update-list-of-values.dto.d.ts.map +1 -1
- package/dist/dtos/update-list-of-values.dto.js.map +1 -1
- package/dist/dtos/update-menu-item-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/update-menu-item-metadata.dto.js.map +1 -1
- package/dist/dtos/update-scheduled-job.dto.d.ts.map +1 -1
- package/dist/dtos/update-scheduled-job.dto.js.map +1 -1
- package/dist/dtos/update-security-rule.dto.d.ts.map +1 -1
- package/dist/dtos/update-security-rule.dto.js.map +1 -1
- package/dist/dtos/update-sms-template.dto.d.ts.map +1 -1
- package/dist/dtos/update-sms-template.dto.js.map +1 -1
- package/dist/dtos/update-view-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/update-view-metadata.dto.js.map +1 -1
- package/dist/entities/user.entity.d.ts +1 -0
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +6 -1
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.d.ts +2 -0
- package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js +33 -23
- package/dist/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.js.map +1 -1
- package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.d.ts +3 -0
- package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js +36 -23
- package/dist/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.js.map +1 -1
- package/dist/helpers/security.helper.js +1 -0
- package/dist/helpers/security.helper.js.map +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/repository/solid-base.repository.d.ts +10 -1
- package/dist/repository/solid-base.repository.d.ts.map +1 -1
- package/dist/repository/solid-base.repository.js +109 -0
- package/dist/repository/solid-base.repository.js.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.d.ts +2 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +142 -91
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/module-test-data.service.d.ts.map +1 -1
- package/dist/seeders/module-test-data.service.js +3 -3
- package/dist/seeders/module-test-data.service.js.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.d.ts +1 -1
- package/dist/seeders/permission-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/permission-metadata-seeder.service.js +1 -1
- package/dist/seeders/permission-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +12 -25
- package/dist/services/authentication.service.d.ts +22 -8
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +228 -214
- 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 +18 -2
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +4 -0
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +66 -32
- 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 +7 -4
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/file/disk-file.service.d.ts +0 -2
- package/dist/services/file/disk-file.service.d.ts.map +1 -1
- package/dist/services/file/disk-file.service.js +7 -16
- package/dist/services/file/disk-file.service.js.map +1 -1
- package/dist/services/file/index.d.ts +1 -0
- package/dist/services/file/index.d.ts.map +1 -1
- package/dist/services/file/index.js +1 -0
- package/dist/services/file/index.js.map +1 -1
- package/dist/services/file/storage-path-builder.d.ts +17 -0
- package/dist/services/file/storage-path-builder.d.ts.map +1 -0
- package/dist/{seeders/sms-template-seeder.service.js → services/file/storage-path-builder.js} +45 -35
- package/dist/services/file/storage-path-builder.js.map +1 -0
- package/dist/services/media.service.d.ts +1 -1
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +45 -6
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-s3-storage-provider.js.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.d.ts.map +1 -1
- package/dist/services/mediaStorageProviders/file-storage-provider.js +46 -7
- package/dist/services/mediaStorageProviders/file-storage-provider.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts +4 -6
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +16 -14
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/queues/common.d.ts +3 -0
- package/dist/services/queues/common.d.ts.map +1 -0
- package/dist/services/queues/common.js +39 -0
- package/dist/services/queues/common.js.map +1 -0
- package/dist/services/queues/database-publisher.service.d.ts.map +1 -1
- package/dist/services/queues/database-publisher.service.js +3 -1
- package/dist/services/queues/database-publisher.service.js.map +1 -1
- package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/database-subscriber.service.js +5 -2
- package/dist/services/queues/database-subscriber.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-publisher.service.js +13 -6
- package/dist/services/queues/rabbitmq-publisher.service.js.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
- package/dist/services/queues/rabbitmq-subscriber.service.js +9 -5
- package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
- package/dist/services/setting.service.d.ts +3 -2
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +7 -4
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +24 -2
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +8 -6
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/solid-core.module.d.ts +3 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +49 -9
- package/dist/solid-core.module.js.map +1 -1
- package/dist/testing/__examples__/register-example-specs.d.ts +3 -0
- package/dist/testing/__examples__/register-example-specs.d.ts.map +1 -0
- package/dist/testing/__examples__/register-example-specs.js +8 -0
- package/dist/testing/__examples__/register-example-specs.js.map +1 -0
- package/dist/testing/__examples__/specs/custom-health.spec.d.ts +17 -0
- package/dist/testing/__examples__/specs/custom-health.spec.d.ts.map +1 -0
- package/dist/testing/__examples__/specs/custom-health.spec.js +30 -0
- package/dist/testing/__examples__/specs/custom-health.spec.js.map +1 -0
- package/dist/testing/adapters/api/api-adapter.d.ts +9 -0
- package/dist/testing/adapters/api/api-adapter.d.ts.map +1 -0
- package/dist/testing/adapters/api/api-adapter.js +76 -0
- package/dist/testing/adapters/api/api-adapter.js.map +1 -0
- package/dist/testing/adapters/api/api.types.d.ts +14 -0
- package/dist/testing/adapters/api/api.types.d.ts.map +1 -0
- package/dist/testing/adapters/api/api.types.js +3 -0
- package/dist/testing/adapters/api/api.types.js.map +1 -0
- package/dist/testing/adapters/ui/playwright-adapter.d.ts +14 -0
- package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -0
- package/dist/testing/adapters/ui/playwright-adapter.js +80 -0
- package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -0
- package/dist/testing/adapters/ui/ui.types.d.ts +5 -0
- package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -0
- package/dist/testing/adapters/ui/ui.types.js +3 -0
- package/dist/testing/adapters/ui/ui.types.js.map +1 -0
- package/dist/testing/contracts/runtime-context.types.d.ts +35 -0
- package/dist/testing/contracts/runtime-context.types.d.ts.map +1 -0
- package/dist/testing/contracts/runtime-context.types.js +3 -0
- package/dist/testing/contracts/runtime-context.types.js.map +1 -0
- package/dist/testing/contracts/test-spec.types.d.ts +21 -0
- package/dist/testing/contracts/test-spec.types.d.ts.map +1 -0
- package/dist/testing/contracts/test-spec.types.js +3 -0
- package/dist/testing/contracts/test-spec.types.js.map +1 -0
- package/dist/testing/contracts/testing-metadata.types.d.ts +41 -0
- package/dist/testing/contracts/testing-metadata.types.d.ts.map +1 -0
- package/dist/testing/contracts/testing-metadata.types.js +3 -0
- package/dist/testing/contracts/testing-metadata.types.js.map +1 -0
- package/dist/testing/core/interpolation.d.ts +4 -0
- package/dist/testing/core/interpolation.d.ts.map +1 -0
- package/dist/testing/core/interpolation.js +180 -0
- package/dist/testing/core/interpolation.js.map +1 -0
- package/dist/testing/core/normalize-steps.d.ts +7 -0
- package/dist/testing/core/normalize-steps.d.ts.map +1 -0
- package/dist/testing/core/normalize-steps.js +20 -0
- package/dist/testing/core/normalize-steps.js.map +1 -0
- package/dist/testing/core/resource-store.d.ts +8 -0
- package/dist/testing/core/resource-store.d.ts.map +1 -0
- package/dist/testing/core/resource-store.js +41 -0
- package/dist/testing/core/resource-store.js.map +1 -0
- package/dist/testing/core/spec-registry.d.ts +10 -0
- package/dist/testing/core/spec-registry.d.ts.map +1 -0
- package/dist/testing/core/spec-registry.js +32 -0
- package/dist/testing/core/spec-registry.js.map +1 -0
- package/dist/testing/core/step-registry.d.ts +10 -0
- package/dist/testing/core/step-registry.d.ts.map +1 -0
- package/dist/testing/core/step-registry.js +26 -0
- package/dist/testing/core/step-registry.js.map +1 -0
- package/dist/testing/core/testing-engine.d.ts +14 -0
- package/dist/testing/core/testing-engine.d.ts.map +1 -0
- package/dist/testing/core/testing-engine.js +97 -0
- package/dist/testing/core/testing-engine.js.map +1 -0
- package/dist/testing/core/timeout.d.ts +2 -0
- package/dist/testing/core/timeout.d.ts.map +1 -0
- package/dist/testing/core/timeout.js +18 -0
- package/dist/testing/core/timeout.js.map +1 -0
- package/dist/testing/reporter/attachments.d.ts +4 -0
- package/dist/testing/reporter/attachments.d.ts.map +1 -0
- package/dist/testing/reporter/attachments.js +25 -0
- package/dist/testing/reporter/attachments.js.map +1 -0
- package/dist/testing/reporter/console-reporter.d.ts +45 -0
- package/dist/testing/reporter/console-reporter.d.ts.map +1 -0
- package/dist/testing/reporter/console-reporter.js +189 -0
- package/dist/testing/reporter/console-reporter.js.map +1 -0
- package/dist/testing/reporter/reporter.types.d.ts +37 -0
- package/dist/testing/reporter/reporter.types.d.ts.map +1 -0
- package/dist/testing/reporter/reporter.types.js +3 -0
- package/dist/testing/reporter/reporter.types.js.map +1 -0
- package/dist/testing/runner/lifecycle.d.ts +9 -0
- package/dist/testing/runner/lifecycle.d.ts.map +1 -0
- package/dist/testing/runner/lifecycle.js +33 -0
- package/dist/testing/runner/lifecycle.js.map +1 -0
- package/dist/testing/runner/run-from-metadata.d.ts +24 -0
- package/dist/testing/runner/run-from-metadata.d.ts.map +1 -0
- package/dist/testing/runner/run-from-metadata.js +70 -0
- package/dist/testing/runner/run-from-metadata.js.map +1 -0
- package/dist/testing/runner/scenario-filter.d.ts +9 -0
- package/dist/testing/runner/scenario-filter.d.ts.map +1 -0
- package/dist/testing/runner/scenario-filter.js +22 -0
- package/dist/testing/runner/scenario-filter.js.map +1 -0
- package/dist/testing/steps/api/auth.step.d.ts +3 -0
- package/dist/testing/steps/api/auth.step.d.ts.map +1 -0
- package/dist/testing/steps/api/auth.step.js +38 -0
- package/dist/testing/steps/api/auth.step.js.map +1 -0
- package/dist/testing/steps/api/index.d.ts +3 -0
- package/dist/testing/steps/api/index.d.ts.map +1 -0
- package/dist/testing/steps/api/index.js +10 -0
- package/dist/testing/steps/api/index.js.map +1 -0
- package/dist/testing/steps/api/request.step.d.ts +3 -0
- package/dist/testing/steps/api/request.step.d.ts.map +1 -0
- package/dist/testing/steps/api/request.step.js +281 -0
- package/dist/testing/steps/api/request.step.js.map +1 -0
- package/dist/testing/steps/assert/http.step.d.ts +3 -0
- package/dist/testing/steps/assert/http.step.d.ts.map +1 -0
- package/dist/testing/steps/assert/http.step.js +27 -0
- package/dist/testing/steps/assert/http.step.js.map +1 -0
- package/dist/testing/steps/assert/index.d.ts +3 -0
- package/dist/testing/steps/assert/index.d.ts.map +1 -0
- package/dist/testing/steps/assert/index.js +12 -0
- package/dist/testing/steps/assert/index.js.map +1 -0
- package/dist/testing/steps/assert/jsonpath.step.d.ts +3 -0
- package/dist/testing/steps/assert/jsonpath.step.d.ts.map +1 -0
- package/dist/testing/steps/assert/jsonpath.step.js +40 -0
- package/dist/testing/steps/assert/jsonpath.step.js.map +1 -0
- package/dist/testing/steps/assert/primitives.step.d.ts +3 -0
- package/dist/testing/steps/assert/primitives.step.d.ts.map +1 -0
- package/dist/testing/steps/assert/primitives.step.js +43 -0
- package/dist/testing/steps/assert/primitives.step.js.map +1 -0
- package/dist/testing/steps/test/index.d.ts +3 -0
- package/dist/testing/steps/test/index.d.ts.map +1 -0
- package/dist/testing/steps/test/index.js +8 -0
- package/dist/testing/steps/test/index.js.map +1 -0
- package/dist/testing/steps/test/test-spec.step.d.ts +3 -0
- package/dist/testing/steps/test/test-spec.step.d.ts.map +1 -0
- package/dist/testing/steps/test/test-spec.step.js +41 -0
- package/dist/testing/steps/test/test-spec.step.js.map +1 -0
- package/dist/testing/steps/ui/actions.step.d.ts +3 -0
- package/dist/testing/steps/ui/actions.step.d.ts.map +1 -0
- package/dist/testing/steps/ui/actions.step.js +31 -0
- package/dist/testing/steps/ui/actions.step.js.map +1 -0
- package/dist/testing/steps/ui/assertions.step.d.ts +3 -0
- package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -0
- package/dist/testing/steps/ui/assertions.step.js +41 -0
- package/dist/testing/steps/ui/assertions.step.js.map +1 -0
- package/dist/testing/steps/ui/form.step.d.ts +3 -0
- package/dist/testing/steps/ui/form.step.d.ts.map +1 -0
- package/dist/testing/steps/ui/form.step.js +34 -0
- package/dist/testing/steps/ui/form.step.js.map +1 -0
- package/dist/testing/steps/ui/index.d.ts +3 -0
- package/dist/testing/steps/ui/index.d.ts.map +1 -0
- package/dist/testing/steps/ui/index.js +14 -0
- package/dist/testing/steps/ui/index.js.map +1 -0
- package/dist/testing/steps/ui/navigation.step.d.ts +3 -0
- package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -0
- package/dist/testing/steps/ui/navigation.step.js +39 -0
- package/dist/testing/steps/ui/navigation.step.js.map +1 -0
- package/dist/testing/steps/util/index.d.ts +3 -0
- package/dist/testing/steps/util/index.d.ts.map +1 -0
- package/dist/testing/steps/util/index.js +12 -0
- package/dist/testing/steps/util/index.js.map +1 -0
- package/dist/testing/steps/util/log.step.d.ts +3 -0
- package/dist/testing/steps/util/log.step.d.ts.map +1 -0
- package/dist/testing/steps/util/log.step.js +18 -0
- package/dist/testing/steps/util/log.step.js.map +1 -0
- package/dist/testing/steps/util/require.step.d.ts +3 -0
- package/dist/testing/steps/util/require.step.d.ts.map +1 -0
- package/dist/testing/steps/util/require.step.js +16 -0
- package/dist/testing/steps/util/require.step.js.map +1 -0
- package/dist/testing/steps/util/sleep.step.d.ts +3 -0
- package/dist/testing/steps/util/sleep.step.d.ts.map +1 -0
- package/dist/testing/steps/util/sleep.step.js +13 -0
- package/dist/testing/steps/util/sleep.step.js.map +1 -0
- package/docs/test-data-workflow.md +51 -11
- package/package.json +10 -2
- package/src/commands/run-tests.command.ts +278 -0
- package/src/commands/test-data.command.ts +26 -26
- package/src/commands/test.command.ts +14 -0
- package/src/constants/error-messages.ts +1 -0
- package/src/constants.ts +3 -3
- package/src/controllers/role-metadata.controller.ts +26 -18
- package/src/controllers/service.controller.ts +58 -59
- package/src/dtos/basic-filters.dto.ts +0 -2
- package/src/dtos/create-email-template.dto.ts +7 -0
- package/src/dtos/create-list-of-values.dto.ts +7 -0
- package/src/dtos/create-menu-item-metadata.dto.ts +12 -1
- package/src/dtos/create-role-metadata.dto.ts +9 -0
- package/src/dtos/create-scheduled-job.dto.ts +14 -0
- package/src/dtos/create-security-rule.dto.ts +6 -0
- package/src/dtos/create-sms-template.dto.ts +6 -0
- package/src/dtos/create-user.dto.ts +1 -0
- package/src/dtos/create-view-metadata.dto.ts +11 -0
- package/src/dtos/otp-sign-in.dto.ts +3 -3
- package/src/dtos/otp-sign-up.dto.ts +3 -3
- package/src/dtos/resolve-s3-url.dto.ts +2 -12
- package/src/dtos/sign-up.dto.ts +0 -2
- package/src/dtos/update-email-template.dto.ts +6 -0
- package/src/dtos/update-list-of-values.dto.ts +8 -0
- package/src/dtos/update-menu-item-metadata.dto.ts +12 -0
- package/src/dtos/update-scheduled-job.dto.ts +15 -0
- package/src/dtos/update-security-rule.dto.ts +7 -0
- package/src/dtos/update-sms-template.dto.ts +32 -32
- package/src/dtos/update-view-metadata.dto.ts +12 -0
- package/src/entities/user.entity.ts +3 -0
- package/src/helpers/field-crud-managers/ManyToManyRelationFieldCrudManager.ts +43 -32
- package/src/helpers/field-crud-managers/OneToManyRelationFieldCrudManager.ts +45 -33
- package/src/helpers/security.helper.ts +1 -1
- package/src/index.ts +3 -4
- package/src/repository/solid-base.repository.ts +172 -1
- package/src/seeders/module-metadata-seeder.service.ts +191 -150
- package/src/seeders/module-test-data.service.ts +5 -3
- package/src/seeders/permission-metadata-seeder.service.ts +1 -4
- package/src/seeders/seed-data/solid-core-metadata.json +12 -25
- package/src/services/authentication.service.ts +268 -266
- package/src/services/chatter-message.service.ts +18 -1
- package/src/services/crud-helper.service.ts +79 -36
- package/src/services/crud.service.ts +10 -4
- package/src/services/field-metadata.service.ts +0 -71
- package/src/services/file/disk-file.service.ts +8 -18
- package/src/services/file/index.ts +1 -0
- package/src/services/file/storage-path-builder.ts +56 -0
- package/src/services/media.service.ts +13 -7
- package/src/services/mediaStorageProviders/file-s3-storage-provider.ts +1 -1
- package/src/services/mediaStorageProviders/file-storage-provider.ts +13 -8
- package/src/services/module-metadata.service.ts +18 -15
- package/src/services/queues/common.ts +75 -0
- package/src/services/queues/database-publisher.service.ts +4 -1
- package/src/services/queues/database-subscriber.service.ts +5 -3
- package/src/services/queues/rabbitmq-publisher.service.ts +17 -7
- package/src/services/queues/rabbitmq-subscriber.service.ts +9 -5
- package/src/services/setting.service.ts +5 -3
- package/src/services/settings/default-settings-provider.service.ts +5 -3
- package/src/solid-core.module.ts +20 -12
- package/src/testing/README.md +364 -0
- package/src/testing/__examples__/register-example-specs.ts +6 -0
- package/src/testing/__examples__/specs/custom-health.spec.ts +29 -0
- package/src/testing/__examples__/testing.sample.json +82 -0
- package/src/testing/adapters/api/api-adapter.ts +85 -0
- package/src/testing/adapters/api/api.types.ts +15 -0
- package/src/testing/adapters/ui/playwright-adapter.ts +54 -0
- package/src/testing/adapters/ui/ui.types.ts +4 -0
- package/src/testing/contracts/runtime-context.types.ts +36 -0
- package/src/testing/contracts/test-spec.types.ts +24 -0
- package/src/testing/contracts/testing-metadata.types.ts +46 -0
- package/src/testing/core/interpolation.ts +189 -0
- package/src/testing/core/normalize-steps.ts +21 -0
- package/src/testing/core/resource-store.ts +38 -0
- package/src/testing/core/spec-registry.ts +33 -0
- package/src/testing/core/step-registry.ts +27 -0
- package/src/testing/core/testing-engine.ts +127 -0
- package/src/testing/core/timeout.ts +19 -0
- package/src/testing/reporter/attachments.ts +25 -0
- package/src/testing/reporter/console-reporter.ts +229 -0
- package/src/testing/reporter/reporter.types.ts +36 -0
- package/src/testing/runner/lifecycle.ts +31 -0
- package/src/testing/runner/run-from-metadata.ts +87 -0
- package/src/testing/runner/scenario-filter.ts +33 -0
- package/src/testing/steps/api/auth.step.ts +66 -0
- package/src/testing/steps/api/index.ts +10 -0
- package/src/testing/steps/api/request.step.ts +358 -0
- package/src/testing/steps/assert/http.step.ts +33 -0
- package/src/testing/steps/assert/index.ts +12 -0
- package/src/testing/steps/assert/jsonpath.step.ts +50 -0
- package/src/testing/steps/assert/primitives.step.ts +69 -0
- package/src/testing/steps/test/index.ts +8 -0
- package/src/testing/steps/test/test-spec.step.ts +52 -0
- package/src/testing/steps/ui/actions.step.ts +36 -0
- package/src/testing/steps/ui/assertions.step.ts +54 -0
- package/src/testing/steps/ui/form.step.ts +39 -0
- package/src/testing/steps/ui/index.ts +12 -0
- package/src/testing/steps/ui/navigation.step.ts +53 -0
- package/src/testing/steps/util/index.ts +10 -0
- package/src/testing/steps/util/log.step.ts +19 -0
- package/src/testing/steps/util/require.step.ts +16 -0
- package/src/testing/steps/util/sleep.step.ts +15 -0
- package/tsconfig.json +35 -25
- package/tsconfig.tests.json +14 -0
- package/dist/passport-strategies/local.strategy.d.ts +0 -15
- package/dist/passport-strategies/local.strategy.d.ts.map +0 -1
- package/dist/passport-strategies/local.strategy.js +0 -44
- package/dist/passport-strategies/local.strategy.js.map +0 -1
- package/dist/seeders/email-template-seeder.service.d.ts +0 -10
- package/dist/seeders/email-template-seeder.service.d.ts.map +0 -1
- package/dist/seeders/email-template-seeder.service.js +0 -84
- package/dist/seeders/email-template-seeder.service.js.map +0 -1
- package/dist/seeders/sms-template-seeder.service.d.ts +0 -10
- package/dist/seeders/sms-template-seeder.service.d.ts.map +0 -1
- package/dist/seeders/sms-template-seeder.service.js.map +0 -1
- package/dist/seeders/user-seeder.service.d.ts +0 -10
- package/dist/seeders/user-seeder.service.d.ts.map +0 -1
- package/dist/seeders/user-seeder.service.js +0 -44
- package/dist/seeders/user-seeder.service.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1
- package/src/passport-strategies/local.strategy.ts +0 -28
- package/src/seeders/email-template-seeder.service.ts +0 -49
- package/src/seeders/sms-template-seeder.service.ts +0 -50
- package/src/seeders/user-seeder.service.ts +0 -33
|
@@ -18,9 +18,12 @@ import { ChatterMessageDetails } from '../entities/chatter-message-details.entit
|
|
|
18
18
|
import { ChatterMessage } from '../entities/chatter-message.entity';
|
|
19
19
|
import { getMediaStorageProvider } from './mediaStorageProviders';
|
|
20
20
|
import { RequestContextService } from './request-context.service';
|
|
21
|
-
import {
|
|
21
|
+
import { Logger } from '@nestjs/common';
|
|
22
|
+
|
|
22
23
|
@Injectable()
|
|
23
24
|
export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
25
|
+
private readonly _logger = new Logger(ChatterMessageService.name);
|
|
26
|
+
|
|
24
27
|
constructor(
|
|
25
28
|
@InjectEntityManager()
|
|
26
29
|
readonly entityManager: EntityManager,
|
|
@@ -502,16 +505,23 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
502
505
|
return populatedEntity;
|
|
503
506
|
}
|
|
504
507
|
|
|
508
|
+
private logHeapUsed(label: string) {
|
|
509
|
+
const mb = () => Math.round(process.memoryUsage().heapUsed / 1024 / 1024);
|
|
510
|
+
this._logger.log(`heapUsedMB(${label}): ${mb()}`);
|
|
511
|
+
}
|
|
512
|
+
|
|
505
513
|
// [2026-02-05T23:31:21.025Z] INFO: [200 OK]
|
|
506
514
|
// GET /api/chatter-message/getChatterMessages/216/mswipeBoomboxBulkUpload?populateMedia[0]=messageAttachments&populate[0]=user&populate[1]=chatterMessageDetails&limit=25 22747ms
|
|
507
515
|
async getChatterMessages(entityId: number, entityName: string, query: any) {
|
|
508
516
|
const { limit = 25, offset = 0, populate = [], populateMedia = [], filters } = query;
|
|
517
|
+
this.logHeapUsed('getChatterMessages-start');
|
|
509
518
|
|
|
510
519
|
const model = await this.modelMetadataRepo.findOne({
|
|
511
520
|
where: {
|
|
512
521
|
singularName: entityName
|
|
513
522
|
},
|
|
514
523
|
});
|
|
524
|
+
this.logHeapUsed('getChatterMessages-modelLoaded');
|
|
515
525
|
const oneToManyFields = await this.fieldMetadataRepo.find({
|
|
516
526
|
where: {
|
|
517
527
|
model: { id: model.id },
|
|
@@ -519,11 +529,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
519
529
|
relationType: 'one-to-many'
|
|
520
530
|
}
|
|
521
531
|
});
|
|
532
|
+
this.logHeapUsed('getChatterMessages-oneToManyFieldsLoaded');
|
|
522
533
|
|
|
523
534
|
const relatedEntitiesMap = new Map<string, number[]>();
|
|
524
535
|
|
|
525
536
|
for (const field of oneToManyFields) {
|
|
526
537
|
if (field.enableAuditTracking === false) {
|
|
538
|
+
this._logger.log(`Skipping field ${field.name} for chatter message retrieval because audit tracking is disabled`);
|
|
527
539
|
continue
|
|
528
540
|
}
|
|
529
541
|
const coModelName = field.relationCoModelSingularName;
|
|
@@ -552,8 +564,10 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
552
564
|
relatedEntitiesMap.set(field.name, relatedIds);
|
|
553
565
|
}
|
|
554
566
|
}
|
|
567
|
+
this.logHeapUsed('getChatterMessages-relatedEntitiesLoaded');
|
|
555
568
|
|
|
556
569
|
const qb = await this.repo.createSecurityRuleAwareQueryBuilder('entity');
|
|
570
|
+
this.logHeapUsed('getChatterMessages-queryBuilderReady');
|
|
557
571
|
|
|
558
572
|
const orConditions: string[] = [];
|
|
559
573
|
const parameters: any = {};
|
|
@@ -602,10 +616,13 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
|
|
|
602
616
|
qb.skip(offset).take(limit);
|
|
603
617
|
|
|
604
618
|
const [entities, count] = await qb.getManyAndCount();
|
|
619
|
+
this.logHeapUsed('getChatterMessages-entitiesLoaded');
|
|
605
620
|
|
|
606
621
|
if (populateMedia && populateMedia.length > 0) {
|
|
607
622
|
const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
|
|
623
|
+
this.logHeapUsed('getChatterMessages-beforePopulateMedia');
|
|
608
624
|
await this['handlePopulateMedia'](normalizedPopulateMedia, entities);
|
|
625
|
+
this.logHeapUsed('getChatterMessages-afterPopulateMedia');
|
|
609
626
|
}
|
|
610
627
|
|
|
611
628
|
const currentPage = Math.floor(offset / limit) + 1;
|
|
@@ -3,7 +3,7 @@ import { BasicFilterDto } from "../dtos/basic-filters.dto";
|
|
|
3
3
|
import { classify } from "@angular-devkit/core/src/utils/strings";
|
|
4
4
|
import { ActiveUserData } from "src/interfaces/active-user-data.interface";
|
|
5
5
|
import { SolidRegistry } from "src/helpers/solid-registry";
|
|
6
|
-
import { Logger } from "@nestjs/common";
|
|
6
|
+
import { BadRequestException, Logger } from "@nestjs/common";
|
|
7
7
|
import { ERROR_MESSAGES } from "src/constants/error-messages";
|
|
8
8
|
|
|
9
9
|
export enum FilterCombinator {
|
|
@@ -64,88 +64,102 @@ export class CrudHelperService {
|
|
|
64
64
|
const primaryFilterObj = normalizedFilters[key];
|
|
65
65
|
const normalizedPrimaryFilterObj = this.normalizeObjectKeys(primaryFilterObj);
|
|
66
66
|
|
|
67
|
+
const [rawField, funcAlias] = key.split(':');
|
|
68
|
+
|
|
67
69
|
// Get the operator or field from the key
|
|
68
70
|
const operatorOrField = Object.keys(normalizedPrimaryFilterObj)[0];
|
|
69
71
|
// if the key is an operator, then build the query based on the operator
|
|
70
72
|
if (operatorOrField.startsWith('$')) {
|
|
71
73
|
const operator = operatorOrField;
|
|
72
|
-
|
|
74
|
+
let columnExpression: string | undefined;
|
|
75
|
+
if (funcAlias) {
|
|
76
|
+
try {
|
|
77
|
+
columnExpression = this.buildDateGranularityExpression(this.getDriver(selectQb), `${alias}.${rawField}`, funcAlias);
|
|
78
|
+
} catch {
|
|
79
|
+
throw new BadRequestException(`Unsupported field function '${funcAlias}'. Supported functions are: day, week, month, year.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
this.buildOperatorQuery(qb, alias, rawField, normalizedPrimaryFilterObj, operator, columnExpression);
|
|
73
83
|
return;
|
|
74
84
|
}
|
|
75
85
|
else { // Recursively call the applyFilters method to handle nested conditions
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
86
|
+
if (funcAlias) {
|
|
87
|
+
throw new BadRequestException(`Function alias ':${funcAlias}' is not valid on relation field '${rawField}'. It can only be applied to scalar fields.`);
|
|
88
|
+
}
|
|
89
|
+
const joinField = `${alias}.${rawField}`;
|
|
90
|
+
if (!this.isRelationJoined(selectQb, joinField)) selectQb.leftJoin(joinField, rawField);
|
|
91
|
+
this.applyFilters(qb, primaryFilterObj, rawField, selectQb);
|
|
79
92
|
}
|
|
80
93
|
});
|
|
81
94
|
}
|
|
82
95
|
}
|
|
83
96
|
|
|
84
|
-
private buildOperatorQuery(qb: any, alias: string, field: string, normalizedPrimaryOperatorObj: any, operator: string) {
|
|
97
|
+
private buildOperatorQuery(qb: any, alias: string, field: string, normalizedPrimaryOperatorObj: any, operator: string, columnExpression?: string) {
|
|
85
98
|
const uniqueFieldAlias = `${alias}_${field}_${Math.floor(Math.random() * 1000)}`;
|
|
99
|
+
const colExpr = columnExpression ?? `${alias}.${field}`;
|
|
86
100
|
switch (operator) {
|
|
87
101
|
case '$eq':
|
|
88
|
-
qb.andWhere(`${
|
|
102
|
+
qb.andWhere(`${colExpr} = :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$eq });
|
|
89
103
|
break;
|
|
90
104
|
case '$eqi':
|
|
91
|
-
qb.andWhere(`LOWER(${
|
|
105
|
+
qb.andWhere(`LOWER(${colExpr}) = :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$eqi.toLowerCase() });
|
|
92
106
|
break;
|
|
93
107
|
case '$ne':
|
|
94
|
-
qb.andWhere(`${
|
|
108
|
+
qb.andWhere(`${colExpr} != :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$ne });
|
|
95
109
|
break;
|
|
96
110
|
case '$nei':
|
|
97
|
-
qb.andWhere(`LOWER(${
|
|
111
|
+
qb.andWhere(`LOWER(${colExpr}) != :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$nei.toLowerCase() });
|
|
98
112
|
break;
|
|
99
113
|
case '$gt':
|
|
100
|
-
qb.andWhere(`${
|
|
114
|
+
qb.andWhere(`${colExpr} > :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$gt });
|
|
101
115
|
break;
|
|
102
116
|
case '$gte':
|
|
103
|
-
qb.andWhere(`${
|
|
117
|
+
qb.andWhere(`${colExpr} >= :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$gte });
|
|
104
118
|
break;
|
|
105
119
|
case '$lt':
|
|
106
|
-
qb.andWhere(`${
|
|
120
|
+
qb.andWhere(`${colExpr} < :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$lt });
|
|
107
121
|
break;
|
|
108
122
|
case '$lte':
|
|
109
|
-
qb.andWhere(`${
|
|
123
|
+
qb.andWhere(`${colExpr} <= :${uniqueFieldAlias}`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$lte });
|
|
110
124
|
break;
|
|
111
125
|
case '$in':
|
|
112
|
-
qb.andWhere(`${
|
|
126
|
+
qb.andWhere(`${colExpr} IN (:...${uniqueFieldAlias})`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$in });
|
|
113
127
|
break;
|
|
114
128
|
case '$notIn':
|
|
115
|
-
qb.andWhere(`${
|
|
129
|
+
qb.andWhere(`${colExpr} NOT IN (:...${uniqueFieldAlias})`, { [uniqueFieldAlias]: normalizedPrimaryOperatorObj.$notIn });
|
|
116
130
|
break;
|
|
117
131
|
case '$contains':
|
|
118
|
-
qb.andWhere(`${
|
|
132
|
+
qb.andWhere(`${colExpr} LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$contains}%` });
|
|
119
133
|
break;
|
|
120
134
|
case '$notContains':
|
|
121
|
-
qb.andWhere(`${
|
|
135
|
+
qb.andWhere(`${colExpr} NOT LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$notContains}%` });
|
|
122
136
|
break;
|
|
123
137
|
case '$containsi':
|
|
124
|
-
qb.andWhere(`LOWER(${
|
|
138
|
+
qb.andWhere(`LOWER(${colExpr}) LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$containsi.toLowerCase()}%` });
|
|
125
139
|
break;
|
|
126
140
|
case '$notContainsi':
|
|
127
|
-
qb.andWhere(`LOWER(${
|
|
141
|
+
qb.andWhere(`LOWER(${colExpr}) NOT LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$notContainsi.toLowerCase()}%` });
|
|
128
142
|
break;
|
|
129
143
|
case '$null':
|
|
130
|
-
qb.andWhere(`${
|
|
144
|
+
qb.andWhere(`${colExpr} IS NULL`);
|
|
131
145
|
break;
|
|
132
146
|
case '$notNull':
|
|
133
|
-
qb.andWhere(`${
|
|
147
|
+
qb.andWhere(`${colExpr} IS NOT NULL`);
|
|
134
148
|
break;
|
|
135
149
|
case '$between':
|
|
136
|
-
qb.andWhere(`${
|
|
150
|
+
qb.andWhere(`${colExpr} BETWEEN :${uniqueFieldAlias}0 AND :${uniqueFieldAlias}1`, { [`${uniqueFieldAlias}0`]: normalizedPrimaryOperatorObj.$between[0], [`${uniqueFieldAlias}1`]: normalizedPrimaryOperatorObj.$between[1] });
|
|
137
151
|
break;
|
|
138
152
|
case '$startsWith':
|
|
139
|
-
qb.andWhere(`${
|
|
153
|
+
qb.andWhere(`${colExpr} LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `${normalizedPrimaryOperatorObj.$startsWith}%` });
|
|
140
154
|
break;
|
|
141
155
|
case '$startsWithi':
|
|
142
|
-
qb.andWhere(`LOWER(${
|
|
156
|
+
qb.andWhere(`LOWER(${colExpr}) LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `${normalizedPrimaryOperatorObj.$startsWithi.toLowerCase()}%` });
|
|
143
157
|
break;
|
|
144
158
|
case '$endsWith':
|
|
145
|
-
qb.andWhere(`${
|
|
159
|
+
qb.andWhere(`${colExpr} LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$endsWith}` });
|
|
146
160
|
break;
|
|
147
161
|
case '$endsWithi':
|
|
148
|
-
qb.andWhere(`LOWER(${
|
|
162
|
+
qb.andWhere(`LOWER(${colExpr}) LIKE :${uniqueFieldAlias}`, { [uniqueFieldAlias]: `%${normalizedPrimaryOperatorObj.$endsWithi.toLowerCase()}` });
|
|
149
163
|
break;
|
|
150
164
|
default:
|
|
151
165
|
throw new Error(`Operator ${operator} is not supported`);
|
|
@@ -588,6 +602,27 @@ export class CrudHelperService {
|
|
|
588
602
|
}
|
|
589
603
|
}
|
|
590
604
|
|
|
605
|
+
private getGroupFieldValues(
|
|
606
|
+
group: any,
|
|
607
|
+
groupByFields: string[],
|
|
608
|
+
groupAliasMap: Record<string, string>
|
|
609
|
+
): Array<{ rawVal: any; alias: string; granularity?: string }> {
|
|
610
|
+
return groupByFields
|
|
611
|
+
.map(field => {
|
|
612
|
+
const parts = field.split(':');
|
|
613
|
+
const granularity = parts[1];
|
|
614
|
+
const alias = groupAliasMap[field] ?? this.sanitizeAlias(field.replace(/\./g, '_'));
|
|
615
|
+
const rawVal = group[alias] ?? group[field] ?? group[field.replace(/\./g, '_')];
|
|
616
|
+
return { rawVal, alias, granularity };
|
|
617
|
+
})
|
|
618
|
+
.filter(({ rawVal }) => rawVal !== undefined && rawVal !== null);
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
private normalizeGroupValue(value: any, granularity?: string): any {
|
|
622
|
+
if (!granularity) return value;
|
|
623
|
+
return this.formatGroupValue(value, 'YYYY-MM-DD');
|
|
624
|
+
}
|
|
625
|
+
|
|
591
626
|
getGroupName(
|
|
592
627
|
group: any,
|
|
593
628
|
aggregateAliases: Set<string>,
|
|
@@ -595,22 +630,28 @@ export class CrudHelperService {
|
|
|
595
630
|
groupAliasMap: Record<string, string>,
|
|
596
631
|
groupFormatMap: Record<string, string | undefined>
|
|
597
632
|
): string {
|
|
598
|
-
const
|
|
599
|
-
.map(field => {
|
|
600
|
-
const alias = groupAliasMap[field] ?? this.sanitizeAlias(field.replace(/\./g, '_'));
|
|
601
|
-
const rawVal = group[alias] ?? group[field] ?? group[field.replace(/\./g, '_')];
|
|
602
|
-
return this.formatGroupValue(rawVal, groupFormatMap[alias]);
|
|
603
|
-
})
|
|
604
|
-
.filter(v => v !== undefined && v !== null);
|
|
633
|
+
const fieldValues = this.getGroupFieldValues(group, groupByFields, groupAliasMap);
|
|
605
634
|
|
|
606
|
-
if (
|
|
635
|
+
if (fieldValues.length === 0) {
|
|
607
636
|
return Object.keys(group)
|
|
608
637
|
.filter(key => !this.isAggregateFieldKey(key, aggregateAliases))
|
|
609
638
|
.map(key => group[key])
|
|
610
639
|
.join('_');
|
|
611
640
|
}
|
|
612
641
|
|
|
613
|
-
return
|
|
642
|
+
return fieldValues
|
|
643
|
+
.map(({ rawVal, alias }) => this.formatGroupValue(rawVal, groupFormatMap[alias]))
|
|
644
|
+
.join('_');
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
getGroupValue(
|
|
648
|
+
group: any,
|
|
649
|
+
groupByFields: string[],
|
|
650
|
+
groupAliasMap: Record<string, string>
|
|
651
|
+
): any {
|
|
652
|
+
const fieldValues = this.getGroupFieldValues(group, groupByFields, groupAliasMap);
|
|
653
|
+
if (fieldValues.length === 1) return this.normalizeGroupValue(fieldValues[0].rawVal, fieldValues[0].granularity);
|
|
654
|
+
return fieldValues.map(({ rawVal, granularity }) => this.normalizeGroupValue(rawVal, granularity)).join('_');
|
|
614
655
|
}
|
|
615
656
|
|
|
616
657
|
createGroupRecords(group: any, aggregateAliases: Set<string>, groupData: any, groupByFields: string[], groupAliasMap: Record<string, string>, groupFormatMap: Record<string, string | undefined>) {
|
|
@@ -622,6 +663,7 @@ export class CrudHelperService {
|
|
|
622
663
|
}
|
|
623
664
|
createGroupMeta(group: any, aggregateAliases: Set<string>, groupByFields: string[], groupAliasMap: Record<string, string>, groupFormatMap: Record<string, string | undefined>) {
|
|
624
665
|
const groupName = this.getGroupName(group, aggregateAliases, groupByFields, groupAliasMap, groupFormatMap);
|
|
666
|
+
const groupValue = this.getGroupValue(group, groupByFields, groupAliasMap);
|
|
625
667
|
const groupAggregateValues = {}
|
|
626
668
|
for (const key in group) {
|
|
627
669
|
if (group.hasOwnProperty(key) && this.isAggregateFieldKey(key, aggregateAliases)) {
|
|
@@ -631,6 +673,7 @@ export class CrudHelperService {
|
|
|
631
673
|
}
|
|
632
674
|
return {
|
|
633
675
|
groupName,
|
|
676
|
+
groupValue,
|
|
634
677
|
...groupAggregateValues
|
|
635
678
|
};
|
|
636
679
|
}
|
|
@@ -67,6 +67,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
67
67
|
protected get discoveryService(): DiscoveryService {
|
|
68
68
|
return this._discoveryService ??= this.moduleRef.get(DiscoveryService, { strict: false });
|
|
69
69
|
}
|
|
70
|
+
|
|
70
71
|
protected get settingService(): SettingService {
|
|
71
72
|
return this._settingService ??= this.moduleRef.get(SettingService, { strict: false });
|
|
72
73
|
}
|
|
@@ -128,8 +129,8 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
128
129
|
});
|
|
129
130
|
}
|
|
130
131
|
|
|
131
|
-
private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false, isUpdate: boolean = false) {
|
|
132
|
-
const fieldManager: FieldCrudManager = await this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate);
|
|
132
|
+
private async validateAndTransformDto(field: FieldMetadata, dto: any, files: Express.Multer.File[], hasMediaFields: boolean, isPartialUpdate: boolean = false, isUpdate: boolean = false, entityId?: number) {
|
|
133
|
+
const fieldManager: FieldCrudManager = await this.fieldCrudManager(field, this.entityManager, isPartialUpdate, isUpdate, entityId);
|
|
133
134
|
const validationErrors = fieldManager.validate(dto, files);
|
|
134
135
|
const errors = (validationErrors instanceof Promise) ? await validationErrors : validationErrors;
|
|
135
136
|
if (errors.length > 0) {
|
|
@@ -210,7 +211,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
210
211
|
// 2. Loop through the fields with a switch statement
|
|
211
212
|
// 3. Handle the fields based on field type
|
|
212
213
|
for (const field of fieldsToProcess) {
|
|
213
|
-
const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate, isUpdate);
|
|
214
|
+
const transformed = await this.validateAndTransformDto(field, updateDto, files, hasMediaFields, isPartialUpdate, isUpdate, id);
|
|
214
215
|
updateDto = transformed.dto;
|
|
215
216
|
hasMediaFields = transformed.hasMediaFields;
|
|
216
217
|
}
|
|
@@ -220,6 +221,8 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
220
221
|
const mergedEntity = this.repo.merge(entity, updateDto);
|
|
221
222
|
const savedEntity = await this.repo.save(mergedEntity) as T;
|
|
222
223
|
|
|
224
|
+
//FIXME: Skip the many-to-many, and instead fire differential updates and avoid loading the entire association graph for the ids
|
|
225
|
+
|
|
223
226
|
// 6. Save the media
|
|
224
227
|
if (hasMediaFields) {
|
|
225
228
|
await this.saveMedia(model, files, savedEntity);
|
|
@@ -286,7 +289,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
286
289
|
}
|
|
287
290
|
}
|
|
288
291
|
|
|
289
|
-
private async fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false, isUpdate: boolean = false) {
|
|
292
|
+
private async fieldCrudManager(fieldMetadata: FieldMetadata, entityManager: EntityManager, isPartialUpdate: boolean = false, isUpdate: boolean = false, entityId?: number) {
|
|
290
293
|
const commonOptions = { required: fieldMetadata.required && !isPartialUpdate, fieldName: fieldMetadata.name, isUpdate };
|
|
291
294
|
switch (fieldMetadata.type) {
|
|
292
295
|
case SolidFieldType.shortText: {
|
|
@@ -377,6 +380,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
377
380
|
entityManager,
|
|
378
381
|
inverseFieldName: fieldMetadata.relationCoModelFieldName,
|
|
379
382
|
inverseRelationCoModelFieldName: fieldMetadata.name,
|
|
383
|
+
entityId,
|
|
380
384
|
}
|
|
381
385
|
return new OneToManyRelationFieldCrudManager(oneToManyOptions);
|
|
382
386
|
}
|
|
@@ -389,6 +393,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
389
393
|
isInverseSide: false,
|
|
390
394
|
entityManager,
|
|
391
395
|
fieldName: fieldMetadata.name,
|
|
396
|
+
entityId,
|
|
392
397
|
}
|
|
393
398
|
return new ManyToManyRelationFieldCrudManager(manyToManyOptions);
|
|
394
399
|
}
|
|
@@ -401,6 +406,7 @@ export class CRUDService<T extends CommonEntity> { // Add two generic value i.e
|
|
|
401
406
|
entityManager,
|
|
402
407
|
fieldName: fieldMetadata.relationCoModelFieldName,
|
|
403
408
|
relationCoModelFieldName: fieldMetadata.name,
|
|
409
|
+
entityId,
|
|
404
410
|
}
|
|
405
411
|
return new ManyToManyRelationFieldCrudManager(inverseManyToManyOptions);
|
|
406
412
|
}
|
|
@@ -1290,77 +1290,6 @@ export class FieldMetadataService implements OnApplicationBootstrap {
|
|
|
1290
1290
|
return fieldObject;
|
|
1291
1291
|
}
|
|
1292
1292
|
|
|
1293
|
-
// async resolveS3Url(resolveS3UrlDto: ResolveS3UrlDto) {
|
|
1294
|
-
|
|
1295
|
-
// const { modelName, fieldName, fieldValue, s3KeyFieldName } = resolveS3UrlDto;
|
|
1296
|
-
|
|
1297
|
-
// // ------------------------------------------------
|
|
1298
|
-
// // 1. Load model metadata
|
|
1299
|
-
// // ------------------------------------------------
|
|
1300
|
-
// const modelRepo = this.dataSource.getRepository(ModelMetadata);
|
|
1301
|
-
// const model = await modelRepo.findOne({
|
|
1302
|
-
// where: { singularName: modelName },
|
|
1303
|
-
// relations: ['fields']
|
|
1304
|
-
// });
|
|
1305
|
-
|
|
1306
|
-
// if (!model) {
|
|
1307
|
-
// throw new NotFoundException(`Model ${modelName} not found`);
|
|
1308
|
-
// }
|
|
1309
|
-
|
|
1310
|
-
// // ------------------------------------------------
|
|
1311
|
-
// // 2. Validate the field we are filtering by
|
|
1312
|
-
// // ------------------------------------------------
|
|
1313
|
-
// const filterFieldMeta = model.fields.find(f => f.name === fieldName);
|
|
1314
|
-
// if (!filterFieldMeta) {
|
|
1315
|
-
// throw new NotFoundException(
|
|
1316
|
-
// `Field ${fieldName} not found in model ${modelName}`
|
|
1317
|
-
// );
|
|
1318
|
-
// }
|
|
1319
|
-
|
|
1320
|
-
// // ------------------------------------------------
|
|
1321
|
-
// // 3. Load the actual entity repository
|
|
1322
|
-
// // ------------------------------------------------
|
|
1323
|
-
// const entityRepo = this.dataSource.getRepository(model.singularName);
|
|
1324
|
-
|
|
1325
|
-
// // ------------------------------------------------
|
|
1326
|
-
// // 4. Query using fieldName = fieldValue
|
|
1327
|
-
// // ------------------------------------------------
|
|
1328
|
-
// const record = await entityRepo.findOne({
|
|
1329
|
-
// where: { [fieldName]: fieldValue }
|
|
1330
|
-
// });
|
|
1331
|
-
|
|
1332
|
-
// if (!record) {
|
|
1333
|
-
// throw new NotFoundException(
|
|
1334
|
-
// `${modelName} record not found for ${fieldName}="${fieldValue}"`
|
|
1335
|
-
// );
|
|
1336
|
-
// }
|
|
1337
|
-
|
|
1338
|
-
// // ------------------------------------------------
|
|
1339
|
-
// // 5. Extract S3 key from s3KeyFieldName
|
|
1340
|
-
// // ------------------------------------------------
|
|
1341
|
-
// const s3Key = record[s3KeyFieldName];
|
|
1342
|
-
|
|
1343
|
-
// if (!s3Key) {
|
|
1344
|
-
// throw new NotFoundException(
|
|
1345
|
-
// `Field "${s3KeyFieldName}" has no value in ${modelName}.${fieldName}="${fieldValue}"`
|
|
1346
|
-
// );
|
|
1347
|
-
// }
|
|
1348
|
-
|
|
1349
|
-
// // ------------------------------------------------
|
|
1350
|
-
// // 6. Generate signed or public URL
|
|
1351
|
-
// // ------------------------------------------------
|
|
1352
|
-
// let url = "";
|
|
1353
|
-
|
|
1354
|
-
// // TODO - get
|
|
1355
|
-
// if (resolveS3UrlDto.isPrivate == "true") {
|
|
1356
|
-
// const expiryInSeconds = 60 * 60;
|
|
1357
|
-
// url = await this.fileService.getSignedUrl(s3Key, expiryInSeconds, resolveS3UrlDto.bucketName);
|
|
1358
|
-
// } else {
|
|
1359
|
-
// url = `https://${resolveS3UrlDto.bucketName}.s3.${this.configService.get('S3_AWS_REGION_NAME')}.amazonaws.com/${s3Key}`;
|
|
1360
|
-
// }
|
|
1361
|
-
// return { url: url }
|
|
1362
|
-
// }
|
|
1363
|
-
|
|
1364
1293
|
async resolveS3Url(resolveS3UrlDto: ResolveS3UrlDto) {
|
|
1365
1294
|
let url = "";
|
|
1366
1295
|
const normalizedKey = this.normalizeS3Key(resolveS3UrlDto.s3Key);
|
|
@@ -9,25 +9,17 @@ import { IFileService, WriteOptions, CopyOptions, UrlOptions } from './file-serv
|
|
|
9
9
|
/**
|
|
10
10
|
* Disk-based implementation of IFileService.
|
|
11
11
|
* Handles file operations on the local filesystem.
|
|
12
|
+
* Callers are responsible for providing complete paths (use DiskStoragePathBuilder for primary storage paths).
|
|
12
13
|
*/
|
|
13
14
|
@Injectable()
|
|
14
15
|
export class DiskFileService implements IFileService {
|
|
15
16
|
private readonly logger = new Logger(DiskFileService.name);
|
|
16
|
-
private readonly fileStorageDir: string;
|
|
17
17
|
private readonly baseUrl: string;
|
|
18
18
|
|
|
19
19
|
constructor() {
|
|
20
|
-
this.fileStorageDir = process.env.AB_MEDIA_FILE_STORAGE_DIR || 'uploads';
|
|
21
20
|
this.baseUrl = process.env.BASE_URL || '';
|
|
22
21
|
}
|
|
23
22
|
|
|
24
|
-
private resolvePath(filePath: string): string {
|
|
25
|
-
if (path.isAbsolute(filePath)) {
|
|
26
|
-
return filePath;
|
|
27
|
-
}
|
|
28
|
-
return `${this.fileStorageDir}/${filePath}`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
23
|
/**
|
|
32
24
|
* Read file contents as Buffer
|
|
33
25
|
*/
|
|
@@ -50,10 +42,9 @@ export class DiskFileService implements IFileService {
|
|
|
50
42
|
* @returns Public URL of the written file
|
|
51
43
|
*/
|
|
52
44
|
async write(filePath: string, data: Buffer | string, options?: WriteOptions): Promise<string> {
|
|
53
|
-
|
|
54
|
-
await
|
|
55
|
-
|
|
56
|
-
return `${this.baseUrl}/${resolvedPath}`;
|
|
45
|
+
await this.ensureDirectoryExists(filePath);
|
|
46
|
+
await fsPromises.writeFile(filePath, data);
|
|
47
|
+
return `${this.baseUrl}/${filePath}`;
|
|
57
48
|
}
|
|
58
49
|
|
|
59
50
|
/**
|
|
@@ -62,12 +53,11 @@ export class DiskFileService implements IFileService {
|
|
|
62
53
|
* @returns Public URL of the written file
|
|
63
54
|
*/
|
|
64
55
|
async writeStream(filePath: string, stream: Readable, options?: WriteOptions): Promise<string> {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
const writeStream = fs.createWriteStream(resolvedPath);
|
|
56
|
+
await this.ensureDirectoryExists(filePath);
|
|
57
|
+
const writeStream = fs.createWriteStream(filePath);
|
|
68
58
|
await pipeline(stream, writeStream);
|
|
69
|
-
this.logger.debug(`File saved via stream: ${
|
|
70
|
-
return `${this.baseUrl}/${
|
|
59
|
+
this.logger.debug(`File saved via stream: ${filePath}`);
|
|
60
|
+
return `${this.baseUrl}/${filePath}`;
|
|
71
61
|
}
|
|
72
62
|
|
|
73
63
|
/**
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { Injectable, Provider } from '@nestjs/common';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { DEFAULT_MEDIA_FILE_STORAGE_DIR } from '../settings/default-settings-provider.service';
|
|
4
|
+
|
|
5
|
+
export const FILE_STORAGE_PATH_BUILDER = Symbol('FILE_STORAGE_PATH_BUILDER');
|
|
6
|
+
|
|
7
|
+
export interface IStoragePathBuilder {
|
|
8
|
+
build(fileName: string): string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
@Injectable()
|
|
12
|
+
export class DiskStoragePathBuilder implements IStoragePathBuilder {
|
|
13
|
+
private readonly base: string;
|
|
14
|
+
|
|
15
|
+
constructor() {
|
|
16
|
+
this.base = process.env.AB_MEDIA_FILE_STORAGE_DIR || DEFAULT_MEDIA_FILE_STORAGE_DIR;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
build(fileName: string): string {
|
|
20
|
+
if (path.isAbsolute(fileName) || fileName.startsWith(`${this.base}/`)) {
|
|
21
|
+
return fileName;
|
|
22
|
+
}
|
|
23
|
+
return `${this.base}/${fileName}`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
@Injectable()
|
|
28
|
+
export class S3StoragePathBuilder implements IStoragePathBuilder {
|
|
29
|
+
private readonly bucket: string;
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
this.bucket = process.env.S3_DEFAULT_BUCKET ?? '';
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
build(fileName: string): string {
|
|
36
|
+
if (fileName.includes(':')) {
|
|
37
|
+
return fileName;
|
|
38
|
+
}
|
|
39
|
+
return `${this.bucket}:${fileName}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export const StoragePathBuilderFactory: Provider = {
|
|
44
|
+
provide: FILE_STORAGE_PATH_BUILDER,
|
|
45
|
+
useFactory: (disk: DiskStoragePathBuilder, s3: S3StoragePathBuilder): IStoragePathBuilder => {
|
|
46
|
+
const defaultService = process.env.DEFAULT_FILE_SERVICE ?? 'disk';
|
|
47
|
+
switch (defaultService.toLowerCase()) {
|
|
48
|
+
case 's3':
|
|
49
|
+
return s3;
|
|
50
|
+
case 'disk':
|
|
51
|
+
default:
|
|
52
|
+
return disk;
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
inject: [DiskStoragePathBuilder, S3StoragePathBuilder],
|
|
56
|
+
};
|
|
@@ -2,6 +2,8 @@ import { forwardRef, Inject, Injectable, NotFoundException } from '@nestjs/commo
|
|
|
2
2
|
import { ModuleRef } from "@nestjs/core";
|
|
3
3
|
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
4
4
|
import { EntityManager, In } from 'typeorm';
|
|
5
|
+
import * as path from 'path';
|
|
6
|
+
import { DEFAULT_MEDIA_FILE_STORAGE_DIR } from "src/services/settings/default-settings-provider.service";
|
|
5
7
|
import type { SolidCoreSetting } from "src/services/settings/default-settings-provider.service";
|
|
6
8
|
|
|
7
9
|
import { ConfigService } from '@nestjs/config';
|
|
@@ -52,7 +54,7 @@ export class MediaService extends CRUDService<Media> {
|
|
|
52
54
|
|
|
53
55
|
for (const media of data.records) {
|
|
54
56
|
if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.Filesystem) {
|
|
55
|
-
media.relativeUri = `${this.settingService.getConfigValue<SolidCoreSetting>("baseUrl")}/${
|
|
57
|
+
media.relativeUri = `${this.settingService.getConfigValue<SolidCoreSetting>("baseUrl")}/${this.getFullFilePathForDisk(media.relativeUri)}`;
|
|
56
58
|
} else if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.AwsS3) {
|
|
57
59
|
media.relativeUri = this.getAwsS3FullFilePath(
|
|
58
60
|
media.relativeUri,
|
|
@@ -63,7 +65,7 @@ export class MediaService extends CRUDService<Media> {
|
|
|
63
65
|
}
|
|
64
66
|
// data.records.forEach((media: Media) => {
|
|
65
67
|
// if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.Filesystem) {
|
|
66
|
-
// media.relativeUri = `${process.env.BASE_URL}/${
|
|
68
|
+
// media.relativeUri = `${process.env.BASE_URL}/${this.getFileSysytemFullFilePath(media.relativeUri)}`;
|
|
67
69
|
// } else if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.AwsS3) {
|
|
68
70
|
// media.relativeUri = this.getAwsS3FullFilePath(
|
|
69
71
|
// media.relativeUri,
|
|
@@ -78,7 +80,7 @@ export class MediaService extends CRUDService<Media> {
|
|
|
78
80
|
for (const group of data.groupRecords) {
|
|
79
81
|
for (const media of group.groupData.records) {
|
|
80
82
|
if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.Filesystem) {
|
|
81
|
-
media.relativeUri = `${this.settingService.getConfigValue<SolidCoreSetting>("baseUrl")}/${
|
|
83
|
+
media.relativeUri = `${this.settingService.getConfigValue<SolidCoreSetting>("baseUrl")}/${this.getFullFilePathForDisk(media.relativeUri)}`;
|
|
82
84
|
}
|
|
83
85
|
else if (media.mediaStorageProviderMetadata?.type === MediaStorageProviderType.AwsS3) {
|
|
84
86
|
media.relativeUri = this.getAwsS3FullFilePath(media.relativeUri, media.mediaStorageProviderMetadata.bucketName, media.mediaStorageProviderMetadata.region);
|
|
@@ -129,7 +131,7 @@ export class MediaService extends CRUDService<Media> {
|
|
|
129
131
|
|
|
130
132
|
switch (createDto.mediaStorageProviderMetadata.type) {
|
|
131
133
|
case MediaStorageProviderType.Filesystem:
|
|
132
|
-
const fileStoragePath =
|
|
134
|
+
const fileStoragePath = this.getFullFilePathForDisk(this.getFileName(file));
|
|
133
135
|
await this.diskFileService.copy(file.path, fileStoragePath);
|
|
134
136
|
createDto['relativeUri'] = this.getFileName(file);
|
|
135
137
|
break;
|
|
@@ -189,9 +191,13 @@ export class MediaService extends CRUDService<Media> {
|
|
|
189
191
|
}
|
|
190
192
|
//TODO: Move this to a app builder config
|
|
191
193
|
|
|
192
|
-
private
|
|
193
|
-
const
|
|
194
|
-
|
|
194
|
+
private getFullFilePathForDisk(fileName: string): string {
|
|
195
|
+
const base = this.settingService.getConfigValue<SolidCoreSetting>("fileStorageDir")
|
|
196
|
+
|| DEFAULT_MEDIA_FILE_STORAGE_DIR;
|
|
197
|
+
if (path.isAbsolute(fileName) || fileName.startsWith(`${base}/`)) {
|
|
198
|
+
return fileName;
|
|
199
|
+
}
|
|
200
|
+
return `${base}/${fileName}`;
|
|
195
201
|
}
|
|
196
202
|
|
|
197
203
|
private getAwsS3FullFilePath(awsMediaurl: string, bucketName: string, regionName: string): string {
|
|
@@ -43,7 +43,7 @@ export class FileS3StorageProvider<T> implements MediaStorageProvider<T> {
|
|
|
43
43
|
const region = this.getEffectiveRegion(storageMeta.region);
|
|
44
44
|
if (storageMeta.isPublic === false) {
|
|
45
45
|
// Generate signed URL
|
|
46
|
-
const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60;
|
|
46
|
+
const expiryInSeconds = (storageMeta.signedUrlExpiry ?? 60) * 60;
|
|
47
47
|
m['_full_url'] = await this.s3FileService.getUrl(`${storageMeta?.bucketName}:${m.relativeUri}`, { expiresIn: expiryInSeconds, region });
|
|
48
48
|
} else {
|
|
49
49
|
// Public S3 or local filesystem: use normal URL
|