@wildo-ai/saas-backend-lib 1.1.8 → 1.1.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/esm/data-seeding/models/data-seed.shared.schemas.d.ts +8 -0
  2. package/dist/esm/data-seeding/models/data-seed.shared.schemas.d.ts.map +1 -1
  3. package/dist/esm/data-seeding/models/data-seed.shared.schemas.js +17 -0
  4. package/dist/esm/data-seeding/models/data-seed.shared.schemas.js.map +1 -1
  5. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.d.ts.map +1 -1
  6. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.js +9 -1
  7. package/dist/esm/data-seeding/services/data-seed-application-bootstrap.backend.js.map +1 -1
  8. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.d.ts +23 -0
  9. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.d.ts.map +1 -0
  10. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.js +25 -0
  11. package/dist/esm/data-seeding/services/data-seed-environment-admission.backend.js.map +1 -0
  12. package/dist/esm/databases/services/postgresql-migration-runner.backend.d.ts +6 -0
  13. package/dist/esm/databases/services/postgresql-migration-runner.backend.d.ts.map +1 -1
  14. package/dist/esm/databases/services/postgresql-migration-runner.backend.js +8 -1
  15. package/dist/esm/databases/services/postgresql-migration-runner.backend.js.map +1 -1
  16. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts +0 -1
  17. package/dist/esm/external-providers/services/external-providers-registry.backend.service.d.ts.map +1 -1
  18. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js +4 -39
  19. package/dist/esm/external-providers/services/external-providers-registry.backend.service.js.map +1 -1
  20. package/dist/esm/flows-actors/services/agents.backend.service.d.ts +15 -4
  21. package/dist/esm/flows-actors/services/agents.backend.service.d.ts.map +1 -1
  22. package/dist/esm/flows-actors/services/agents.backend.service.js +21 -11
  23. package/dist/esm/flows-actors/services/agents.backend.service.js.map +1 -1
  24. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts +47 -2
  25. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.d.ts.map +1 -1
  26. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js +56 -8
  27. package/dist/esm/flows-actors/utils/acp-session-runner.backend.utils.js.map +1 -1
  28. package/dist/esm/queue/job-consumer.backend.service.d.ts.map +1 -1
  29. package/dist/esm/queue/job-consumer.backend.service.js +21 -8
  30. package/dist/esm/queue/job-consumer.backend.service.js.map +1 -1
  31. package/dist/esm/queue/job-status-tracking.backend.service.d.ts.map +1 -1
  32. package/dist/esm/queue/job-status-tracking.backend.service.js +4 -1
  33. package/dist/esm/queue/job-status-tracking.backend.service.js.map +1 -1
  34. package/dist/esm/queue/queue.backend.service.d.ts +14 -0
  35. package/dist/esm/queue/queue.backend.service.d.ts.map +1 -1
  36. package/dist/esm/queue/queue.backend.service.js +68 -12
  37. package/dist/esm/queue/queue.backend.service.js.map +1 -1
  38. package/dist/esm/queue/scheduled-evidence-coverage.backend.d.ts +8 -0
  39. package/dist/esm/queue/scheduled-evidence-coverage.backend.d.ts.map +1 -1
  40. package/dist/esm/queue/scheduled-evidence-coverage.backend.js +20 -2
  41. package/dist/esm/queue/scheduled-evidence-coverage.backend.js.map +1 -1
  42. package/dist/esm/queue/scheduled-execution.backend.service.d.ts +44 -1
  43. package/dist/esm/queue/scheduled-execution.backend.service.d.ts.map +1 -1
  44. package/dist/esm/queue/scheduled-execution.backend.service.js +180 -10
  45. package/dist/esm/queue/scheduled-execution.backend.service.js.map +1 -1
  46. package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts +73 -21
  47. package/dist/esm/queue/scheduled-message-verifier.backend.service.d.ts.map +1 -1
  48. package/dist/esm/queue/scheduled-message-verifier.backend.service.js +162 -88
  49. package/dist/esm/queue/scheduled-message-verifier.backend.service.js.map +1 -1
  50. package/dist/esm/runtime/services/start-application.backend.service.d.ts.map +1 -1
  51. package/dist/esm/runtime/services/start-application.backend.service.js +16 -1
  52. package/dist/esm/runtime/services/start-application.backend.service.js.map +1 -1
  53. package/package.json +10 -10
  54. package/dist/esm/__tests__/fixture-deep-partial.d.ts +0 -18
  55. package/dist/esm/__tests__/fixture-deep-partial.d.ts.map +0 -1
  56. package/dist/esm/__tests__/fixture-deep-partial.js +0 -1
  57. package/dist/esm/__tests__/fixture-deep-partial.js.map +0 -1
  58. package/dist/esm/__tests__/integration/redis-integration-gate.d.ts +0 -26
  59. package/dist/esm/__tests__/integration/redis-integration-gate.d.ts.map +0 -1
  60. package/dist/esm/__tests__/integration/redis-integration-gate.js +0 -105
  61. package/dist/esm/__tests__/integration/redis-integration-gate.js.map +0 -1
  62. package/dist/esm/__tests__/setup.d.ts +0 -7
  63. package/dist/esm/__tests__/setup.d.ts.map +0 -1
  64. package/dist/esm/__tests__/setup.js +0 -14
  65. package/dist/esm/__tests__/setup.js.map +0 -1
  66. package/dist/esm/__tests__/test-container.d.ts +0 -41
  67. package/dist/esm/__tests__/test-container.d.ts.map +0 -1
  68. package/dist/esm/__tests__/test-container.js +0 -98
  69. package/dist/esm/__tests__/test-container.js.map +0 -1
  70. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts +0 -47
  71. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.d.ts.map +0 -1
  72. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js +0 -82
  73. package/dist/esm/base-classes/services/__tests__/mock-resource-operation-helper.service.js.map +0 -1
  74. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.d.ts +0 -57
  75. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.d.ts.map +0 -1
  76. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.js +0 -172
  77. package/dist/esm/base-classes/services/repositories/__tests__/method-span-scan.guard-helpers.js.map +0 -1
  78. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.d.ts +0 -41
  79. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.d.ts.map +0 -1
  80. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.js +0 -54
  81. package/dist/esm/base-classes/services/repositories/__tests__/repositories-registry-infrastructure-read.double.js.map +0 -1
  82. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.d.ts +0 -20
  83. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.d.ts.map +0 -1
  84. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.js +0 -33
  85. package/dist/esm/billing/services/__tests__/subscription-provider-projection.test-double.js.map +0 -1
  86. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.d.ts +0 -22
  87. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.d.ts.map +0 -1
  88. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.js +0 -92
  89. package/dist/esm/billing/services/custom-impl/__tests__/plan-change-confirmation.fixture.js.map +0 -1
  90. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.d.ts +0 -15
  91. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.d.ts.map +0 -1
  92. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.js +0 -61
  93. package/dist/esm/billing/services/custom-impl/__tests__/subscription-keyed-mutation.fixture.js.map +0 -1
  94. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.d.ts +0 -21
  95. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.d.ts.map +0 -1
  96. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.js +0 -32
  97. package/dist/esm/billing/services/webhooks/__tests__/billing-event-authority.test-double.js.map +0 -1
  98. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts +0 -52
  99. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.d.ts.map +0 -1
  100. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js +0 -74
  101. package/dist/esm/billing/services/webhooks/__tests__/settlement-ledger.test-double.js.map +0 -1
  102. package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts +0 -60
  103. package/dist/esm/config/services/__tests__/mock-app-configuration.service.d.ts.map +0 -1
  104. package/dist/esm/config/services/__tests__/mock-app-configuration.service.js +0 -156
  105. package/dist/esm/config/services/__tests__/mock-app-configuration.service.js.map +0 -1
  106. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.d.ts +0 -31
  107. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.d.ts.map +0 -1
  108. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.js +0 -47
  109. package/dist/esm/config/services/__tests__/startup-validator-resources-registry.double.js.map +0 -1
  110. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts +0 -20
  111. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.d.ts.map +0 -1
  112. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js +0 -424
  113. package/dist/esm/databases/services/__tests__/mock-mongoose-model.service.js.map +0 -1
  114. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts +0 -19
  115. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.d.ts.map +0 -1
  116. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js +0 -49
  117. package/dist/esm/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.js.map +0 -1
  118. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.d.ts +0 -43
  119. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.d.ts.map +0 -1
  120. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.js +0 -61
  121. package/dist/esm/flows-actors/services/__tests__/pending-decision.fixtures.js.map +0 -1
  122. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.d.ts +0 -25
  123. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.d.ts.map +0 -1
  124. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.js +0 -92
  125. package/dist/esm/inbound/services/__tests__/support/in-memory-infrastructure-repositories.js.map +0 -1
  126. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.d.ts +0 -7
  127. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.d.ts.map +0 -1
  128. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.js +0 -194
  129. package/dist/esm/meta-workflows/services/__tests__/fixtures/meta-workflow-evaluation-treatment.test-fixture.js.map +0 -1
  130. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts +0 -34
  131. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.d.ts.map +0 -1
  132. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js +0 -59
  133. package/dist/esm/monitoring/logger/services/__tests__/mock-logger.service.js.map +0 -1
  134. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.d.ts +0 -48
  135. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.d.ts.map +0 -1
  136. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.js +0 -53
  137. package/dist/esm/monitoring/observability/services/__tests__/mock-metrics.service.js.map +0 -1
  138. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.d.ts +0 -3
  139. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.d.ts.map +0 -1
  140. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.js +0 -19
  141. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/bundle.js.map +0 -1
  142. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.d.ts +0 -51
  143. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.d.ts.map +0 -1
  144. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.js +0 -24
  145. package/dist/esm/notifications/services/__tests__/fixtures/personal-notification-browser/host.js.map +0 -1
  146. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.d.ts +0 -8
  147. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.d.ts.map +0 -1
  148. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.js +0 -9
  149. package/dist/esm/notifications/services/__tests__/recipient-language.test-double.js.map +0 -1
  150. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.d.ts +0 -10
  151. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.d.ts.map +0 -1
  152. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.js +0 -18
  153. package/dist/esm/pdf-templates/__tests__/fixtures/tiny-pdf-template.fixture.js.map +0 -1
  154. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.d.ts +0 -11
  155. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.d.ts.map +0 -1
  156. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.js +0 -34
  157. package/dist/esm/security/api-keys/__tests__/api-key-usage-redis.double.js.map +0 -1
  158. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.d.ts +0 -105
  159. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.d.ts.map +0 -1
  160. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.js +0 -140
  161. package/dist/esm/security/authentications/__tests__/registration-onboarding.harness.js.map +0 -1
  162. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.d.ts +0 -35
  163. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.d.ts.map +0 -1
  164. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.js +0 -46
  165. package/dist/esm/security/authentications/services/__tests__/oauth-provider-audit-spies.mock.js.map +0 -1
  166. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.d.ts +0 -2
  167. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.d.ts.map +0 -1
  168. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.js +0 -18
  169. package/dist/esm/security/connected-accounts/__tests__/support/real-connection-client-methods.js.map +0 -1
  170. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.d.ts +0 -20
  171. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.d.ts.map +0 -1
  172. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.js +0 -56
  173. package/dist/esm/systems-of-record/credentials/__tests__/certificate-fixtures.js.map +0 -1
  174. package/dist/tsconfig.build.tsbuildinfo +0 -1
