@tstdl/base 0.93.182 → 0.93.183
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/api/server/api-request-token.provider.js +1 -1
- package/api/server/gateway.js +6 -1
- package/authentication/authentication.api.d.ts +13 -40
- package/authentication/authentication.api.js +5 -14
- package/authentication/client/authentication.service.d.ts +6 -14
- package/authentication/client/authentication.service.js +22 -4
- package/authentication/client/module.d.ts +1 -1
- package/authentication/client/module.js +4 -4
- package/authentication/models/index.d.ts +1 -0
- package/authentication/models/index.js +1 -0
- package/authentication/models/totp-results.model.d.ts +11 -0
- package/authentication/models/totp-results.model.js +37 -0
- package/authentication/server/authentication.api-controller.d.ts +3 -3
- package/authentication/server/authentication.api-controller.js +31 -4
- package/authentication/server/authentication.service.d.ts +5 -14
- package/authentication/server/authentication.service.js +6 -4
- package/core.d.ts +0 -5
- package/core.js +0 -8
- package/document-management/api/document-management.api.d.ts +2 -2
- package/document-management/service-models/document.service-model.d.ts +1 -1
- package/examples/config.d.ts +25 -0
- package/examples/config.js +26 -0
- package/notification/server/module.d.ts +1 -1
- package/notification/server/module.js +1 -1
- package/package.json +5 -5
- package/signals/api.d.ts +5 -1
- package/signals/api.js +3 -1
- package/signals/implementation/api.d.ts +13 -5
- package/signals/implementation/api.js +7 -1
- package/signals/implementation/asserts.d.ts +2 -2
- package/signals/implementation/asserts.js +3 -3
- package/signals/implementation/computed.d.ts +7 -34
- package/signals/implementation/computed.js +14 -83
- package/signals/implementation/configure.js +6 -2
- package/signals/implementation/effect.d.ts +65 -46
- package/signals/implementation/effect.js +97 -62
- package/signals/implementation/index.d.ts +2 -4
- package/signals/implementation/index.js +2 -4
- package/signals/implementation/linked_signal.d.ts +36 -0
- package/signals/implementation/linked_signal.js +34 -0
- package/signals/implementation/primitive/computed.d.ts +55 -0
- package/signals/implementation/primitive/computed.js +107 -0
- package/signals/implementation/primitive/effect.d.ts +26 -0
- package/signals/implementation/primitive/effect.js +31 -0
- package/signals/implementation/{equality.d.ts → primitive/equality.d.ts} +1 -1
- package/signals/implementation/{equality.js → primitive/equality.js} +1 -1
- package/signals/implementation/primitive/errors.d.ts +10 -0
- package/signals/implementation/{errors.js → primitive/errors.js} +3 -4
- package/signals/implementation/primitive/formatter.d.ts +19 -0
- package/signals/implementation/primitive/formatter.js +136 -0
- package/signals/implementation/{graph.d.ts → primitive/graph.d.ts} +68 -36
- package/signals/implementation/primitive/graph.js +386 -0
- package/signals/implementation/primitive/linked_signal.d.ts +46 -0
- package/signals/implementation/primitive/linked_signal.js +110 -0
- package/signals/implementation/primitive/signal.d.ts +31 -0
- package/signals/implementation/primitive/signal.js +80 -0
- package/signals/implementation/primitive/untracked.d.ts +12 -0
- package/signals/implementation/primitive/untracked.js +23 -0
- package/signals/implementation/{watch.d.ts → primitive/watch.d.ts} +1 -2
- package/signals/implementation/{watch.js → primitive/watch.js} +22 -16
- package/signals/implementation/resource/api.d.ts +275 -0
- package/signals/implementation/resource/api.js +26 -0
- package/signals/implementation/resource/debounce.d.ts +13 -0
- package/signals/implementation/resource/debounce.js +113 -0
- package/signals/implementation/resource/from_snapshots.d.ts +16 -0
- package/signals/implementation/resource/from_snapshots.js +44 -0
- package/signals/implementation/resource/index.d.ts +11 -0
- package/signals/implementation/resource/index.js +11 -0
- package/signals/implementation/resource/resource.d.ts +110 -0
- package/signals/implementation/resource/resource.js +402 -0
- package/signals/implementation/root_effect_scheduler.d.ts +50 -0
- package/signals/implementation/root_effect_scheduler.js +66 -0
- package/signals/implementation/signal.d.ts +42 -18
- package/signals/implementation/signal.js +29 -49
- package/signals/implementation/to-observable.d.ts +12 -5
- package/signals/implementation/to-observable.js +12 -2
- package/signals/implementation/to-signal.d.ts +9 -18
- package/signals/implementation/to-signal.js +46 -13
- package/signals/implementation/untracked.d.ts +1 -1
- package/signals/implementation/untracked.js +3 -11
- package/signals/operators/debounce.d.ts +8 -0
- package/signals/operators/debounce.js +19 -0
- package/signals/operators/derive-async.js +43 -15
- package/signals/operators/index.d.ts +2 -0
- package/signals/operators/index.js +2 -0
- package/signals/operators/throttle.d.ts +8 -0
- package/signals/operators/throttle.js +31 -0
- package/ai/genkit/tests/multi-region.test.d.ts +0 -2
- package/ai/genkit/tests/multi-region.test.js +0 -179
- package/ai/genkit/tests/token-limit-fallback.test.d.ts +0 -2
- package/ai/genkit/tests/token-limit-fallback.test.js +0 -209
- package/ai/prompts/tests/prompt-builder.test.d.ts +0 -1
- package/ai/prompts/tests/prompt-builder.test.js +0 -22
- package/ai/tests/instructions-formatter.test.d.ts +0 -1
- package/ai/tests/instructions-formatter.test.js +0 -116
- package/ai/tests/steering.test.d.ts +0 -1
- package/ai/tests/steering.test.js +0 -37
- package/api/client/tests/api-client.test.d.ts +0 -1
- package/api/client/tests/api-client.test.js +0 -194
- package/api/server/tests/csrf.middleware.test.d.ts +0 -1
- package/api/server/tests/csrf.middleware.test.js +0 -91
- package/authentication/tests/authentication-password-requirements.validator.test.d.ts +0 -1
- package/authentication/tests/authentication-password-requirements.validator.test.js +0 -29
- package/authentication/tests/authentication.api-controller.test.d.ts +0 -1
- package/authentication/tests/authentication.api-controller.test.js +0 -156
- package/authentication/tests/authentication.api-request-token.provider.test.d.ts +0 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +0 -48
- package/authentication/tests/authentication.client-error-handling.test.d.ts +0 -1
- package/authentication/tests/authentication.client-error-handling.test.js +0 -123
- package/authentication/tests/authentication.client-middleware.test.d.ts +0 -1
- package/authentication/tests/authentication.client-middleware.test.js +0 -118
- package/authentication/tests/authentication.client-service-methods.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-methods.test.js +0 -177
- package/authentication/tests/authentication.client-service-refresh.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service-refresh.test.js +0 -153
- package/authentication/tests/authentication.client-service.test.d.ts +0 -1
- package/authentication/tests/authentication.client-service.test.js +0 -76
- package/authentication/tests/authentication.refresh-busy-loop.test.d.ts +0 -1
- package/authentication/tests/authentication.refresh-busy-loop.test.js +0 -84
- package/authentication/tests/authentication.service.test.d.ts +0 -1
- package/authentication/tests/authentication.service.test.js +0 -167
- package/authentication/tests/authentication.test-ancillary-service.d.ts +0 -9
- package/authentication/tests/authentication.test-ancillary-service.js +0 -27
- package/authentication/tests/brute-force-protection.test.d.ts +0 -1
- package/authentication/tests/brute-force-protection.test.js +0 -211
- package/authentication/tests/helper.test.d.ts +0 -1
- package/authentication/tests/helper.test.js +0 -122
- package/authentication/tests/password-requirements.error.test.d.ts +0 -1
- package/authentication/tests/password-requirements.error.test.js +0 -14
- package/authentication/tests/remember.api.test.d.ts +0 -1
- package/authentication/tests/remember.api.test.js +0 -117
- package/authentication/tests/remember.service.test.d.ts +0 -1
- package/authentication/tests/remember.service.test.js +0 -83
- package/authentication/tests/subject.service.test.d.ts +0 -1
- package/authentication/tests/subject.service.test.js +0 -140
- package/authentication/tests/suspended-subject.test.d.ts +0 -1
- package/authentication/tests/suspended-subject.test.js +0 -120
- package/authentication/tests/totp.enrollment.test.d.ts +0 -1
- package/authentication/tests/totp.enrollment.test.js +0 -123
- package/authentication/tests/totp.login.test.d.ts +0 -1
- package/authentication/tests/totp.login.test.js +0 -213
- package/authentication/tests/totp.recovery-codes.test.d.ts +0 -1
- package/authentication/tests/totp.recovery-codes.test.js +0 -97
- package/authentication/tests/totp.status.test.d.ts +0 -1
- package/authentication/tests/totp.status.test.js +0 -72
- package/cancellation/tests/coverage.test.d.ts +0 -1
- package/cancellation/tests/coverage.test.js +0 -49
- package/cancellation/tests/leak.test.d.ts +0 -1
- package/cancellation/tests/leak.test.js +0 -35
- package/cancellation/tests/token.test.d.ts +0 -1
- package/cancellation/tests/token.test.js +0 -136
- package/circuit-breaker/tests/circuit-breaker.test.d.ts +0 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +0 -116
- package/cryptography/tests/cryptography.test.d.ts +0 -1
- package/cryptography/tests/cryptography.test.js +0 -175
- package/cryptography/tests/jwt.test.d.ts +0 -1
- package/cryptography/tests/jwt.test.js +0 -54
- package/cryptography/tests/modern.test.d.ts +0 -1
- package/cryptography/tests/modern.test.js +0 -105
- package/cryptography/tests/module.test.d.ts +0 -1
- package/cryptography/tests/module.test.js +0 -100
- package/cryptography/tests/totp.test.d.ts +0 -1
- package/cryptography/tests/totp.test.js +0 -108
- package/document-management/tests/ai-config-hierarchy.test.d.ts +0 -1
- package/document-management/tests/ai-config-hierarchy.test.js +0 -59
- package/document-management/tests/ai-config-integration.test.d.ts +0 -1
- package/document-management/tests/ai-config-integration.test.js +0 -125
- package/document-management/tests/ai-config-merge.test.d.ts +0 -1
- package/document-management/tests/ai-config-merge.test.js +0 -46
- package/document-management/tests/document-management-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-management-ai-overrides.test.js +0 -63
- package/document-management/tests/document-management-core.test.d.ts +0 -1
- package/document-management/tests/document-management-core.test.js +0 -157
- package/document-management/tests/document-management.api.test.d.ts +0 -1
- package/document-management/tests/document-management.api.test.js +0 -101
- package/document-management/tests/document-statistics.service.test.d.ts +0 -1
- package/document-management/tests/document-statistics.service.test.js +0 -498
- package/document-management/tests/document-validation-ai-overrides.test.d.ts +0 -1
- package/document-management/tests/document-validation-ai-overrides.test.js +0 -87
- package/document-management/tests/document.service.test.d.ts +0 -1
- package/document-management/tests/document.service.test.js +0 -143
- package/document-management/tests/enum-helpers.test.d.ts +0 -1
- package/document-management/tests/enum-helpers.test.js +0 -452
- package/document-management/tests/helper.d.ts +0 -24
- package/document-management/tests/helper.js +0 -39
- package/errors/tests/format.test.d.ts +0 -1
- package/errors/tests/format.test.js +0 -84
- package/http/tests/server-timing.test.d.ts +0 -1
- package/http/tests/server-timing.test.js +0 -42
- package/injector/tests/advanced.test.d.ts +0 -1
- package/injector/tests/advanced.test.js +0 -116
- package/injector/tests/async-init.test.d.ts +0 -1
- package/injector/tests/async-init.test.js +0 -77
- package/injector/tests/basic.test.d.ts +0 -1
- package/injector/tests/basic.test.js +0 -114
- package/injector/tests/hierarchical.test.d.ts +0 -1
- package/injector/tests/hierarchical.test.js +0 -59
- package/injector/tests/leak.test.d.ts +0 -1
- package/injector/tests/leak.test.js +0 -45
- package/injector/tests/lifecycles.test.d.ts +0 -1
- package/injector/tests/lifecycles.test.js +0 -109
- package/logger/tests/pretty-print.test.d.ts +0 -1
- package/logger/tests/pretty-print.test.js +0 -60
- package/notification/tests/notification-api.test.d.ts +0 -1
- package/notification/tests/notification-api.test.js +0 -124
- package/notification/tests/notification-client.test.d.ts +0 -1
- package/notification/tests/notification-client.test.js +0 -101
- package/notification/tests/notification-flow.test.d.ts +0 -1
- package/notification/tests/notification-flow.test.js +0 -296
- package/notification/tests/notification-sse.service.test.d.ts +0 -1
- package/notification/tests/notification-sse.service.test.js +0 -43
- package/notification/tests/notification-type.service.test.d.ts +0 -1
- package/notification/tests/notification-type.service.test.js +0 -41
- package/object-storage/s3/tests/s3.object-storage.integration.test.d.ts +0 -1
- package/object-storage/s3/tests/s3.object-storage.integration.test.js +0 -303
- package/orm/tests/build-jsonb.test.d.ts +0 -1
- package/orm/tests/build-jsonb.test.js +0 -39
- package/orm/tests/data-types.test.d.ts +0 -1
- package/orm/tests/data-types.test.js +0 -39
- package/orm/tests/database-extension.test.d.ts +0 -1
- package/orm/tests/database-extension.test.js +0 -63
- package/orm/tests/database-migration.test.d.ts +0 -1
- package/orm/tests/database-migration.test.js +0 -83
- package/orm/tests/decorators.test.d.ts +0 -1
- package/orm/tests/decorators.test.js +0 -77
- package/orm/tests/encryption.test.d.ts +0 -1
- package/orm/tests/encryption.test.js +0 -31
- package/orm/tests/query-complex.test.d.ts +0 -1
- package/orm/tests/query-complex.test.js +0 -172
- package/orm/tests/query-converter-complex.test.d.ts +0 -1
- package/orm/tests/query-converter-complex.test.js +0 -131
- package/orm/tests/query-converter.test.d.ts +0 -1
- package/orm/tests/query-converter.test.js +0 -123
- package/orm/tests/repository-advanced.test.d.ts +0 -1
- package/orm/tests/repository-advanced.test.js +0 -189
- package/orm/tests/repository-attributes.test.d.ts +0 -1
- package/orm/tests/repository-attributes.test.js +0 -83
- package/orm/tests/repository-compound-primary-key.test.d.ts +0 -2
- package/orm/tests/repository-compound-primary-key.test.js +0 -226
- package/orm/tests/repository-comprehensive.test.d.ts +0 -1
- package/orm/tests/repository-comprehensive.test.js +0 -162
- package/orm/tests/repository-coverage.test.d.ts +0 -2
- package/orm/tests/repository-coverage.test.js +0 -242
- package/orm/tests/repository-cti-complex.test.d.ts +0 -1
- package/orm/tests/repository-cti-complex.test.js +0 -151
- package/orm/tests/repository-cti-embedded.test.d.ts +0 -1
- package/orm/tests/repository-cti-embedded.test.js +0 -178
- package/orm/tests/repository-cti-extensive.test.d.ts +0 -2
- package/orm/tests/repository-cti-extensive.test.js +0 -279
- package/orm/tests/repository-cti-mapping.test.d.ts +0 -2
- package/orm/tests/repository-cti-mapping.test.js +0 -108
- package/orm/tests/repository-cti-search.test.d.ts +0 -1
- package/orm/tests/repository-cti-search.test.js +0 -141
- package/orm/tests/repository-cti-soft-delete.test.d.ts +0 -2
- package/orm/tests/repository-cti-soft-delete.test.js +0 -103
- package/orm/tests/repository-cti-transactions.test.d.ts +0 -1
- package/orm/tests/repository-cti-transactions.test.js +0 -112
- package/orm/tests/repository-cti-upsert-many.test.d.ts +0 -2
- package/orm/tests/repository-cti-upsert-many.test.js +0 -115
- package/orm/tests/repository-cti.test.d.ts +0 -2
- package/orm/tests/repository-cti.test.js +0 -390
- package/orm/tests/repository-edge-cases.test.d.ts +0 -1
- package/orm/tests/repository-edge-cases.test.js +0 -178
- package/orm/tests/repository-expiration.test.d.ts +0 -2
- package/orm/tests/repository-expiration.test.js +0 -140
- package/orm/tests/repository-extra-coverage.test.d.ts +0 -2
- package/orm/tests/repository-extra-coverage.test.js +0 -402
- package/orm/tests/repository-mapping.test.d.ts +0 -2
- package/orm/tests/repository-mapping.test.js +0 -65
- package/orm/tests/repository-regression.test.d.ts +0 -1
- package/orm/tests/repository-regression.test.js +0 -288
- package/orm/tests/repository-search-coverage.test.d.ts +0 -1
- package/orm/tests/repository-search-coverage.test.js +0 -107
- package/orm/tests/repository-search.test.d.ts +0 -1
- package/orm/tests/repository-search.test.js +0 -105
- package/orm/tests/repository-soft-delete.test.d.ts +0 -1
- package/orm/tests/repository-soft-delete.test.js +0 -118
- package/orm/tests/repository-transactions-nested.test.d.ts +0 -1
- package/orm/tests/repository-transactions-nested.test.js +0 -178
- package/orm/tests/repository-types.test.d.ts +0 -1
- package/orm/tests/repository-types.test.js +0 -184
- package/orm/tests/repository-undelete.test.d.ts +0 -2
- package/orm/tests/repository-undelete.test.js +0 -201
- package/orm/tests/schema-converter.test.d.ts +0 -1
- package/orm/tests/schema-converter.test.js +0 -82
- package/orm/tests/schema-generation.test.d.ts +0 -2
- package/orm/tests/schema-generation.test.js +0 -174
- package/orm/tests/sql-helpers.test.d.ts +0 -1
- package/orm/tests/sql-helpers.test.js +0 -67
- package/orm/tests/transaction-safety.test.d.ts +0 -1
- package/orm/tests/transaction-safety.test.js +0 -81
- package/orm/tests/transactional.test.d.ts +0 -1
- package/orm/tests/transactional.test.js +0 -215
- package/orm/tests/utils.test.d.ts +0 -1
- package/orm/tests/utils.test.js +0 -70
- package/pdf/tests/utils.test.d.ts +0 -1
- package/pdf/tests/utils.test.js +0 -187
- package/process/tests/spawn.test.d.ts +0 -1
- package/process/tests/spawn.test.js +0 -182
- package/rate-limit/tests/postgres-rate-limiter.test.d.ts +0 -1
- package/rate-limit/tests/postgres-rate-limiter.test.js +0 -84
- package/renderer/tests/renderer.test.d.ts +0 -1
- package/renderer/tests/renderer.test.js +0 -88
- package/rpc/tests/rpc.integration.test.d.ts +0 -1
- package/rpc/tests/rpc.integration.test.js +0 -615
- package/signals/implementation/errors.d.ts +0 -2
- package/signals/implementation/graph.js +0 -312
- package/signals/implementation/writable-signal.d.ts +0 -48
- package/signals/implementation/writable-signal.js +0 -32
- package/task-queue/tests/coverage-branch.test.d.ts +0 -1
- package/task-queue/tests/coverage-branch.test.js +0 -395
- package/task-queue/tests/coverage-enhancement.test.d.ts +0 -1
- package/task-queue/tests/coverage-enhancement.test.js +0 -150
- package/task-queue/tests/dag.test.d.ts +0 -1
- package/task-queue/tests/dag.test.js +0 -188
- package/task-queue/tests/dependencies.test.d.ts +0 -1
- package/task-queue/tests/dependencies.test.js +0 -296
- package/task-queue/tests/enqueue-batch.test.d.ts +0 -1
- package/task-queue/tests/enqueue-batch.test.js +0 -125
- package/task-queue/tests/enqueue-item.test.d.ts +0 -1
- package/task-queue/tests/enqueue-item.test.js +0 -12
- package/task-queue/tests/fan-out-spawning.test.d.ts +0 -1
- package/task-queue/tests/fan-out-spawning.test.js +0 -94
- package/task-queue/tests/idempotent-replacement.test.d.ts +0 -1
- package/task-queue/tests/idempotent-replacement.test.js +0 -114
- package/task-queue/tests/missing-idempotent-tasks.test.d.ts +0 -1
- package/task-queue/tests/missing-idempotent-tasks.test.js +0 -39
- package/task-queue/tests/optimization-edge-cases.test.d.ts +0 -1
- package/task-queue/tests/optimization-edge-cases.test.js +0 -124
- package/task-queue/tests/queue-generic.test.d.ts +0 -1
- package/task-queue/tests/queue-generic.test.js +0 -8
- package/task-queue/tests/queue.test.d.ts +0 -1
- package/task-queue/tests/queue.test.js +0 -756
- package/task-queue/tests/shutdown.test.d.ts +0 -1
- package/task-queue/tests/shutdown.test.js +0 -41
- package/task-queue/tests/task-context.test.d.ts +0 -1
- package/task-queue/tests/task-context.test.js +0 -7
- package/task-queue/tests/task-union.test.d.ts +0 -1
- package/task-queue/tests/task-union.test.js +0 -18
- package/task-queue/tests/transactions.test.d.ts +0 -1
- package/task-queue/tests/transactions.test.js +0 -47
- package/task-queue/tests/typing.test.d.ts +0 -1
- package/task-queue/tests/typing.test.js +0 -9
- package/task-queue/tests/worker.test.d.ts +0 -1
- package/task-queue/tests/worker.test.js +0 -258
- package/task-queue/tests/zombie-parent.test.d.ts +0 -1
- package/task-queue/tests/zombie-parent.test.js +0 -45
- package/task-queue/tests/zombie-recovery.test.d.ts +0 -1
- package/task-queue/tests/zombie-recovery.test.js +0 -51
- package/utils/tests/backoff.test.d.ts +0 -1
- package/utils/tests/backoff.test.js +0 -41
- package/utils/tests/retry-with-backoff.test.d.ts +0 -1
- package/utils/tests/retry-with-backoff.test.js +0 -49
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { GenkitModuleOptions } from '../../ai/genkit/module.js';
|
|
3
|
-
import { runInInjectionContext } from '../../injector/index.js';
|
|
4
|
-
import { ObjectStorage } from '../../object-storage/index.js';
|
|
5
|
-
import { TaskQueue } from '../../task-queue/index.js';
|
|
6
|
-
import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
|
|
7
|
-
import { DocumentManagementAuthorizationService } from '../authorization/document-management-authorization.service.js';
|
|
8
|
-
import { DocumentManagementApiController } from '../server/api/document-management.api.js';
|
|
9
|
-
import { configureDocumentManagement } from '../server/configure.js';
|
|
10
|
-
import { DocumentCollectionService } from '../server/services/document-collection.service.js';
|
|
11
|
-
import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
|
|
12
|
-
import { DocumentService } from '../server/services/document.service.js';
|
|
13
|
-
import { TestDocumentManagementAncillaryService, TestDocumentManagementAuthorizationService } from './helper.js';
|
|
14
|
-
describe('DocumentManagementApi Stats', () => {
|
|
15
|
-
let injector;
|
|
16
|
-
let database;
|
|
17
|
-
let controller;
|
|
18
|
-
let documentService;
|
|
19
|
-
let collectionService;
|
|
20
|
-
const schema = 'document_management';
|
|
21
|
-
const tenantId = crypto.randomUUID();
|
|
22
|
-
beforeAll(async () => {
|
|
23
|
-
({ injector, database } = await setupIntegrationTest({
|
|
24
|
-
modules: { taskQueue: false, messageBus: true, documentManagement: true },
|
|
25
|
-
orm: { schema },
|
|
26
|
-
}));
|
|
27
|
-
injector.register(GenkitModuleOptions, { useValue: {} });
|
|
28
|
-
injector.register(DocumentManagementAiService, { useValue: { extractContent: vi.fn(), classifyDocumentType: vi.fn(), extractData: vi.fn(), findSuitableCollectionsForDocument: vi.fn(), findSuitableRequestForDocument: vi.fn() } });
|
|
29
|
-
injector.register(ObjectStorage, {
|
|
30
|
-
useValue: {
|
|
31
|
-
uploadObject: vi.fn(),
|
|
32
|
-
getDownloadUrl: vi.fn(),
|
|
33
|
-
getContent: vi.fn(),
|
|
34
|
-
getContentStream: vi.fn(),
|
|
35
|
-
getObject: vi.fn(),
|
|
36
|
-
exists: vi.fn(),
|
|
37
|
-
},
|
|
38
|
-
});
|
|
39
|
-
injector.register(TaskQueue, {
|
|
40
|
-
useValue: {
|
|
41
|
-
enqueue: vi.fn(),
|
|
42
|
-
enqueueMany: vi.fn(),
|
|
43
|
-
process: vi.fn(),
|
|
44
|
-
},
|
|
45
|
-
});
|
|
46
|
-
configureDocumentManagement({
|
|
47
|
-
ancillaryService: TestDocumentManagementAncillaryService,
|
|
48
|
-
authorizationService: TestDocumentManagementAuthorizationService,
|
|
49
|
-
fileObjectStorageModule: 'documents',
|
|
50
|
-
fileUploadObjectStorageModule: 'document-uploads',
|
|
51
|
-
filePreviewObjectStorageModule: 'document-previews',
|
|
52
|
-
injector,
|
|
53
|
-
});
|
|
54
|
-
controller = await injector.resolveAsync(DocumentManagementApiController);
|
|
55
|
-
documentService = await injector.resolveAsync(DocumentService);
|
|
56
|
-
collectionService = await injector.resolveAsync(DocumentCollectionService);
|
|
57
|
-
});
|
|
58
|
-
afterAll(async () => {
|
|
59
|
-
await injector?.dispose();
|
|
60
|
-
});
|
|
61
|
-
beforeEach(async () => {
|
|
62
|
-
await clearTenantData(database, schema, ['collection_assignment', 'workflow', 'document', 'collection', 'tag', 'type', 'category'], tenantId);
|
|
63
|
-
});
|
|
64
|
-
test('getStatistics API endpoint', async () => {
|
|
65
|
-
await runInInjectionContext(injector, async () => {
|
|
66
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
67
|
-
const authService = injector.resolve(DocumentManagementAuthorizationService);
|
|
68
|
-
vi.spyOn(authService, 'getTenantId').mockResolvedValue(tenantId);
|
|
69
|
-
await documentService.create(tenantId, {
|
|
70
|
-
assignment: { collections: [collection.id] },
|
|
71
|
-
skipWorkflow: true,
|
|
72
|
-
}, new Uint8Array([1, 2, 3]));
|
|
73
|
-
const mockContext = {
|
|
74
|
-
getToken: async () => ({ payload: { tenantId } }),
|
|
75
|
-
parameters: {
|
|
76
|
-
includeTotalCount: true,
|
|
77
|
-
includeStorageUsage: true,
|
|
78
|
-
collectionIds: [collection.id],
|
|
79
|
-
},
|
|
80
|
-
};
|
|
81
|
-
const stats = await controller.getStatistics(mockContext);
|
|
82
|
-
expect(stats.totalCount).toBe(1);
|
|
83
|
-
expect(stats.storageUsage).toBe(3);
|
|
84
|
-
});
|
|
85
|
-
});
|
|
86
|
-
test('getStatistics API endpoint should deny access if collection is restricted', async () => {
|
|
87
|
-
await runInInjectionContext(injector, async () => {
|
|
88
|
-
const authService = injector.resolve(DocumentManagementAuthorizationService);
|
|
89
|
-
vi.spyOn(authService, 'getTenantId').mockResolvedValue(tenantId);
|
|
90
|
-
vi.spyOn(authService, 'canReadCollection').mockResolvedValue(false);
|
|
91
|
-
const mockContext = {
|
|
92
|
-
getToken: async () => ({ payload: { tenantId } }),
|
|
93
|
-
parameters: {
|
|
94
|
-
includeTotalCount: true,
|
|
95
|
-
collectionIds: ['some-collection-id'],
|
|
96
|
-
},
|
|
97
|
-
};
|
|
98
|
-
await expect(controller.getStatistics(mockContext)).rejects.toThrow('You are not allowed to read collection some-collection-id');
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,498 +0,0 @@
|
|
|
1
|
-
import { afterAll, beforeAll, beforeEach, describe, expect, test, vi } from 'vitest';
|
|
2
|
-
import { GenkitModuleOptions } from '../../ai/genkit/module.js';
|
|
3
|
-
import { runInInjectionContext } from '../../injector/index.js';
|
|
4
|
-
import { ObjectStorage } from '../../object-storage/index.js';
|
|
5
|
-
import { getRepository } from '../../orm/server/index.js';
|
|
6
|
-
import { clearTenantData, setupIntegrationTest } from '../../testing/index.js';
|
|
7
|
-
import { DocumentValidationDefinition } from '../models/document-validation-definition.model.js';
|
|
8
|
-
import { DocumentValidationExecution, DocumentValidationExecutionState, DocumentValidationResultStatus } from '../models/document-validation-execution.model.js';
|
|
9
|
-
import { DocumentWorkflow, DocumentWorkflowState, DocumentWorkflowStep } from '../models/document-workflow.model.js';
|
|
10
|
-
import { DocumentApproval } from '../models/document.model.js';
|
|
11
|
-
import { configureDocumentManagement } from '../server/configure.js';
|
|
12
|
-
import { DocumentCategoryTypeService } from '../server/services/document-category-type.service.js';
|
|
13
|
-
import { DocumentCollectionService } from '../server/services/document-collection.service.js';
|
|
14
|
-
import { DocumentManagementAiService } from '../server/services/document-management-ai.service.js';
|
|
15
|
-
import { DocumentStatisticsService } from '../server/services/document-statistics.service.js';
|
|
16
|
-
import { DocumentTagService } from '../server/services/document-tag.service.js';
|
|
17
|
-
import { DocumentService } from '../server/services/document.service.js';
|
|
18
|
-
import { TestDocumentManagementAncillaryService, TestDocumentManagementAuthorizationService } from './helper.js';
|
|
19
|
-
describe('DocumentStatisticsService', () => {
|
|
20
|
-
let injector;
|
|
21
|
-
let database;
|
|
22
|
-
let documentService;
|
|
23
|
-
let statsService;
|
|
24
|
-
let collectionService;
|
|
25
|
-
let tagService;
|
|
26
|
-
let categoryTypeService;
|
|
27
|
-
const schema = 'document_management';
|
|
28
|
-
const tenantId = crypto.randomUUID();
|
|
29
|
-
beforeAll(async () => {
|
|
30
|
-
({ injector, database } = await setupIntegrationTest({
|
|
31
|
-
modules: { taskQueue: true, documentManagement: true },
|
|
32
|
-
orm: { schema },
|
|
33
|
-
}));
|
|
34
|
-
const mockObjectStorage = {
|
|
35
|
-
uploadObject: vi.fn(),
|
|
36
|
-
getDownloadUrl: vi.fn(),
|
|
37
|
-
getContent: vi.fn(),
|
|
38
|
-
getContentStream: vi.fn(),
|
|
39
|
-
getObject: vi.fn(),
|
|
40
|
-
exists: vi.fn(),
|
|
41
|
-
};
|
|
42
|
-
const mockAiService = {
|
|
43
|
-
extractContent: vi.fn(),
|
|
44
|
-
classifyDocumentType: vi.fn(),
|
|
45
|
-
extractData: vi.fn(),
|
|
46
|
-
findSuitableCollectionsForDocument: vi.fn(),
|
|
47
|
-
findSuitableRequestForDocument: vi.fn(),
|
|
48
|
-
};
|
|
49
|
-
injector.register(ObjectStorage, { useFactory: () => mockObjectStorage });
|
|
50
|
-
injector.register(GenkitModuleOptions, { useValue: {} });
|
|
51
|
-
injector.register(DocumentManagementAiService, { useValue: mockAiService });
|
|
52
|
-
configureDocumentManagement({
|
|
53
|
-
ancillaryService: TestDocumentManagementAncillaryService,
|
|
54
|
-
authorizationService: TestDocumentManagementAuthorizationService,
|
|
55
|
-
fileObjectStorageModule: 'documents',
|
|
56
|
-
fileUploadObjectStorageModule: 'document-uploads',
|
|
57
|
-
filePreviewObjectStorageModule: 'document-previews',
|
|
58
|
-
injector,
|
|
59
|
-
});
|
|
60
|
-
documentService = await injector.resolveAsync(DocumentService);
|
|
61
|
-
statsService = await injector.resolveAsync(DocumentStatisticsService);
|
|
62
|
-
collectionService = await injector.resolveAsync(DocumentCollectionService);
|
|
63
|
-
tagService = await injector.resolveAsync(DocumentTagService);
|
|
64
|
-
categoryTypeService = await injector.resolveAsync(DocumentCategoryTypeService);
|
|
65
|
-
});
|
|
66
|
-
afterAll(async () => {
|
|
67
|
-
await injector?.dispose();
|
|
68
|
-
});
|
|
69
|
-
beforeEach(async () => {
|
|
70
|
-
await clearTenantData(database, schema, ['validation_execution', 'validation_definition', 'tag_assignment', 'collection_assignment', 'workflow', 'document', 'collection', 'tag', 'type', 'category'], tenantId);
|
|
71
|
-
});
|
|
72
|
-
test('getStatistics should return total count', async () => {
|
|
73
|
-
await runInInjectionContext(injector, async () => {
|
|
74
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
75
|
-
await documentService.create(tenantId, {
|
|
76
|
-
title: 'Doc 1',
|
|
77
|
-
assignment: { collections: [collection.id] },
|
|
78
|
-
skipWorkflow: true,
|
|
79
|
-
}, new Uint8Array([1]));
|
|
80
|
-
await documentService.create(tenantId, {
|
|
81
|
-
title: 'Doc 2',
|
|
82
|
-
assignment: { collections: [collection.id] },
|
|
83
|
-
skipWorkflow: true,
|
|
84
|
-
}, new Uint8Array([1, 2]));
|
|
85
|
-
const stats = await statsService.getStatistics(tenantId, { includeTotalCount: true, collectionIds: [collection.id] });
|
|
86
|
-
expect(stats.totalCount).toBe(2);
|
|
87
|
-
});
|
|
88
|
-
});
|
|
89
|
-
test('getStatistics should return approval breakdown', async () => {
|
|
90
|
-
await runInInjectionContext(injector, async () => {
|
|
91
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
92
|
-
await documentService.create(tenantId, {
|
|
93
|
-
approval: DocumentApproval.Approved,
|
|
94
|
-
assignment: { collections: [collection.id] },
|
|
95
|
-
skipWorkflow: true,
|
|
96
|
-
}, new Uint8Array([1]));
|
|
97
|
-
await documentService.create(tenantId, {
|
|
98
|
-
approval: DocumentApproval.Pending,
|
|
99
|
-
assignment: { collections: [collection.id] },
|
|
100
|
-
skipWorkflow: true,
|
|
101
|
-
}, new Uint8Array([1]));
|
|
102
|
-
await documentService.create(tenantId, {
|
|
103
|
-
approval: DocumentApproval.Rejected,
|
|
104
|
-
assignment: { collections: [collection.id] },
|
|
105
|
-
skipWorkflow: true,
|
|
106
|
-
}, new Uint8Array([1]));
|
|
107
|
-
const stats = await statsService.getStatistics(tenantId, { includeApprovalBreakdown: true, collectionIds: [collection.id] });
|
|
108
|
-
expect(stats.approvalBreakdown?.approved).toBe(1);
|
|
109
|
-
expect(stats.approvalBreakdown?.pending).toBe(1);
|
|
110
|
-
expect(stats.approvalBreakdown?.rejected).toBe(1);
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
test('getStatistics should filter by collection', async () => {
|
|
114
|
-
await runInInjectionContext(injector, async () => {
|
|
115
|
-
const collection1 = await collectionService.createCollection(tenantId, null);
|
|
116
|
-
const collection2 = await collectionService.createCollection(tenantId, null);
|
|
117
|
-
await documentService.create(tenantId, {
|
|
118
|
-
assignment: { collections: [collection1.id] },
|
|
119
|
-
skipWorkflow: true,
|
|
120
|
-
}, new Uint8Array([1]));
|
|
121
|
-
await documentService.create(tenantId, {
|
|
122
|
-
assignment: { collections: [collection2.id] },
|
|
123
|
-
skipWorkflow: true,
|
|
124
|
-
}, new Uint8Array([1]));
|
|
125
|
-
const stats = await statsService.getStatistics(tenantId, { includeTotalCount: true, collectionIds: [collection1.id] });
|
|
126
|
-
expect(stats.totalCount).toBe(1);
|
|
127
|
-
});
|
|
128
|
-
});
|
|
129
|
-
test('getStatistics should return storage usage and total pages', async () => {
|
|
130
|
-
await runInInjectionContext(injector, async () => {
|
|
131
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
132
|
-
const doc = await documentService.create(tenantId, {
|
|
133
|
-
assignment: { collections: [collection.id] },
|
|
134
|
-
skipWorkflow: true,
|
|
135
|
-
}, new Uint8Array([1, 2, 3])); // Size 3
|
|
136
|
-
// Manually set pages since our mock doesn't handle PDF page count
|
|
137
|
-
await documentService.repository.update(doc.id, { pages: 5 });
|
|
138
|
-
const stats = await statsService.getStatistics(tenantId, { includeStorageUsage: true, includeTotalPages: true, collectionIds: [collection.id] });
|
|
139
|
-
expect(stats.storageUsage).toBe(3);
|
|
140
|
-
expect(stats.totalPages).toBe(5);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
test('getStatistics should return data quality metrics', async () => {
|
|
144
|
-
await runInInjectionContext(injector, async () => {
|
|
145
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
146
|
-
// Missing nothing (except type, which is checked separately)
|
|
147
|
-
await documentService.create(tenantId, {
|
|
148
|
-
assignment: { collections: [collection.id] },
|
|
149
|
-
skipWorkflow: true,
|
|
150
|
-
title: 'Title',
|
|
151
|
-
date: 20230101,
|
|
152
|
-
}, new Uint8Array([1]));
|
|
153
|
-
// Missing title and date
|
|
154
|
-
await documentService.create(tenantId, {
|
|
155
|
-
assignment: { collections: [collection.id] },
|
|
156
|
-
skipWorkflow: true,
|
|
157
|
-
}, new Uint8Array([1]));
|
|
158
|
-
const stats = await statsService.getStatistics(tenantId, { includeDataQuality: true, collectionIds: [collection.id] });
|
|
159
|
-
expect(stats.dataQuality?.missingTitle).toBe(1);
|
|
160
|
-
expect(stats.dataQuality?.missingDate).toBe(1);
|
|
161
|
-
expect(stats.dataQuality?.missingType).toBe(2);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
test('getStatistics should return created last 30 days', async () => {
|
|
165
|
-
await runInInjectionContext(injector, async () => {
|
|
166
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
167
|
-
await documentService.create(tenantId, {
|
|
168
|
-
assignment: { collections: [collection.id] },
|
|
169
|
-
skipWorkflow: true,
|
|
170
|
-
}, new Uint8Array([1]));
|
|
171
|
-
const stats = await statsService.getStatistics(tenantId, { includeCreatedLast30Days: true, collectionIds: [collection.id] });
|
|
172
|
-
expect(stats.createdLast30Days).toBe(1);
|
|
173
|
-
});
|
|
174
|
-
});
|
|
175
|
-
test('getStatistics should return tag usage', async () => {
|
|
176
|
-
await runInInjectionContext(injector, async () => {
|
|
177
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
178
|
-
await documentService.create(tenantId, {
|
|
179
|
-
assignment: { collections: [collection.id] },
|
|
180
|
-
skipWorkflow: true,
|
|
181
|
-
tags: ['Tag1'],
|
|
182
|
-
}, new Uint8Array([1]));
|
|
183
|
-
const [tag] = await tagService.loadOrCreate(tenantId, ['Tag1']);
|
|
184
|
-
const stats = await statsService.getStatistics(tenantId, { includeTagUsage: true, collectionIds: [collection.id] });
|
|
185
|
-
expect(stats.tagUsage?.[tag.id]).toBe(1);
|
|
186
|
-
});
|
|
187
|
-
});
|
|
188
|
-
test('getStatistics should return mime type distribution', async () => {
|
|
189
|
-
await runInInjectionContext(injector, async () => {
|
|
190
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
191
|
-
await documentService.create(tenantId, {
|
|
192
|
-
assignment: { collections: [collection.id] },
|
|
193
|
-
skipWorkflow: true,
|
|
194
|
-
}, new Uint8Array([1]));
|
|
195
|
-
const stats = await statsService.getStatistics(tenantId, { includeMimeTypeDistribution: true, collectionIds: [collection.id] });
|
|
196
|
-
expect(Object.keys(stats.mimeTypeDistribution ?? {}).length).toBeGreaterThan(0);
|
|
197
|
-
});
|
|
198
|
-
});
|
|
199
|
-
test('getStatistics should return type breakdown and filter by category', async () => {
|
|
200
|
-
await runInInjectionContext(injector, async () => {
|
|
201
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
202
|
-
const categoryLabel = `Category ${crypto.randomUUID()}`;
|
|
203
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: categoryLabel, parentId: null });
|
|
204
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type 1', categoryId: category.id });
|
|
205
|
-
await documentService.create(tenantId, {
|
|
206
|
-
assignment: { collections: [collection.id] },
|
|
207
|
-
skipWorkflow: true,
|
|
208
|
-
typeId: type.id,
|
|
209
|
-
}, new Uint8Array([1]));
|
|
210
|
-
const stats = await statsService.getStatistics(tenantId, { includeTypeBreakdown: true, collectionIds: [collection.id], categoryIds: [category.id] });
|
|
211
|
-
expect(stats.typeBreakdown?.[type.id]).toBe(1);
|
|
212
|
-
});
|
|
213
|
-
});
|
|
214
|
-
test('getStatistics should return validation failures', async () => {
|
|
215
|
-
await runInInjectionContext(injector, async () => {
|
|
216
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
217
|
-
const doc = await documentService.create(tenantId, {
|
|
218
|
-
assignment: { collections: [collection.id] },
|
|
219
|
-
skipWorkflow: true,
|
|
220
|
-
}, new Uint8Array([1]));
|
|
221
|
-
const workflowRepo = await injector.resolveAsync(getRepository(DocumentWorkflow));
|
|
222
|
-
const validationRepo = await injector.resolveAsync(getRepository(DocumentValidationExecution));
|
|
223
|
-
const definitionRepo = await injector.resolveAsync(getRepository(DocumentValidationDefinition));
|
|
224
|
-
const definition = await definitionRepo.insert({
|
|
225
|
-
tenantId,
|
|
226
|
-
identifier: 'test-val',
|
|
227
|
-
label: 'Test Validation',
|
|
228
|
-
description: null,
|
|
229
|
-
configuration: {},
|
|
230
|
-
});
|
|
231
|
-
const workflow = await workflowRepo.insert({
|
|
232
|
-
tenantId,
|
|
233
|
-
documentId: doc.id,
|
|
234
|
-
step: DocumentWorkflowStep.Validation,
|
|
235
|
-
state: DocumentWorkflowState.Pending,
|
|
236
|
-
skipAi: true,
|
|
237
|
-
completeTimestamp: null,
|
|
238
|
-
failReason: null,
|
|
239
|
-
completeUserId: null,
|
|
240
|
-
});
|
|
241
|
-
await validationRepo.insert({
|
|
242
|
-
tenantId,
|
|
243
|
-
workflowId: workflow.id,
|
|
244
|
-
definitionId: definition.id,
|
|
245
|
-
state: DocumentValidationExecutionState.Completed,
|
|
246
|
-
resultStatus: DocumentValidationResultStatus.Failed,
|
|
247
|
-
resultMessage: null,
|
|
248
|
-
startedAt: null,
|
|
249
|
-
completedAt: null,
|
|
250
|
-
});
|
|
251
|
-
const stats = await statsService.getStatistics(tenantId, { includeValidationFailures: true, collectionIds: [collection.id] });
|
|
252
|
-
expect(stats.validationFailures).toBe(1);
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
test('getStatistics should return nothing when no options selected', async () => {
|
|
256
|
-
await runInInjectionContext(injector, async () => {
|
|
257
|
-
const stats = await statsService.getStatistics(tenantId, { collectionIds: [] });
|
|
258
|
-
expect(Object.keys(stats).length).toBe(0);
|
|
259
|
-
});
|
|
260
|
-
});
|
|
261
|
-
test('getStatistics should support combined filters', async () => {
|
|
262
|
-
await runInInjectionContext(injector, async () => {
|
|
263
|
-
const collection1 = await collectionService.createCollection(tenantId, null);
|
|
264
|
-
const collection2 = await collectionService.createCollection(tenantId, null);
|
|
265
|
-
const category1 = await categoryTypeService.createCategory({ tenantId, label: `Cat 1 ${crypto.randomUUID()}`, parentId: null });
|
|
266
|
-
const category2 = await categoryTypeService.createCategory({ tenantId, label: `Cat 2 ${crypto.randomUUID()}`, parentId: null });
|
|
267
|
-
const type1 = await categoryTypeService.createType({ tenantId, label: 'Type 1', categoryId: category1.id });
|
|
268
|
-
const type2 = await categoryTypeService.createType({ tenantId, label: 'Type 2', categoryId: category2.id });
|
|
269
|
-
// Doc 1: Coll 1, Type 1 (Cat 1)
|
|
270
|
-
await documentService.create(tenantId, {
|
|
271
|
-
assignment: { collections: [collection1.id] },
|
|
272
|
-
typeId: type1.id,
|
|
273
|
-
skipWorkflow: true,
|
|
274
|
-
}, new Uint8Array([1]));
|
|
275
|
-
// Doc 2: Coll 1, Type 2 (Cat 2)
|
|
276
|
-
await documentService.create(tenantId, {
|
|
277
|
-
assignment: { collections: [collection1.id] },
|
|
278
|
-
typeId: type2.id,
|
|
279
|
-
skipWorkflow: true,
|
|
280
|
-
}, new Uint8Array([1]));
|
|
281
|
-
// Doc 3: Coll 2, Type 1 (Cat 1)
|
|
282
|
-
await documentService.create(tenantId, {
|
|
283
|
-
assignment: { collections: [collection2.id] },
|
|
284
|
-
typeId: type1.id,
|
|
285
|
-
skipWorkflow: true,
|
|
286
|
-
}, new Uint8Array([1]));
|
|
287
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
288
|
-
includeTotalCount: true,
|
|
289
|
-
collectionIds: [collection1.id],
|
|
290
|
-
categoryIds: [category1.id],
|
|
291
|
-
});
|
|
292
|
-
expect(stats.totalCount).toBe(1); // Only Doc 1 matches both
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
test('getStatistics should return multiple stats without category filters', async () => {
|
|
296
|
-
await runInInjectionContext(injector, async () => {
|
|
297
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
298
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: `Cat ${crypto.randomUUID()}`, parentId: null });
|
|
299
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type', categoryId: category.id });
|
|
300
|
-
await documentService.create(tenantId, {
|
|
301
|
-
assignment: { collections: [collection.id] },
|
|
302
|
-
typeId: type.id,
|
|
303
|
-
skipWorkflow: true,
|
|
304
|
-
title: 'Title',
|
|
305
|
-
}, new Uint8Array([1, 2, 3]));
|
|
306
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
307
|
-
includeTotalCount: true,
|
|
308
|
-
includeTypeBreakdown: true,
|
|
309
|
-
includeMimeTypeDistribution: true,
|
|
310
|
-
includeStorageUsage: true,
|
|
311
|
-
includeDataQuality: true,
|
|
312
|
-
collectionIds: [collection.id],
|
|
313
|
-
});
|
|
314
|
-
expect(stats.totalCount).toBe(1);
|
|
315
|
-
expect(stats.typeBreakdown?.[type.id]).toBe(1);
|
|
316
|
-
expect(stats.storageUsage).toBe(3);
|
|
317
|
-
expect(stats.dataQuality?.missingTitle).toBe(0);
|
|
318
|
-
});
|
|
319
|
-
});
|
|
320
|
-
test('getStatistics should return stats with only collection filter', async () => {
|
|
321
|
-
await runInInjectionContext(injector, async () => {
|
|
322
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
323
|
-
await documentService.create(tenantId, {
|
|
324
|
-
assignment: { collections: [collection.id] },
|
|
325
|
-
skipWorkflow: true,
|
|
326
|
-
}, new Uint8Array([1]));
|
|
327
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
328
|
-
includeTotalCount: true,
|
|
329
|
-
includeMimeTypeDistribution: true,
|
|
330
|
-
collectionIds: [collection.id],
|
|
331
|
-
});
|
|
332
|
-
expect(stats.totalCount).toBe(1);
|
|
333
|
-
});
|
|
334
|
-
});
|
|
335
|
-
test('getStatistics should return mime type distribution with category filter', async () => {
|
|
336
|
-
await runInInjectionContext(injector, async () => {
|
|
337
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
338
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: `Cat ${crypto.randomUUID()}`, parentId: null });
|
|
339
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type', categoryId: category.id });
|
|
340
|
-
await documentService.create(tenantId, {
|
|
341
|
-
assignment: { collections: [collection.id] },
|
|
342
|
-
typeId: type.id,
|
|
343
|
-
skipWorkflow: true,
|
|
344
|
-
}, new Uint8Array([1]));
|
|
345
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
346
|
-
includeMimeTypeDistribution: true,
|
|
347
|
-
collectionIds: [collection.id],
|
|
348
|
-
categoryIds: [category.id],
|
|
349
|
-
});
|
|
350
|
-
expect(Object.keys(stats.mimeTypeDistribution ?? {}).length).toBeGreaterThan(0);
|
|
351
|
-
});
|
|
352
|
-
});
|
|
353
|
-
test('getStatistics should return tag usage with filters', async () => {
|
|
354
|
-
await runInInjectionContext(injector, async () => {
|
|
355
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
356
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: `Cat ${crypto.randomUUID()}`, parentId: null });
|
|
357
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type', categoryId: category.id });
|
|
358
|
-
await documentService.create(tenantId, {
|
|
359
|
-
assignment: { collections: [collection.id] },
|
|
360
|
-
typeId: type.id,
|
|
361
|
-
skipWorkflow: true,
|
|
362
|
-
tags: ['Tag1'],
|
|
363
|
-
}, new Uint8Array([1]));
|
|
364
|
-
const [tag] = await tagService.loadOrCreate(tenantId, ['Tag1']);
|
|
365
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
366
|
-
includeTagUsage: true,
|
|
367
|
-
collectionIds: [collection.id],
|
|
368
|
-
categoryIds: [category.id],
|
|
369
|
-
});
|
|
370
|
-
expect(stats.tagUsage?.[tag.id]).toBe(1);
|
|
371
|
-
});
|
|
372
|
-
});
|
|
373
|
-
test('getStatistics should return validation failures with collection filter', async () => {
|
|
374
|
-
await runInInjectionContext(injector, async () => {
|
|
375
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
376
|
-
const doc = await documentService.create(tenantId, {
|
|
377
|
-
assignment: { collections: [collection.id] },
|
|
378
|
-
skipWorkflow: true,
|
|
379
|
-
}, new Uint8Array([1]));
|
|
380
|
-
const workflowRepo = await injector.resolveAsync(getRepository(DocumentWorkflow));
|
|
381
|
-
const validationRepo = await injector.resolveAsync(getRepository(DocumentValidationExecution));
|
|
382
|
-
const definitionRepo = await injector.resolveAsync(getRepository(DocumentValidationDefinition));
|
|
383
|
-
const definition = await definitionRepo.insert({
|
|
384
|
-
tenantId,
|
|
385
|
-
identifier: 'test-val-2',
|
|
386
|
-
label: 'Test Validation',
|
|
387
|
-
description: null,
|
|
388
|
-
configuration: {},
|
|
389
|
-
});
|
|
390
|
-
const workflow = await workflowRepo.insert({
|
|
391
|
-
tenantId,
|
|
392
|
-
documentId: doc.id,
|
|
393
|
-
step: DocumentWorkflowStep.Validation,
|
|
394
|
-
state: DocumentWorkflowState.Pending,
|
|
395
|
-
skipAi: true,
|
|
396
|
-
completeTimestamp: null,
|
|
397
|
-
failReason: null,
|
|
398
|
-
completeUserId: null,
|
|
399
|
-
});
|
|
400
|
-
await validationRepo.insert({
|
|
401
|
-
tenantId,
|
|
402
|
-
workflowId: workflow.id,
|
|
403
|
-
definitionId: definition.id,
|
|
404
|
-
state: DocumentValidationExecutionState.Completed,
|
|
405
|
-
resultStatus: DocumentValidationResultStatus.Failed,
|
|
406
|
-
resultMessage: null,
|
|
407
|
-
startedAt: null,
|
|
408
|
-
completedAt: null,
|
|
409
|
-
});
|
|
410
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
411
|
-
includeValidationFailures: true,
|
|
412
|
-
collectionIds: [collection.id],
|
|
413
|
-
});
|
|
414
|
-
expect(stats.validationFailures).toBe(1);
|
|
415
|
-
});
|
|
416
|
-
});
|
|
417
|
-
test('getStatistics should return validation failures with category filter', async () => {
|
|
418
|
-
await runInInjectionContext(injector, async () => {
|
|
419
|
-
const categoryLabel = `Cat val ${crypto.randomUUID()}`;
|
|
420
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: categoryLabel, parentId: null });
|
|
421
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type val', categoryId: category.id });
|
|
422
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
423
|
-
const doc = await documentService.create(tenantId, {
|
|
424
|
-
assignment: { collections: [collection.id] },
|
|
425
|
-
typeId: type.id,
|
|
426
|
-
skipWorkflow: true,
|
|
427
|
-
}, new Uint8Array([1]));
|
|
428
|
-
const workflowRepo = await injector.resolveAsync(getRepository(DocumentWorkflow));
|
|
429
|
-
const validationRepo = await injector.resolveAsync(getRepository(DocumentValidationExecution));
|
|
430
|
-
const definitionRepo = await injector.resolveAsync(getRepository(DocumentValidationDefinition));
|
|
431
|
-
const definition = await definitionRepo.insert({
|
|
432
|
-
tenantId,
|
|
433
|
-
identifier: 'test-val-3',
|
|
434
|
-
label: 'Test Validation',
|
|
435
|
-
description: null,
|
|
436
|
-
configuration: {},
|
|
437
|
-
});
|
|
438
|
-
const workflow = await workflowRepo.insert({
|
|
439
|
-
tenantId,
|
|
440
|
-
documentId: doc.id,
|
|
441
|
-
step: DocumentWorkflowStep.Validation,
|
|
442
|
-
state: DocumentWorkflowState.Pending,
|
|
443
|
-
skipAi: true,
|
|
444
|
-
completeTimestamp: null,
|
|
445
|
-
failReason: null,
|
|
446
|
-
completeUserId: null,
|
|
447
|
-
});
|
|
448
|
-
await validationRepo.insert({
|
|
449
|
-
tenantId,
|
|
450
|
-
workflowId: workflow.id,
|
|
451
|
-
definitionId: definition.id,
|
|
452
|
-
state: DocumentValidationExecutionState.Completed,
|
|
453
|
-
resultStatus: DocumentValidationResultStatus.Failed,
|
|
454
|
-
resultMessage: null,
|
|
455
|
-
startedAt: null,
|
|
456
|
-
completedAt: null,
|
|
457
|
-
});
|
|
458
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
459
|
-
includeValidationFailures: true,
|
|
460
|
-
collectionIds: [collection.id],
|
|
461
|
-
categoryIds: [category.id],
|
|
462
|
-
});
|
|
463
|
-
expect(stats.validationFailures).toBe(1);
|
|
464
|
-
});
|
|
465
|
-
});
|
|
466
|
-
test('getStatistics should return type breakdown with collection filter', async () => {
|
|
467
|
-
await runInInjectionContext(injector, async () => {
|
|
468
|
-
const collection = await collectionService.createCollection(tenantId, null);
|
|
469
|
-
const category = await categoryTypeService.createCategory({ tenantId, label: `Cat ${crypto.randomUUID()}`, parentId: null });
|
|
470
|
-
const type = await categoryTypeService.createType({ tenantId, label: 'Type', categoryId: category.id });
|
|
471
|
-
await documentService.create(tenantId, {
|
|
472
|
-
assignment: { collections: [collection.id] },
|
|
473
|
-
typeId: type.id,
|
|
474
|
-
skipWorkflow: true,
|
|
475
|
-
}, new Uint8Array([1]));
|
|
476
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
477
|
-
includeTypeBreakdown: true,
|
|
478
|
-
collectionIds: [collection.id],
|
|
479
|
-
});
|
|
480
|
-
expect(stats.typeBreakdown?.[type.id]).toBe(1);
|
|
481
|
-
});
|
|
482
|
-
});
|
|
483
|
-
test('getStatistics should return zeroed stats for empty tenant', async () => {
|
|
484
|
-
await runInInjectionContext(injector, async () => {
|
|
485
|
-
const stats = await statsService.getStatistics(tenantId, {
|
|
486
|
-
includeTotalCount: true,
|
|
487
|
-
includeStorageUsage: true,
|
|
488
|
-
includeTotalPages: true,
|
|
489
|
-
includeValidationFailures: true,
|
|
490
|
-
collectionIds: [],
|
|
491
|
-
});
|
|
492
|
-
expect(stats.totalCount).toBe(0);
|
|
493
|
-
expect(stats.storageUsage).toBe(0);
|
|
494
|
-
expect(stats.totalPages).toBe(0);
|
|
495
|
-
expect(stats.validationFailures).toBe(0);
|
|
496
|
-
});
|
|
497
|
-
});
|
|
498
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|