@@ -1,47 +0,0 @@
1
- import { vi } from 'vitest';
2
- /**
3
- * The `ResourcesRegistryBackendService` double every startup-validator fixture builds from.
4
- *
5
- * ## Why a shared factory rather than an object literal per fixture
6
- *
7
- * `ApplicationStartupConfigValidatorService` runs a growing list of COLLECTORS over the registry, and
8
- * each new one is free to reach for a registry method the previous ones did not. Four fixtures across
9
- * two files each declared their own registry literal, so a collector added in `engine/` broke all four
10
- * at once with `<method> is not a function` — and the four had to be found and fixed one by one.
11
- * Measured 2026-09-16: `collectSubjectErasureLaneDeclarationIssues` began calling
12
- * `tryGetResourceConfiguration`, and 49 pins across the two files died on it.
13
- *
14
- * Declaring the double ONCE is what turns that into a single edit. It is the shape
15
- * `.claude/rules/invariant-call-site-enumeration.md` asks for: the next collector's requirement lands
16
- * here, not at N sites that have to be enumerated correctly.
17
- *
18
- * ## The `try` sibling is DERIVED, never declared beside its throwing twin
19
- *
20
- * On the real registry the two are one contract: `getResourceConfiguration` THROWS for an
21
- * unregistered type (feature gating removes whole families), and `tryGetResourceConfiguration`
22
- * answers `undefined` for the callers where absence is a legitimate answer. Deriving one from the
23
- * other here reproduces exactly that relationship, so a fixture cannot supply a lookup whose two
24
- * halves disagree — which is the failure a hand-written pair invites.
25
- */
26
- export function createStartupValidatorResourcesRegistryDouble(members) {
27
- const { getResourceConfiguration, ...rest } = members;
28
- return {
29
- validateInitializedPersistenceAdapterConfiguration: vi.fn(),
30
- ...rest,
31
- ...(getResourceConfiguration
32
- ? {
33
- getResourceConfiguration,
34
- tryGetResourceConfiguration: (resourceType) => {
35
- try {
36
- return getResourceConfiguration(resourceType);
37
- }
38
- catch {
39
- // The real `tryGetResourceConfiguration` answers `undefined` exactly where its twin throws.
40
- return undefined;
41
- }
42
- },
43
- }
44
- : {}),
45
- };
46
- }
47
- //# sourceMappingURL=startup-validator-resources-registry.double.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"startup-validator-resources-registry.double.js","sourceRoot":"","sources":["../../../../../../src/config/services/__tests__/startup-validator-resources-registry.double.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAI5B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,UAAU,6CAA6C,CAAC,OAI7D;IACC,MAAM,EAAE,wBAAwB,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAC;IAEtD,OAAO;QACL,kDAAkD,EAAE,EAAE,CAAC,EAAE,EAAE;QAC3D,GAAG,IAAI;QACP,GAAG,CAAC,wBAAwB;YAC1B,CAAC,CAAC;gBACA,wBAAwB;gBACxB,2BAA2B,EAAE,CAAC,YAA0B,EAAW,EAAE;oBACnE,IAAI,CAAC;wBACH,OAAO,wBAAwB,CAAC,YAAY,CAAC,CAAC;oBAChD,CAAC;oBAAC,MAAM,CAAC;wBACP,4FAA4F;wBAC5F,OAAO,SAAS,CAAC;oBACnB,CAAC;gBACH,CAAC;aACF;YACD,CAAC,CAAC,EAAE,CAAC;KACR,CAAC;AACJ,CAAC","sourcesContent":["import { vi } from 'vitest';\n\nimport type { ResourceType } from '@wildo-ai/saas-models';\n\n/**\n * The `ResourcesRegistryBackendService` double every startup-validator fixture builds from.\n *\n * ## Why a shared factory rather than an object literal per fixture\n *\n * `ApplicationStartupConfigValidatorService` runs a growing list of COLLECTORS over the registry, and\n * each new one is free to reach for a registry method the previous ones did not. Four fixtures across\n * two files each declared their own registry literal, so a collector added in `engine/` broke all four\n * at once with `<method> is not a function` — and the four had to be found and fixed one by one.\n * Measured 2026-09-16: `collectSubjectErasureLaneDeclarationIssues` began calling\n * `tryGetResourceConfiguration`, and 49 pins across the two files died on it.\n *\n * Declaring the double ONCE is what turns that into a single edit. It is the shape\n * `.claude/rules/invariant-call-site-enumeration.md` asks for: the next collector's requirement lands\n * here, not at N sites that have to be enumerated correctly.\n *\n * ## The `try` sibling is DERIVED, never declared beside its throwing twin\n *\n * On the real registry the two are one contract: `getResourceConfiguration` THROWS for an\n * unregistered type (feature gating removes whole families), and `tryGetResourceConfiguration`\n * answers `undefined` for the callers where absence is a legitimate answer. Deriving one from the\n * other here reproduces exactly that relationship, so a fixture cannot supply a lookup whose two\n * halves disagree — which is the failure a hand-written pair invites.\n */\nexport function createStartupValidatorResourcesRegistryDouble(members: {\n getResourceTypes: () => readonly ResourceType[] | readonly string[];\n getResourceConfiguration?: (resourceType: ResourceType) => unknown;\n [additionalMember: string]: unknown;\n}): Record<string, unknown> {\n const { getResourceConfiguration, ...rest } = members;\n\n return {\n validateInitializedPersistenceAdapterConfiguration: vi.fn(),\n ...rest,\n ...(getResourceConfiguration\n ? {\n getResourceConfiguration,\n tryGetResourceConfiguration: (resourceType: ResourceType): unknown => {\n try {\n return getResourceConfiguration(resourceType);\n } catch {\n // The real `tryGetResourceConfiguration` answers `undefined` exactly where its twin throws.\n return undefined;\n }\n },\n }\n : {}),\n };\n}\n"]}
@@ -1,20 +0,0 @@
1
- /**
2
- * In-memory Mongoose `Model` factory for integration tests.
3
- *
4
- * **Naming**: `mock-*.service.ts` — canonical mock module, not a test suite.
5
- * Plain `.ts` keeps it barrel-compilable, and Vitest also excludes these files
6
- * explicitly as a defensive guard.
7
- */
8
- import type { Model, Document } from 'mongoose';
9
- /** Mock mongoose model that stores data in memory */
10
- /**
11
- * @param surrogatePrimaryKeyFieldName - The AUTHORED name of a surrogate primary key, when the
12
- * resource declares one (FILES declares `fileId`, persisted as `_id`). Real Mongoose exposes it
13
- * as a VIRTUAL = `String(_id)`, so the repository's projection names the surrogate rather than
14
- * `_id` and then forces `_id` in for the virtual to resolve from. Without modelling that here, a
15
- * projected row carries `_id` and no surrogate, and any production code reading `row.fileId`
16
- * silently sees `undefined` — which is exactly what happened, in a batch, once the repository
17
- * started resolving surrogates for real.
18
- */
19
- export declare function createMockModel<T extends Document>(name: string, surrogatePrimaryKeyFieldName?: string): Model<T>;
20
- //# sourceMappingURL=mock-mongoose-model.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mock-mongoose-model.service.d.ts","sourceRoot":"","sources":["../../../../../../src/databases/services/__tests__/mock-mongoose-model.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,UAAU,CAAC;AAOhD,qDAAqD;AACrD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,4BAA4B,CAAC,EAAE,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAgfjH"}
@@ -1,424 +0,0 @@
1
- import { vi } from 'vitest';
2
- import { getMockMongoTransactionalState, registerMockMongoModel, } from './mock-mongo-transaction-registry.service.js';
3
- /** Mock mongoose model that stores data in memory */
4
- /**
5
- * @param surrogatePrimaryKeyFieldName - The AUTHORED name of a surrogate primary key, when the
6
- * resource declares one (FILES declares `fileId`, persisted as `_id`). Real Mongoose exposes it
7
- * as a VIRTUAL = `String(_id)`, so the repository's projection names the surrogate rather than
8
- * `_id` and then forces `_id` in for the virtual to resolve from. Without modelling that here, a
9
- * projected row carries `_id` and no surrogate, and any production code reading `row.fileId`
10
- * silently sees `undefined` — which is exactly what happened, in a batch, once the repository
11
- * started resolving surrogates for real.
12
- */
13
- export function createMockModel(name, surrogatePrimaryKeyFieldName) {
14
- let storage = new Map();
15
- let autoIdCounter = 1;
16
- const modelStateKey = {};
17
- const cloneValue = (value) => structuredClone(value);
18
- const getValueAtPath = (value, path) => {
19
- if (!path) {
20
- return value;
21
- }
22
- return path
23
- .split('.')
24
- .filter(Boolean)
25
- .reduce((current, segment) => {
26
- if (!current || typeof current !== 'object') {
27
- return undefined;
28
- }
29
- return current[segment];
30
- }, value);
31
- };
32
- const setValueAtPath = (target, path, value) => {
33
- const tokens = path.split('.').filter(Boolean);
34
- if (tokens.length === 0) {
35
- return;
36
- }
37
- let current = target;
38
- for (let index = 0; index < tokens.length - 1; index += 1) {
39
- const token = tokens[index];
40
- const next = current[token];
41
- if (!next || typeof next !== 'object') {
42
- current[token] = {};
43
- }
44
- current = current[token];
45
- }
46
- current[tokens[tokens.length - 1]] = value;
47
- };
48
- const matchesExpectedValue = (actual, expected) => {
49
- if (expected
50
- && typeof expected === 'object'
51
- && !Array.isArray(expected)
52
- && !('_bsontype' in expected)) {
53
- const operatorEntries = Object.entries(expected)
54
- .filter(([key]) => key.startsWith('$'));
55
- if (operatorEntries.length > 0) {
56
- return operatorEntries.every(([operator, value]) => {
57
- switch (operator) {
58
- case '$in':
59
- return Array.isArray(value) && value.some(candidate => String(candidate) === String(actual));
60
- case '$exists':
61
- return Boolean(value) ? actual !== undefined : actual === undefined;
62
- case '$lt': {
63
- if (actual === undefined || actual === null) {
64
- return false;
65
- }
66
- const normalizedActual = actual instanceof Date ? actual.getTime() : actual;
67
- const normalizedValue = value instanceof Date ? value.getTime() : value;
68
- return normalizedActual < normalizedValue;
69
- }
70
- case '$ne':
71
- return String(actual) !== String(value);
72
- case '$nin':
73
- return Array.isArray(value) && !value.some(candidate => String(candidate) === String(actual));
74
- case '$type':
75
- // Only the BSON aliases a caller of this double actually uses. An unmodelled alias throws rather
76
- // than matching nothing, which would read as "no rows" and hide the gap.
77
- switch (value) {
78
- case 'date': return actual instanceof Date;
79
- case 'string': return typeof actual === 'string';
80
- case 'number': return typeof actual === 'number';
81
- case 'bool': return typeof actual === 'boolean';
82
- default: throw new Error(`in-memory Mongo model: $type '${String(value)}' is not modelled`);
83
- }
84
- default:
85
- return false;
86
- }
87
- });
88
- }
89
- return Object.entries(expected).every(([key, nestedExpected]) => matchesExpectedValue(actual && typeof actual === 'object' ? actual[key] : undefined, nestedExpected));
90
- }
91
- if (actual instanceof Date || expected instanceof Date) {
92
- return String(actual) === String(expected);
93
- }
94
- if (actual !== null
95
- && actual !== undefined
96
- && expected !== null
97
- && expected !== undefined
98
- && typeof actual !== 'boolean'
99
- && typeof expected !== 'boolean'
100
- && typeof actual !== 'object'
101
- && typeof expected === 'object') {
102
- return String(actual) === String(expected);
103
- }
104
- return actual === expected;
105
- };
106
- const matchesFilter = (document, filter) => {
107
- if (!filter || Object.keys(filter).length === 0) {
108
- return true;
109
- }
110
- return Object.entries(filter).every(([key, expected]) => {
111
- if (key === '$or') {
112
- return Array.isArray(expected) && expected.some((candidate) => matchesFilter(document, candidate));
113
- }
114
- return matchesExpectedValue(getValueAtPath(document, key), expected);
115
- });
116
- };
117
- const applyProjection = (document, projection) => {
118
- if (!projection || Object.keys(projection).length === 0) {
119
- return withSurrogatePrimaryKey(cloneValue(document));
120
- }
121
- const includeKeys = Object.entries(projection)
122
- .filter(([, include]) => Boolean(include))
123
- .map(([field]) => field);
124
- if (includeKeys.length === 0) {
125
- return withSurrogatePrimaryKey(cloneValue(document));
126
- }
127
- const projected = {};
128
- for (const field of includeKeys) {
129
- setValueAtPath(projected, field, getValueAtPath(document, field));
130
- }
131
- if (projection._id !== 0 && document._id !== undefined) {
132
- projected._id = document._id;
133
- }
134
- return withSurrogatePrimaryKey(projected);
135
- };
136
- /** Mirror Mongoose's surrogate virtual: `<surrogate> === String(_id)`. */
137
- const withSurrogatePrimaryKey = (document) => {
138
- if (!surrogatePrimaryKeyFieldName || document._id === undefined)
139
- return document;
140
- return { ...document, [surrogatePrimaryKeyFieldName]: String(document._id) };
141
- };
142
- const applyUpdate = (document, update) => {
143
- const nextDocument = cloneValue(document);
144
- for (const [field, value] of Object.entries(update.$set ?? {})) {
145
- setValueAtPath(nextDocument, field, value);
146
- }
147
- for (const [field, increment] of Object.entries(update.$inc ?? {})) {
148
- const currentValue = getValueAtPath(nextDocument, field);
149
- const nextValue = typeof currentValue === 'number'
150
- ? currentValue + Number(increment)
151
- : Number(increment);
152
- setValueAtPath(nextDocument, field, nextValue);
153
- }
154
- for (const field of Object.keys(update.$unset ?? {})) {
155
- const parts = field.split('.');
156
- const parent = parts.length === 1 ? nextDocument : getValueAtPath(nextDocument, parts.slice(0, -1).join('.'));
157
- if (parent && typeof parent === 'object')
158
- delete parent[parts[parts.length - 1]];
159
- }
160
- return nextDocument;
161
- };
162
- /**
163
- * An aggregation-PIPELINE update (`updateMany(filter, [{ $set: … }])`), which Mongo accepts wherever it
164
- * accepts an update document. Models `$set` with literal values, `$field` references and `$add` over
165
- * numbers and at most one Date (Mongo's date + milliseconds). Anything else throws: a double that silently
166
- * skips a stage reports a migration as applied when nothing was written.
167
- */
168
- const applyPipelineUpdate = (document, stages) => {
169
- const nextDocument = cloneValue(document);
170
- const evaluate = (expression) => {
171
- if (typeof expression === 'string' && expression.startsWith('$')) {
172
- return getValueAtPath(nextDocument, expression.slice(1));
173
- }
174
- if (expression && typeof expression === 'object' && !Array.isArray(expression) && !(expression instanceof Date)) {
175
- const [operator, operands] = Object.entries(expression)[0] ?? [];
176
- if (operator === '$add' && Array.isArray(operands)) {
177
- const values = operands.map(evaluate);
178
- if (values.some((value) => value === null || value === undefined))
179
- return null;
180
- const dates = values.filter((value) => value instanceof Date);
181
- if (dates.length > 1)
182
- throw new Error('in-memory Mongo model: $add over two dates is not valid');
183
- const sum = values.reduce((total, value) => total + (value instanceof Date ? value.getTime() : Number(value)), 0);
184
- return dates.length === 1 ? new Date(sum) : sum;
185
- }
186
- if (operator?.startsWith('$'))
187
- throw new Error(`in-memory Mongo model: pipeline operator '${operator}' is not modelled`);
188
- }
189
- return expression;
190
- };
191
- for (const stage of stages) {
192
- const [stageName, stageBody] = Object.entries(stage)[0] ?? [];
193
- if (stageName !== '$set' || !stageBody || typeof stageBody !== 'object') {
194
- throw new Error(`in-memory Mongo model: pipeline stage '${String(stageName)}' is not modelled`);
195
- }
196
- for (const [field, expression] of Object.entries(stageBody)) {
197
- setValueAtPath(nextDocument, field, evaluate(expression));
198
- }
199
- }
200
- return nextDocument;
201
- };
202
- /**
203
- * The collection's secondary indexes, as `collection.indexes()` reports them (`_id_` is always present).
204
- * Not transactional: index DDL in Mongo is not part of a multi-document transaction either.
205
- */
206
- let indexStore = [];
207
- const getState = (session) => {
208
- const transactionalState = getMockMongoTransactionalState(modelStateKey, session);
209
- if (transactionalState) {
210
- return transactionalState;
211
- }
212
- return {
213
- storage,
214
- autoIdCounter,
215
- };
216
- };
217
- const buildQueryMock = (resolver) => {
218
- let sortField;
219
- let sortDirection = 1;
220
- let skipCount = 0;
221
- let limitCount;
222
- let activeSession;
223
- const resolve = () => {
224
- const rawValue = resolver(activeSession);
225
- if (!Array.isArray(rawValue)) {
226
- return cloneValue(rawValue);
227
- }
228
- const value = [...rawValue].map(item => cloneValue(item));
229
- if (sortField) {
230
- value.sort((left, right) => {
231
- const leftValue = getValueAtPath(left, sortField);
232
- const rightValue = getValueAtPath(right, sortField);
233
- if (leftValue === rightValue) {
234
- return 0;
235
- }
236
- if (leftValue === undefined) {
237
- return 1;
238
- }
239
- if (rightValue === undefined) {
240
- return -1;
241
- }
242
- return leftValue < rightValue ? -1 * sortDirection : 1 * sortDirection;
243
- });
244
- }
245
- const sliced = value.slice(skipCount, limitCount === undefined ? undefined : skipCount + limitCount);
246
- return sliced;
247
- };
248
- const promise = () => Promise.resolve(resolve());
249
- const query = {
250
- sort: vi.fn((spec) => {
251
- const [field, direction] = Object.entries(spec)[0] ?? [];
252
- sortField = field;
253
- sortDirection = direction ?? 1;
254
- return query;
255
- }),
256
- skip: vi.fn((count) => {
257
- skipCount = count;
258
- return query;
259
- }),
260
- limit: vi.fn((count) => {
261
- limitCount = count;
262
- return query;
263
- }),
264
- session: vi.fn((session) => {
265
- activeSession = session;
266
- return query;
267
- }),
268
- lean: vi.fn(() => promise()),
269
- exec: vi.fn(() => promise()),
270
- then: (onFulfilled, onRejected) => promise().then(onFulfilled, onRejected),
271
- catch: (onRejected) => promise().catch(onRejected),
272
- finally: (onFinally) => promise().finally(onFinally),
273
- };
274
- return query;
275
- };
276
- const persistDocument = (document, session) => {
277
- const state = getState(session);
278
- const id = String(document._id
279
- ?? state.autoIdCounter.toString(16).padStart(24, '0'));
280
- state.autoIdCounter += 1;
281
- if (!getMockMongoTransactionalState(modelStateKey, session)) {
282
- autoIdCounter = state.autoIdCounter;
283
- }
284
- const savedDocument = {
285
- ...cloneValue(document),
286
- _id: id,
287
- };
288
- state.storage.set(id, savedDocument);
289
- return cloneValue(savedDocument);
290
- };
291
- registerMockMongoModel(modelStateKey, {
292
- cloneState: () => ({
293
- storage: new Map(Array.from(storage.entries()).map(([id, document]) => [id, cloneValue(document)])),
294
- autoIdCounter,
295
- }),
296
- applyState: (state) => {
297
- storage = new Map(Array.from(state.storage.entries()).map(([id, document]) => [id, cloneValue(document)]));
298
- autoIdCounter = state.autoIdCounter;
299
- },
300
- });
301
- const mockModel = {
302
- modelName: name,
303
- schema: {
304
- paths: {},
305
- },
306
- find: vi.fn().mockImplementation((filter, projection, options) => buildQueryMock((session) => Array.from(getState(session ?? options?.session).storage.values())
307
- .filter(document => matchesFilter(document, filter))
308
- .map(document => applyProjection(document, projection)))),
309
- findOne: vi.fn().mockImplementation((filter, projection, options) => buildQueryMock((session) => {
310
- const document = Array.from(getState(session ?? options?.session).storage.values()).find(candidate => matchesFilter(candidate, filter));
311
- return document ? applyProjection(document, projection) : null;
312
- })),
313
- findById: vi.fn().mockImplementation((id, _projection, options) => buildQueryMock((session) => {
314
- const document = getState(session ?? options?.session).storage.get(id);
315
- return document ? cloneValue(document) : null;
316
- })),
317
- create: vi.fn().mockImplementation((doc, options) => {
318
- if (Array.isArray(doc)) {
319
- return Promise.resolve(doc.map(item => persistDocument(item, options?.session)));
320
- }
321
- return Promise.resolve(persistDocument(doc, options?.session));
322
- }),
323
- insertMany: vi.fn().mockImplementation((docs, options) => Promise.resolve(docs.map(document => persistDocument(document, options?.session)))),
324
- // Mongoose writes are thenable queries, not bare promises. Infrastructure
325
- // guarded mutations use .exec(), ordinary updates await the same query.
326
- findOneAndUpdate: vi.fn().mockImplementation((filter, update, options) => buildQueryMock((session) => {
327
- const state = getState(session ?? options?.session);
328
- const existingEntry = Array.from(state.storage.entries()).find(([, document]) => matchesFilter(document, filter));
329
- if (!existingEntry)
330
- return null;
331
- const [id, document] = existingEntry;
332
- const updated = applyUpdate(document, update);
333
- state.storage.set(id, updated);
334
- return cloneValue(updated);
335
- })),
336
- findByIdAndUpdate: vi.fn().mockImplementation((id, update, options) => {
337
- const state = getState(options?.session);
338
- const existing = state.storage.get(id);
339
- if (!existing) {
340
- return Promise.resolve(null);
341
- }
342
- const updated = applyUpdate(existing, update);
343
- state.storage.set(id, updated);
344
- return Promise.resolve(cloneValue(updated));
345
- }),
346
- updateMany: vi.fn().mockImplementation((filter, update, options) => {
347
- const state = getState(options?.session);
348
- let matchedCount = 0;
349
- for (const [id, document] of state.storage.entries()) {
350
- if (!matchesFilter(document, filter)) {
351
- continue;
352
- }
353
- matchedCount += 1;
354
- state.storage.set(id, Array.isArray(update) ? applyPipelineUpdate(document, update) : applyUpdate(document, update));
355
- }
356
- return Promise.resolve({
357
- matchedCount,
358
- modifiedCount: matchedCount,
359
- });
360
- }),
361
- findByIdAndDelete: vi.fn().mockImplementation((id, options) => {
362
- const state = getState(options?.session);
363
- const existing = state.storage.get(id);
364
- state.storage.delete(id);
365
- return Promise.resolve(existing ? cloneValue(existing) : null);
366
- }),
367
- deleteMany: vi.fn().mockImplementation((filter, options) => {
368
- const state = getState(options?.session);
369
- let deletedCount = 0;
370
- for (const [id, document] of Array.from(state.storage.entries())) {
371
- if (!matchesFilter(document, filter)) {
372
- continue;
373
- }
374
- state.storage.delete(id);
375
- deletedCount += 1;
376
- }
377
- return Promise.resolve({ deletedCount });
378
- }),
379
- deleteOne: vi.fn().mockImplementation((filter, options) => {
380
- const state = getState(options?.session);
381
- for (const [id, document] of Array.from(state.storage.entries())) {
382
- if (!matchesFilter(document, filter)) {
383
- continue;
384
- }
385
- state.storage.delete(id);
386
- return Promise.resolve({ deletedCount: 1 });
387
- }
388
- return Promise.resolve({ deletedCount: 0 });
389
- }),
390
- // Mongo creates a collection on first write; an explicit create is idempotent here as for an existing one.
391
- createCollection: vi.fn().mockImplementation(() => Promise.resolve(undefined)),
392
- countDocuments: vi.fn().mockImplementation((filter, options) => buildQueryMock((session) => Array.from(getState(session ?? options?.session).storage.values()).filter(document => matchesFilter(document, filter)).length)),
393
- };
394
- /** The driver-level `model.collection` surface boot migrations use: index DDL and raw updates. */
395
- mockModel.collection = {
396
- indexes: vi.fn().mockImplementation(() => Promise.resolve([{ v: 2, key: { _id: 1 }, name: '_id_' }, ...indexStore.map((index) => cloneValue(index))])),
397
- createIndex: vi.fn().mockImplementation((keySpec, options = {}) => {
398
- const { name: requestedName, ...indexOptions } = options;
399
- const name = typeof requestedName === 'string'
400
- ? requestedName
401
- : Object.entries(keySpec).map(([field, direction]) => `${field}_${direction}`).join('_');
402
- const existing = indexStore.find((index) => index.name === name);
403
- if (existing) {
404
- const { v: _version, key: existingKey, name: _name, ...existingOptions } = existing;
405
- if (JSON.stringify(existingKey) === JSON.stringify(keySpec) && JSON.stringify(existingOptions) === JSON.stringify(indexOptions)) {
406
- return Promise.resolve(name);
407
- }
408
- return Promise.reject(Object.assign(new Error(`Index already exists with a different definition: ${name}`), { code: 85, codeName: 'IndexOptionsConflict' }));
409
- }
410
- indexStore = [...indexStore, { v: 2, key: { ...keySpec }, name, ...indexOptions }];
411
- return Promise.resolve(name);
412
- }),
413
- dropIndex: vi.fn().mockImplementation((name) => {
414
- if (!indexStore.some((index) => index.name === name)) {
415
- return Promise.reject(Object.assign(new Error(`index not found with name [${name}]`), { code: 27, codeName: 'IndexNotFound' }));
416
- }
417
- indexStore = indexStore.filter((index) => index.name !== name);
418
- return Promise.resolve({ ok: 1 });
419
- }),
420
- updateMany: mockModel.updateMany,
421
- };
422
- return mockModel;
423
- }
424
- //# sourceMappingURL=mock-mongoose-model.service.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mock-mongoose-model.service.js","sourceRoot":"","sources":["../../../../../../src/databases/services/__tests__/mock-mongoose-model.service.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * In-memory Mongoose `Model` factory for integration tests.\n *\n * **Naming**: `mock-*.service.ts` — canonical mock module, not a test suite.\n * Plain `.ts` keeps it barrel-compilable, and Vitest also excludes these files\n * explicitly as a defensive guard.\n */\nimport type { Model, Document } from 'mongoose';\nimport { vi } from 'vitest';\nimport {\n getMockMongoTransactionalState,\n registerMockMongoModel,\n} from './mock-mongo-transaction-registry.service';\n\n/** Mock mongoose model that stores data in memory */\n/**\n * @param surrogatePrimaryKeyFieldName - The AUTHORED name of a surrogate primary key, when the\n * resource declares one (FILES declares `fileId`, persisted as `_id`). Real Mongoose exposes it\n * as a VIRTUAL = `String(_id)`, so the repository's projection names the surrogate rather than\n * `_id` and then forces `_id` in for the virtual to resolve from. Without modelling that here, a\n * projected row carries `_id` and no surrogate, and any production code reading `row.fileId`\n * silently sees `undefined` — which is exactly what happened, in a batch, once the repository\n * started resolving surrogates for real.\n */\nexport function createMockModel<T extends Document>(name: string, surrogatePrimaryKeyFieldName?: string): Model<T> {\n let storage = new Map<string, any>();\n let autoIdCounter = 1;\n const modelStateKey = {};\n\n const cloneValue = <R>(value: R): R => structuredClone(value);\n\n const getValueAtPath = (value: unknown, path: string): unknown => {\n if (!path) {\n return value;\n }\n\n return path\n .split('.')\n .filter(Boolean)\n .reduce<unknown>((current, segment) => {\n if (!current || typeof current !== 'object') {\n return undefined;\n }\n\n return (current as Record<string, unknown>)[segment];\n }, value);\n };\n\n const setValueAtPath = (target: Record<string, unknown>, path: string, value: unknown): void => {\n const tokens = path.split('.').filter(Boolean);\n if (tokens.length === 0) {\n return;\n }\n\n let current: Record<string, unknown> = target;\n for (let index = 0; index < tokens.length - 1; index += 1) {\n const token = tokens[index];\n const next = current[token];\n if (!next || typeof next !== 'object') {\n current[token] = {};\n }\n current = current[token] as Record<string, unknown>;\n }\n\n current[tokens[tokens.length - 1]] = value;\n };\n\n const matchesExpectedValue = (actual: unknown, expected: unknown): boolean => {\n if (\n expected\n && typeof expected === 'object'\n && !Array.isArray(expected)\n && !('_bsontype' in (expected as Record<string, unknown>))\n ) {\n const operatorEntries = Object.entries(expected as Record<string, unknown>)\n .filter(([key]) => key.startsWith('$'));\n\n if (operatorEntries.length > 0) {\n return operatorEntries.every(([operator, value]) => {\n switch (operator) {\n case '$in':\n return Array.isArray(value) && value.some(candidate => String(candidate) === String(actual));\n case '$exists':\n return Boolean(value) ? actual !== undefined : actual === undefined;\n case '$lt': {\n if (actual === undefined || actual === null) {\n return false;\n }\n\n const normalizedActual = actual instanceof Date ? actual.getTime() : actual;\n const normalizedValue = value instanceof Date ? value.getTime() : value;\n return normalizedActual < normalizedValue;\n }\n case '$ne':\n return String(actual) !== String(value);\n case '$nin':\n return Array.isArray(value) && !value.some(candidate => String(candidate) === String(actual));\n case '$type':\n // Only the BSON aliases a caller of this double actually uses. An unmodelled alias throws rather\n // than matching nothing, which would read as \"no rows\" and hide the gap.\n switch (value) {\n case 'date': return actual instanceof Date;\n case 'string': return typeof actual === 'string';\n case 'number': return typeof actual === 'number';\n case 'bool': return typeof actual === 'boolean';\n default: throw new Error(`in-memory Mongo model: $type '${String(value)}' is not modelled`);\n }\n default:\n return false;\n }\n });\n }\n\n return Object.entries(expected as Record<string, unknown>).every(\n ([key, nestedExpected]) => matchesExpectedValue(\n actual && typeof actual === 'object' ? (actual as Record<string, unknown>)[key] : undefined,\n nestedExpected,\n ),\n );\n }\n\n if (actual instanceof Date || expected instanceof Date) {\n return String(actual) === String(expected);\n }\n\n if (\n actual !== null\n && actual !== undefined\n && expected !== null\n && expected !== undefined\n && typeof actual !== 'boolean'\n && typeof expected !== 'boolean'\n && typeof actual !== 'object'\n && typeof expected === 'object'\n ) {\n return String(actual) === String(expected);\n }\n\n return actual === expected;\n };\n\n const matchesFilter = (document: Record<string, unknown>, filter?: Record<string, unknown>): boolean => {\n if (!filter || Object.keys(filter).length === 0) {\n return true;\n }\n\n return Object.entries(filter).every(([key, expected]) => {\n if (key === '$or') {\n return Array.isArray(expected) && expected.some(\n (candidate) => matchesFilter(document, candidate as Record<string, unknown>),\n );\n }\n\n return matchesExpectedValue(getValueAtPath(document, key), expected);\n });\n };\n\n const applyProjection = (document: Record<string, unknown>, projection?: Record<string, unknown> | null) => {\n if (!projection || Object.keys(projection).length === 0) {\n return withSurrogatePrimaryKey(cloneValue(document) as Record<string, unknown>);\n }\n\n const includeKeys = Object.entries(projection)\n .filter(([, include]) => Boolean(include))\n .map(([field]) => field);\n\n if (includeKeys.length === 0) {\n return withSurrogatePrimaryKey(cloneValue(document) as Record<string, unknown>);\n }\n\n const projected: Record<string, unknown> = {};\n for (const field of includeKeys) {\n setValueAtPath(projected, field, getValueAtPath(document, field));\n }\n\n if (projection._id !== 0 && document._id !== undefined) {\n projected._id = document._id;\n }\n\n return withSurrogatePrimaryKey(projected);\n };\n\n /** Mirror Mongoose's surrogate virtual: `<surrogate> === String(_id)`. */\n const withSurrogatePrimaryKey = (document: Record<string, unknown>) => {\n if (!surrogatePrimaryKeyFieldName || document._id === undefined) return document;\n return { ...document, [surrogatePrimaryKeyFieldName]: String(document._id) };\n };\n\n const applyUpdate = (document: Record<string, unknown>, update: Record<string, any>) => {\n const nextDocument = cloneValue(document);\n\n for (const [field, value] of Object.entries(update.$set ?? {})) {\n setValueAtPath(nextDocument, field, value);\n }\n\n for (const [field, increment] of Object.entries(update.$inc ?? {})) {\n const currentValue = getValueAtPath(nextDocument, field);\n const nextValue = typeof currentValue === 'number'\n ? currentValue + Number(increment)\n : Number(increment);\n setValueAtPath(nextDocument, field, nextValue);\n }\n\n for (const field of Object.keys(update.$unset ?? {})) {\n const parts = field.split('.');\n const parent = parts.length === 1 ? nextDocument : getValueAtPath(nextDocument, parts.slice(0, -1).join('.'));\n if (parent && typeof parent === 'object') delete (parent as Record<string, unknown>)[parts[parts.length - 1]];\n }\n\n return nextDocument;\n };\n\n /**\n * An aggregation-PIPELINE update (`updateMany(filter, [{ $set: … }])`), which Mongo accepts wherever it\n * accepts an update document. Models `$set` with literal values, `$field` references and `$add` over\n * numbers and at most one Date (Mongo's date + milliseconds). Anything else throws: a double that silently\n * skips a stage reports a migration as applied when nothing was written.\n */\n const applyPipelineUpdate = (document: Record<string, unknown>, stages: Array<Record<string, any>>) => {\n const nextDocument = cloneValue(document);\n const evaluate = (expression: unknown): unknown => {\n if (typeof expression === 'string' && expression.startsWith('$')) {\n return getValueAtPath(nextDocument, expression.slice(1));\n }\n if (expression && typeof expression === 'object' && !Array.isArray(expression) && !(expression instanceof Date)) {\n const [operator, operands] = Object.entries(expression as Record<string, unknown>)[0] ?? [];\n if (operator === '$add' && Array.isArray(operands)) {\n const values = operands.map(evaluate);\n if (values.some((value) => value === null || value === undefined)) return null;\n const dates = values.filter((value): value is Date => value instanceof Date);\n if (dates.length > 1) throw new Error('in-memory Mongo model: $add over two dates is not valid');\n const sum = values.reduce<number>((total, value) => total + (value instanceof Date ? value.getTime() : Number(value)), 0);\n return dates.length === 1 ? new Date(sum) : sum;\n }\n if (operator?.startsWith('$')) throw new Error(`in-memory Mongo model: pipeline operator '${operator}' is not modelled`);\n }\n return expression;\n };\n for (const stage of stages) {\n const [stageName, stageBody] = Object.entries(stage)[0] ?? [];\n if (stageName !== '$set' || !stageBody || typeof stageBody !== 'object') {\n throw new Error(`in-memory Mongo model: pipeline stage '${String(stageName)}' is not modelled`);\n }\n for (const [field, expression] of Object.entries(stageBody as Record<string, unknown>)) {\n setValueAtPath(nextDocument, field, evaluate(expression));\n }\n }\n return nextDocument;\n };\n\n /**\n * The collection's secondary indexes, as `collection.indexes()` reports them (`_id_` is always present).\n * Not transactional: index DDL in Mongo is not part of a multi-document transaction either.\n */\n let indexStore: Array<Record<string, any>> = [];\n\n const getState = (session?: unknown) => {\n const transactionalState = getMockMongoTransactionalState(modelStateKey, session);\n if (transactionalState) {\n return transactionalState;\n }\n\n return {\n storage,\n autoIdCounter,\n };\n };\n\n const buildQueryMock = <R>(resolver: (session?: unknown) => R) => {\n let sortField: string | undefined;\n let sortDirection = 1;\n let skipCount = 0;\n let limitCount: number | undefined;\n let activeSession: unknown;\n\n const resolve = (): R => {\n const rawValue = resolver(activeSession);\n if (!Array.isArray(rawValue)) {\n return cloneValue(rawValue);\n }\n\n const value = [...rawValue].map(item => cloneValue(item));\n if (sortField) {\n value.sort((left, right) => {\n const leftValue = getValueAtPath(left, sortField);\n const rightValue = getValueAtPath(right, sortField);\n if (leftValue === rightValue) {\n return 0;\n }\n\n if (leftValue === undefined) {\n return 1;\n }\n\n if (rightValue === undefined) {\n return -1;\n }\n\n return leftValue < rightValue ? -1 * sortDirection : 1 * sortDirection;\n });\n }\n\n const sliced = value.slice(skipCount, limitCount === undefined ? undefined : skipCount + limitCount);\n return sliced as R;\n };\n\n const promise = () => Promise.resolve(resolve());\n const query = {\n sort: vi.fn((spec: Record<string, 1 | -1>) => {\n const [field, direction] = Object.entries(spec)[0] ?? [];\n sortField = field;\n sortDirection = direction ?? 1;\n return query;\n }),\n skip: vi.fn((count: number) => {\n skipCount = count;\n return query;\n }),\n limit: vi.fn((count: number) => {\n limitCount = count;\n return query;\n }),\n session: vi.fn((session: unknown) => {\n activeSession = session;\n return query;\n }),\n lean: vi.fn(() => promise()),\n exec: vi.fn(() => promise()),\n then: (onFulfilled?: (value: R) => unknown, onRejected?: (reason: unknown) => unknown) =>\n promise().then(onFulfilled, onRejected),\n catch: (onRejected?: (reason: unknown) => unknown) => promise().catch(onRejected),\n finally: (onFinally?: () => void) => promise().finally(onFinally),\n };\n\n return query;\n };\n\n const persistDocument = (document: Record<string, unknown>, session?: unknown) => {\n const state = getState(session);\n const id = String(\n document._id\n ?? state.autoIdCounter.toString(16).padStart(24, '0')\n );\n state.autoIdCounter += 1;\n if (!getMockMongoTransactionalState(modelStateKey, session)) {\n autoIdCounter = state.autoIdCounter;\n }\n const savedDocument = {\n ...cloneValue(document),\n _id: id,\n };\n state.storage.set(id, savedDocument);\n return cloneValue(savedDocument);\n };\n\n registerMockMongoModel(modelStateKey, {\n cloneState: () => ({\n storage: new Map(\n Array.from(storage.entries()).map(([id, document]) => [id, cloneValue(document)])\n ),\n autoIdCounter,\n }),\n applyState: (state) => {\n storage = new Map(\n Array.from(state.storage.entries()).map(([id, document]) => [id, cloneValue(document)])\n );\n autoIdCounter = state.autoIdCounter;\n },\n });\n\n const mockModel = {\n modelName: name,\n schema: {\n paths: {},\n },\n find: vi.fn().mockImplementation((filter?: Record<string, unknown>, projection?: Record<string, unknown> | null, options?: { session?: unknown }) =>\n buildQueryMock((session) =>\n Array.from(getState(session ?? options?.session).storage.values())\n .filter(document => matchesFilter(document, filter))\n .map(document => applyProjection(document, projection)),\n )\n ),\n findOne: vi.fn().mockImplementation((filter?: Record<string, unknown>, projection?: Record<string, unknown> | null, options?: { session?: unknown }) =>\n buildQueryMock((session) => {\n const document = Array.from(getState(session ?? options?.session).storage.values()).find(candidate => matchesFilter(candidate, filter));\n return document ? applyProjection(document, projection) : null;\n })\n ),\n findById: vi.fn().mockImplementation((id: string, _projection?: unknown, options?: { session?: unknown }) =>\n buildQueryMock((session) => {\n const document = getState(session ?? options?.session).storage.get(id);\n return document ? cloneValue(document) : null;\n })\n ),\n create: vi.fn().mockImplementation((doc: any, options?: { session?: unknown }) => {\n if (Array.isArray(doc)) {\n return Promise.resolve(doc.map(item => persistDocument(item, options?.session)) as unknown as T[]);\n }\n\n return Promise.resolve(persistDocument(doc, options?.session) as unknown as T);\n }),\n insertMany: vi.fn().mockImplementation((docs: any[], options?: { session?: unknown }) =>\n Promise.resolve(docs.map(document => persistDocument(document, options?.session)) as unknown as T[])\n ),\n // Mongoose writes are thenable queries, not bare promises. Infrastructure\n // guarded mutations use .exec(), ordinary updates await the same query.\n findOneAndUpdate: vi.fn().mockImplementation((filter: Record<string, unknown>, update: Record<string, any>, options?: { session?: unknown }) =>\n buildQueryMock((session) => {\n const state = getState(session ?? options?.session);\n const existingEntry = Array.from(state.storage.entries()).find(([, document]) => matchesFilter(document, filter));\n if (!existingEntry) return null;\n const [id, document] = existingEntry;\n const updated = applyUpdate(document, update);\n state.storage.set(id, updated);\n return cloneValue(updated) as T;\n })\n ),\n findByIdAndUpdate: vi.fn().mockImplementation((id: string, update: any, options?: { session?: unknown }) => {\n const state = getState(options?.session);\n const existing = state.storage.get(id);\n if (!existing) {\n return Promise.resolve(null);\n }\n\n const updated = applyUpdate(existing, update);\n state.storage.set(id, updated);\n return Promise.resolve(cloneValue(updated) as T);\n }),\n updateMany: vi.fn().mockImplementation((filter: Record<string, unknown>, update: Record<string, any>, options?: { session?: unknown }) => {\n const state = getState(options?.session);\n let matchedCount = 0;\n\n for (const [id, document] of state.storage.entries()) {\n if (!matchesFilter(document, filter)) {\n continue;\n }\n\n matchedCount += 1;\n state.storage.set(id, Array.isArray(update) ? applyPipelineUpdate(document, update) : applyUpdate(document, update));\n }\n\n return Promise.resolve({\n matchedCount,\n modifiedCount: matchedCount,\n });\n }),\n findByIdAndDelete: vi.fn().mockImplementation((id: string, options?: { session?: unknown }) => {\n const state = getState(options?.session);\n const existing = state.storage.get(id);\n state.storage.delete(id);\n return Promise.resolve(existing ? cloneValue(existing) : null);\n }),\n deleteMany: vi.fn().mockImplementation((filter: Record<string, unknown>, options?: { session?: unknown }) => {\n const state = getState(options?.session);\n let deletedCount = 0;\n\n for (const [id, document] of Array.from(state.storage.entries())) {\n if (!matchesFilter(document, filter)) {\n continue;\n }\n\n state.storage.delete(id);\n deletedCount += 1;\n }\n\n return Promise.resolve({ deletedCount });\n }),\n deleteOne: vi.fn().mockImplementation((filter: Record<string, unknown>, options?: { session?: unknown }) => {\n const state = getState(options?.session);\n for (const [id, document] of Array.from(state.storage.entries())) {\n if (!matchesFilter(document, filter)) {\n continue;\n }\n\n state.storage.delete(id);\n return Promise.resolve({ deletedCount: 1 });\n }\n\n return Promise.resolve({ deletedCount: 0 });\n }),\n // Mongo creates a collection on first write; an explicit create is idempotent here as for an existing one.\n createCollection: vi.fn().mockImplementation(() => Promise.resolve(undefined)),\n countDocuments: vi.fn().mockImplementation((filter?: Record<string, unknown>, options?: { session?: unknown }) =>\n buildQueryMock((session) =>\n Array.from(getState(session ?? options?.session).storage.values()).filter(document => matchesFilter(document, filter)).length\n )\n ),\n } as unknown as Model<T>;\n\n /** The driver-level `model.collection` surface boot migrations use: index DDL and raw updates. */\n (mockModel as unknown as { collection: unknown }).collection = {\n indexes: vi.fn().mockImplementation(() =>\n Promise.resolve([{ v: 2, key: { _id: 1 }, name: '_id_' }, ...indexStore.map((index) => cloneValue(index))])),\n createIndex: vi.fn().mockImplementation((keySpec: Record<string, 1 | -1>, options: Record<string, unknown> = {}) => {\n const { name: requestedName, ...indexOptions } = options;\n const name = typeof requestedName === 'string'\n ? requestedName\n : Object.entries(keySpec).map(([field, direction]) => `${field}_${direction}`).join('_');\n const existing = indexStore.find((index) => index.name === name);\n if (existing) {\n const { v: _version, key: existingKey, name: _name, ...existingOptions } = existing;\n if (JSON.stringify(existingKey) === JSON.stringify(keySpec) && JSON.stringify(existingOptions) === JSON.stringify(indexOptions)) {\n return Promise.resolve(name);\n }\n return Promise.reject(Object.assign(new Error(`Index already exists with a different definition: ${name}`), { code: 85, codeName: 'IndexOptionsConflict' }));\n }\n indexStore = [...indexStore, { v: 2, key: { ...keySpec }, name, ...indexOptions }];\n return Promise.resolve(name);\n }),\n dropIndex: vi.fn().mockImplementation((name: string) => {\n if (!indexStore.some((index) => index.name === name)) {\n return Promise.reject(Object.assign(new Error(`index not found with name [${name}]`), { code: 27, codeName: 'IndexNotFound' }));\n }\n indexStore = indexStore.filter((index) => index.name !== name);\n return Promise.resolve({ ok: 1 });\n }),\n updateMany: (mockModel as unknown as { updateMany: (...args: unknown[]) => unknown }).updateMany,\n };\n\n return mockModel;\n}\n"]}
@@ -1,19 +0,0 @@
1
- /**
2
- * Vitest-oriented mock Zod → Mongoose convertor for integration tests (`vi.fn` on methods).
3
- *
4
- * **Naming**: `mock-*.service.ts` — canonical mock module, not a test suite.
5
- * Plain `.ts` keeps it barrel-compilable, and Vitest also excludes these files
6
- * explicitly as a defensive guard.
7
- */
8
- import 'reflect-metadata';
9
- import type { Model } from 'mongoose';
10
- export declare class MockZodToMongooseSchemaConvertorBackendService {
11
- private models;
12
- convertResourceConfigurationToModel: import("vitest").Mock<[resourceConfig: any, _options?: any], {
13
- mainModel: Model<any, {}, {}, {}, any, any>;
14
- inheritanceSchemas: any[];
15
- }>;
16
- getModel(name: string): Model<any> | undefined;
17
- reset(): void;
18
- }
19
- //# sourceMappingURL=mock-zod-mongoose-schema-convertor.service.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"mock-zod-mongoose-schema-convertor.service.d.ts","sourceRoot":"","sources":["../../../../../../src/databases/services/__tests__/mock-zod-mongoose-schema-convertor.service.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,kBAAkB,CAAC;AAE1B,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAMtC,qBACa,8CAA8C;IACzD,OAAO,CAAC,MAAM,CAAiC;IAE/C,mCAAmC;;;OAiBhC;IAEH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS;IAI9C,KAAK;CAKN"}