@volontariapp/domain-storage 0.7.0 → 0.8.0-snap-cde7a1d

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 (56) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/enums/attachment-refusal-reason.enum.d.ts +7 -0
  3. package/dist/enums/attachment-refusal-reason.enum.d.ts.map +1 -0
  4. package/dist/enums/attachment-refusal-reason.enum.js +8 -0
  5. package/dist/enums/attachment-refusal-reason.enum.js.map +1 -0
  6. package/dist/enums/index.d.ts +1 -0
  7. package/dist/enums/index.d.ts.map +1 -1
  8. package/dist/enums/index.js +1 -0
  9. package/dist/enums/index.js.map +1 -1
  10. package/dist/exceptions/file-attachment-refused.exception.d.ts +7 -0
  11. package/dist/exceptions/file-attachment-refused.exception.d.ts.map +1 -0
  12. package/dist/exceptions/file-attachment-refused.exception.js +7 -0
  13. package/dist/exceptions/file-attachment-refused.exception.js.map +1 -0
  14. package/dist/exceptions/index.d.ts +2 -0
  15. package/dist/exceptions/index.d.ts.map +1 -1
  16. package/dist/exceptions/index.js +2 -0
  17. package/dist/exceptions/index.js.map +1 -1
  18. package/dist/exceptions/too-many-files.exception.d.ts +6 -0
  19. package/dist/exceptions/too-many-files.exception.d.ts.map +1 -0
  20. package/dist/exceptions/too-many-files.exception.js +7 -0
  21. package/dist/exceptions/too-many-files.exception.js.map +1 -0
  22. package/dist/policies/attachment-validation.rule.d.ts +28 -0
  23. package/dist/policies/attachment-validation.rule.d.ts.map +1 -0
  24. package/dist/policies/attachment-validation.rule.js +40 -0
  25. package/dist/policies/attachment-validation.rule.js.map +1 -0
  26. package/dist/policies/index.d.ts +1 -0
  27. package/dist/policies/index.d.ts.map +1 -1
  28. package/dist/policies/index.js +1 -0
  29. package/dist/policies/index.js.map +1 -1
  30. package/dist/repositories/file-repository.types.d.ts +15 -0
  31. package/dist/repositories/file-repository.types.d.ts.map +1 -1
  32. package/dist/repositories/postgres-file.repository.d.ts +2 -1
  33. package/dist/repositories/postgres-file.repository.d.ts.map +1 -1
  34. package/dist/repositories/postgres-file.repository.js +67 -0
  35. package/dist/repositories/postgres-file.repository.js.map +1 -1
  36. package/dist/test/attachment-exceptions.unit.spec.d.ts +2 -0
  37. package/dist/test/attachment-exceptions.unit.spec.d.ts.map +1 -0
  38. package/dist/test/attachment-exceptions.unit.spec.js +26 -0
  39. package/dist/test/attachment-exceptions.unit.spec.js.map +1 -0
  40. package/dist/test/attachment-validation.rule.unit.spec.d.ts +2 -0
  41. package/dist/test/attachment-validation.rule.unit.spec.d.ts.map +1 -0
  42. package/dist/test/attachment-validation.rule.unit.spec.js +83 -0
  43. package/dist/test/attachment-validation.rule.unit.spec.js.map +1 -0
  44. package/dist/test/factories/attachment.factory.d.ts +4 -0
  45. package/dist/test/factories/attachment.factory.d.ts.map +1 -0
  46. package/dist/test/factories/attachment.factory.js +19 -0
  47. package/dist/test/factories/attachment.factory.js.map +1 -0
  48. package/dist/test/integration/postgres-file.repository.reserve.int.spec.d.ts +2 -0
  49. package/dist/test/integration/postgres-file.repository.reserve.int.spec.d.ts.map +1 -0
  50. package/dist/test/integration/postgres-file.repository.reserve.int.spec.js +205 -0
  51. package/dist/test/integration/postgres-file.repository.reserve.int.spec.js.map +1 -0
  52. package/dist/test/mocks/file-update-failure.mock.d.ts +2 -0
  53. package/dist/test/mocks/file-update-failure.mock.d.ts.map +1 -0
  54. package/dist/test/mocks/file-update-failure.mock.js +17 -0
  55. package/dist/test/mocks/file-update-failure.mock.js.map +1 -0
  56. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [`5cf1c51`](https://github.com/Volontariapp/npm-packages/commit/5cf1c51503e441ac7f232b9ab96d7df33470632a) Thanks [@VictorAgahi](https://github.com/VictorAgahi)! - Add the shared attachment validation rule (`classifyFileForAttachment`) and `PostgresFileRepository.reserve`, the synchronous all-or-nothing reservation of `ConfirmFileAttachment`, with the `FileAttachmentRefusedException` and `TooManyFilesException` domain errors.
8
+
3
9
  ## 0.7.0
4
10
 
5
11
  ### Minor Changes
@@ -0,0 +1,7 @@
1
+ export declare enum AttachmentRefusalReason {
2
+ ENTITY_TYPE_MISMATCH = "ENTITY_TYPE_MISMATCH",
3
+ SCAN_STATUS_NOT_ACCEPTED = "SCAN_STATUS_NOT_ACCEPTED",
4
+ ATTACHED_TO_ANOTHER_ENTITY = "ATTACHED_TO_ANOTHER_ENTITY",
5
+ FILE_RELEASED = "FILE_RELEASED"
6
+ }
7
+ //# sourceMappingURL=attachment-refusal-reason.enum.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-refusal-reason.enum.d.ts","sourceRoot":"","sources":["../../src/enums/attachment-refusal-reason.enum.ts"],"names":[],"mappings":"AACA,oBAAY,uBAAuB;IAEjC,oBAAoB,yBAAyB;IAE7C,wBAAwB,6BAA6B;IAErD,0BAA0B,+BAA+B;IAEzD,aAAa,kBAAkB;CAChC"}
@@ -0,0 +1,8 @@
1
+ export var AttachmentRefusalReason;
2
+ (function (AttachmentRefusalReason) {
3
+ AttachmentRefusalReason["ENTITY_TYPE_MISMATCH"] = "ENTITY_TYPE_MISMATCH";
4
+ AttachmentRefusalReason["SCAN_STATUS_NOT_ACCEPTED"] = "SCAN_STATUS_NOT_ACCEPTED";
5
+ AttachmentRefusalReason["ATTACHED_TO_ANOTHER_ENTITY"] = "ATTACHED_TO_ANOTHER_ENTITY";
6
+ AttachmentRefusalReason["FILE_RELEASED"] = "FILE_RELEASED";
7
+ })(AttachmentRefusalReason || (AttachmentRefusalReason = {}));
8
+ //# sourceMappingURL=attachment-refusal-reason.enum.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-refusal-reason.enum.js","sourceRoot":"","sources":["../../src/enums/attachment-refusal-reason.enum.ts"],"names":[],"mappings":"AACA,MAAM,CAAN,IAAY,uBASX;AATD,WAAY,uBAAuB;IAEjC,wEAA6C,CAAA;IAE7C,gFAAqD,CAAA;IAErD,oFAAyD,CAAA;IAEzD,0DAA+B,CAAA;AACjC,CAAC,EATW,uBAAuB,KAAvB,uBAAuB,QASlC"}
@@ -3,4 +3,5 @@ export * from './entity-type.enum.js';
3
3
  export * from './scan-status.enum.js';
4
4
  export * from './validation-mode.enum.js';
5
5
  export * from './rejection-reason.enum.js';
6
+ export * from './attachment-refusal-reason.enum.js';
6
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enums/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/enums/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC"}
@@ -3,4 +3,5 @@ export * from './entity-type.enum.js';
3
3
  export * from './scan-status.enum.js';
4
4
  export * from './validation-mode.enum.js';
5
5
  export * from './rejection-reason.enum.js';
6
+ export * from './attachment-refusal-reason.enum.js';
6
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enums/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/enums/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,uBAAuB,CAAC;AACtC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,qCAAqC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import { UnprocessableEntityError } from '@volontariapp/errors';
2
+ import type { AttachmentRefusalReason } from '../enums/attachment-refusal-reason.enum.js';
3
+ import type { EntityType } from '../enums/entity-type.enum.js';
4
+ export declare class FileAttachmentRefusedException extends UnprocessableEntityError {
5
+ constructor(fileId: string, reason: AttachmentRefusalReason, entityType: EntityType, entityId: string);
6
+ }
7
+ //# sourceMappingURL=file-attachment-refused.exception.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-attachment-refused.exception.d.ts","sourceRoot":"","sources":["../../src/exceptions/file-attachment-refused.exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAChE,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAC1F,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAO/D,qBAAa,8BAA+B,SAAQ,wBAAwB;gBAExE,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,uBAAuB,EAC/B,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,MAAM;CAQnB"}
@@ -0,0 +1,7 @@
1
+ import { UnprocessableEntityError } from '@volontariapp/errors';
2
+ export class FileAttachmentRefusedException extends UnprocessableEntityError {
3
+ constructor(fileId, reason, entityType, entityId) {
4
+ super(`File '${fileId}' cannot be attached to ${entityType} '${entityId}': ${reason}.`, 'FILE_ATTACHMENT_REFUSED', { fileId, reason, entityType, entityId });
5
+ }
6
+ }
7
+ //# sourceMappingURL=file-attachment-refused.exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-attachment-refused.exception.js","sourceRoot":"","sources":["../../src/exceptions/file-attachment-refused.exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAC;AAShE,MAAM,OAAO,8BAA+B,SAAQ,wBAAwB;IAC1E,YACE,MAAc,EACd,MAA+B,EAC/B,UAAsB,EACtB,QAAgB;QAEhB,KAAK,CACH,SAAS,MAAM,2BAA2B,UAAU,KAAK,QAAQ,MAAM,MAAM,GAAG,EAChF,yBAAyB,EACzB,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,CACzC,CAAC;IACJ,CAAC;CACF"}
@@ -2,4 +2,6 @@ export * from './file-not-found.exception.js';
2
2
  export * from './file-size-not-allowed.exception.js';
3
3
  export * from './invalid-entity-type.exception.js';
4
4
  export * from './invalid-file-extension.exception.js';
5
+ export * from './file-attachment-refused.exception.js';
6
+ export * from './too-many-files.exception.js';
5
7
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exceptions/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/exceptions/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC"}
@@ -2,4 +2,6 @@ export * from './file-not-found.exception.js';
2
2
  export * from './file-size-not-allowed.exception.js';
3
3
  export * from './invalid-entity-type.exception.js';
4
4
  export * from './invalid-file-extension.exception.js';
5
+ export * from './file-attachment-refused.exception.js';
6
+ export * from './too-many-files.exception.js';
5
7
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exceptions/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/exceptions/index.ts"],"names":[],"mappings":"AAAA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,sCAAsC,CAAC;AACrD,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,wCAAwC,CAAC;AACvD,cAAc,+BAA+B,CAAC"}
@@ -0,0 +1,6 @@
1
+ import { BadRequestError } from '@volontariapp/errors';
2
+ import type { EntityType } from '../enums/entity-type.enum.js';
3
+ export declare class TooManyFilesException extends BadRequestError {
4
+ constructor(entityType: EntityType, count: number, maxPerEntity: number);
5
+ }
6
+ //# sourceMappingURL=too-many-files.exception.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"too-many-files.exception.d.ts","sourceRoot":"","sources":["../../src/exceptions/too-many-files.exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAE/D,qBAAa,qBAAsB,SAAQ,eAAe;gBAC5C,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM;CAOxE"}
@@ -0,0 +1,7 @@
1
+ import { BadRequestError } from '@volontariapp/errors';
2
+ export class TooManyFilesException extends BadRequestError {
3
+ constructor(entityType, count, maxPerEntity) {
4
+ super(`${String(count)} files exceed the limit of ${String(maxPerEntity)} for entity type '${entityType}'.`, 'TOO_MANY_FILES', { entityType, count, maxPerEntity });
5
+ }
6
+ }
7
+ //# sourceMappingURL=too-many-files.exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"too-many-files.exception.js","sourceRoot":"","sources":["../../src/exceptions/too-many-files.exception.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,MAAM,OAAO,qBAAsB,SAAQ,eAAe;IACxD,YAAY,UAAsB,EAAE,KAAa,EAAE,YAAoB;QACrE,KAAK,CACH,GAAG,MAAM,CAAC,KAAK,CAAC,8BAA8B,MAAM,CAAC,YAAY,CAAC,qBAAqB,UAAU,IAAI,EACrG,gBAAgB,EAChB,EAAE,UAAU,EAAE,KAAK,EAAE,YAAY,EAAE,CACpC,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,28 @@
1
+ import { AttachmentRefusalReason } from '../enums/attachment-refusal-reason.enum.js';
2
+ import type { EntityType } from '../enums/entity-type.enum.js';
3
+ import { FileStatus } from '../enums/file-status.enum.js';
4
+ import { ScanStatus } from '../enums/scan-status.enum.js';
5
+ export interface AttachmentCandidate {
6
+ ownerId: string;
7
+ entityType: EntityType;
8
+ entityId: string | null;
9
+ status: FileStatus;
10
+ scanStatus: ScanStatus;
11
+ }
12
+ export interface AttachmentTarget {
13
+ ownerId: string;
14
+ entityType: EntityType;
15
+ entityId: string;
16
+ }
17
+ export type AttachmentVerdict = {
18
+ readonly kind: 'RESERVE';
19
+ } | {
20
+ readonly kind: 'ALREADY_HELD';
21
+ } | {
22
+ readonly kind: 'NOT_FOUND';
23
+ } | {
24
+ readonly kind: 'REFUSED';
25
+ readonly reason: AttachmentRefusalReason;
26
+ };
27
+ export declare function classifyFileForAttachment(file: AttachmentCandidate | null, target: AttachmentTarget): AttachmentVerdict;
28
+ //# sourceMappingURL=attachment-validation.rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-validation.rule.d.ts","sourceRoot":"","sources":["../../src/policies/attachment-validation.rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAI1D,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC;IACnB,UAAU,EAAE,UAAU,CAAC;CACxB;AAGD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,MAAM,iBAAiB,GAEzB;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAA;CAAE,GAE5B;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GAEjC;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,CAAC;AA6B3E,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,mBAAmB,GAAG,IAAI,EAChC,MAAM,EAAE,gBAAgB,GACvB,iBAAiB,CA6BnB"}
@@ -0,0 +1,40 @@
1
+ import { AttachmentRefusalReason } from '../enums/attachment-refusal-reason.enum.js';
2
+ import { FileStatus } from '../enums/file-status.enum.js';
3
+ import { ScanStatus } from '../enums/scan-status.enum.js';
4
+ import { getValidationPolicy } from './get-validation-policy.js';
5
+ const RESERVE = { kind: 'RESERVE' };
6
+ const ALREADY_HELD = { kind: 'ALREADY_HELD' };
7
+ const NOT_FOUND = { kind: 'NOT_FOUND' };
8
+ const refused = (reason) => ({
9
+ kind: 'REFUSED',
10
+ reason,
11
+ });
12
+ const isSameEntity = (file, target) => file.entityType === target.entityType &&
13
+ file.entityId?.toLowerCase() === target.entityId.toLowerCase();
14
+ export function classifyFileForAttachment(file, target) {
15
+ if (file?.ownerId !== target.ownerId) {
16
+ return NOT_FOUND;
17
+ }
18
+ if (file.entityType !== target.entityType) {
19
+ return refused(AttachmentRefusalReason.ENTITY_TYPE_MISMATCH);
20
+ }
21
+ const { asyncAllowed } = getValidationPolicy(target.entityType);
22
+ const scanAccepted = file.scanStatus === ScanStatus.CLEAN ||
23
+ (file.scanStatus === ScanStatus.SCANNING && asyncAllowed);
24
+ if (!scanAccepted) {
25
+ return refused(AttachmentRefusalReason.SCAN_STATUS_NOT_ACCEPTED);
26
+ }
27
+ switch (file.status) {
28
+ case FileStatus.PENDING:
29
+ return RESERVE;
30
+ case FileStatus.RESERVED:
31
+ case FileStatus.ATTACHED:
32
+ return isSameEntity(file, target)
33
+ ? ALREADY_HELD
34
+ : refused(AttachmentRefusalReason.ATTACHED_TO_ANOTHER_ENTITY);
35
+ case FileStatus.ORPHANED:
36
+ case FileStatus.DELETED:
37
+ return refused(AttachmentRefusalReason.FILE_RELEASED);
38
+ }
39
+ }
40
+ //# sourceMappingURL=attachment-validation.rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-validation.rule.js","sourceRoot":"","sources":["../../src/policies/attachment-validation.rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AAErF,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AA2BjE,MAAM,OAAO,GAAsB,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACvD,MAAM,YAAY,GAAsB,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;AACjE,MAAM,SAAS,GAAsB,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAE3D,MAAM,OAAO,GAAG,CAAC,MAA+B,EAAqB,EAAE,CAAC,CAAC;IACvE,IAAI,EAAE,SAAS;IACf,MAAM;CACP,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,CAAC,IAAyB,EAAE,MAAwB,EAAW,EAAE,CACpF,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU;IACrC,IAAI,CAAC,QAAQ,EAAE,WAAW,EAAE,KAAK,MAAM,CAAC,QAAQ,CAAC,WAAW,EAAE,CAAC;AAgBjE,MAAM,UAAU,yBAAyB,CACvC,IAAgC,EAChC,MAAwB;IAExB,IAAI,IAAI,EAAE,OAAO,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;QACrC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;QAC1C,OAAO,OAAO,CAAC,uBAAuB,CAAC,oBAAoB,CAAC,CAAC;IAC/D,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,GAAG,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAChE,MAAM,YAAY,GAChB,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,KAAK;QACpC,CAAC,IAAI,CAAC,UAAU,KAAK,UAAU,CAAC,QAAQ,IAAI,YAAY,CAAC,CAAC;IAC5D,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,OAAO,CAAC,uBAAuB,CAAC,wBAAwB,CAAC,CAAC;IACnE,CAAC;IAED,QAAQ,IAAI,CAAC,MAAM,EAAE,CAAC;QACpB,KAAK,UAAU,CAAC,OAAO;YACrB,OAAO,OAAO,CAAC;QACjB,KAAK,UAAU,CAAC,QAAQ,CAAC;QACzB,KAAK,UAAU,CAAC,QAAQ;YACtB,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC;gBAC/B,CAAC,CAAC,YAAY;gBACd,CAAC,CAAC,OAAO,CAAC,uBAAuB,CAAC,0BAA0B,CAAC,CAAC;QAClE,KAAK,UAAU,CAAC,QAAQ,CAAC;QACzB,KAAK,UAAU,CAAC,OAAO;YACrB,OAAO,OAAO,CAAC,uBAAuB,CAAC,aAAa,CAAC,CAAC;IAC1D,CAAC;AACH,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './validation-policy.constants.js';
2
2
  export * from './resolve-validation-mode.js';
3
3
  export * from './get-validation-policy.js';
4
+ export * from './attachment-validation.rule.js';
4
5
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC"}
@@ -1,4 +1,5 @@
1
1
  export * from './validation-policy.constants.js';
2
2
  export * from './resolve-validation-mode.js';
3
3
  export * from './get-validation-policy.js';
4
+ export * from './attachment-validation.rule.js';
4
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/policies/index.ts"],"names":[],"mappings":"AAAA,cAAc,kCAAkC,CAAC;AACjD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,4BAA4B,CAAC;AAC3C,cAAc,iCAAiC,CAAC"}
@@ -1,5 +1,6 @@
1
1
  import type { EntityType } from '../enums/entity-type.enum.js';
2
2
  import type { FileStatus } from '../enums/file-status.enum.js';
3
+ import type { ScanStatus } from '../enums/scan-status.enum.js';
3
4
  import type { RejectionReason } from '../enums/rejection-reason.enum.js';
4
5
  import type { ValidationMode } from '../enums/validation-mode.enum.js';
5
6
  export interface CreatePendingFileInput {
@@ -21,6 +22,20 @@ export interface ConfirmUploadResult {
21
22
  id: string;
22
23
  validationMode: ValidationMode;
23
24
  }
25
+ export interface ReserveFilesInput {
26
+ fileIds: readonly string[];
27
+ entityType: EntityType;
28
+ entityId: string;
29
+ ownerId: string;
30
+ }
31
+ export interface ReservationRow {
32
+ id: string;
33
+ owner_id: string;
34
+ entity_type: EntityType;
35
+ entity_id: string | null;
36
+ status: FileStatus;
37
+ scan_status: ScanStatus;
38
+ }
24
39
  export interface CompleteScanInput {
25
40
  fileId: string;
26
41
  publicKey: string;
@@ -1 +1 @@
1
- {"version":3,"file":"file-repository.types.d.ts","sourceRoot":"","sources":["../../src/repositories/file-repository.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IAErC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;CACzB;AAGD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,UAAU,CAAC;IAEnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAGD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"file-repository.types.d.ts","sourceRoot":"","sources":["../../src/repositories/file-repository.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AAEvE,MAAM,WAAW,sBAAsB;IAErC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,UAAU,CAAC;IACvB,gBAAgB,EAAE,MAAM,CAAC;IACzB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,cAAc,CAAC;IAC/B,eAAe,EAAE,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,cAAc,EAAE,cAAc,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAEhC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IAEjB,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;CACzB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;CACzB;AAGD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,UAAU,CAAC;IAEnB,YAAY,EAAE,OAAO,CAAC;CACvB;AAGD,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,UAAU,CAAC;IACnB,WAAW,EAAE,UAAU,CAAC;IACxB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,QAAQ,EAAE,MAAM,CAAC;CAClB"}
@@ -1,6 +1,6 @@
1
1
  import type { DataSource } from 'typeorm';
2
2
  import { FileModel } from '../models/file.model.js';
3
- import type { CompleteScanInput, ConfirmUploadInput, ConfirmUploadResult, CreatePendingFileInput, RejectScanInput, ScanTransitionResult } from './file-repository.types.js';
3
+ import type { CompleteScanInput, ConfirmUploadInput, ConfirmUploadResult, CreatePendingFileInput, RejectScanInput, ReserveFilesInput, ScanTransitionResult } from './file-repository.types.js';
4
4
  export declare const RESET_UPLOAD_DELAY_MINUTES = 15;
5
5
  export declare class PostgresFileRepository {
6
6
  private readonly dataSource;
@@ -10,6 +10,7 @@ export declare class PostgresFileRepository {
10
10
  confirmUpload(input: ConfirmUploadInput): Promise<ConfirmUploadResult | null>;
11
11
  switchToAsync(fileId: string): Promise<boolean>;
12
12
  resetToAwaitingUpload(fileId: string): Promise<boolean>;
13
+ reserve(input: ReserveFilesInput): Promise<FileModel[]>;
13
14
  completeScan(input: CompleteScanInput): Promise<ScanTransitionResult | null>;
14
15
  rejectScan(input: RejectScanInput): Promise<ScanTransitionResult | null>;
15
16
  private finishScan;
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-file.repository.d.ts","sourceRoot":"","sources":["../../src/repositories/postgres-file.repository.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,SAAS,CAAC;AAIzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAMpD,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EACf,oBAAoB,EAErB,MAAM,4BAA4B,CAAC;AAGpC,eAAO,MAAM,0BAA0B,KAAK,CAAC;AAuB7C,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;gBAElD,UAAU,EAAE,UAAU;IAG7C,aAAa,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC;IAkBhE,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAsC7E,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB/C,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBvD,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAkB5E,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAiBhE,UAAU;YAmCV,gBAAgB;YAahB,YAAY;IAQ1B,OAAO,CAAC,aAAa;CAOtB"}
1
+ {"version":3,"file":"postgres-file.repository.d.ts","sourceRoot":"","sources":["../../src/repositories/postgres-file.repository.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,SAAS,CAAC;AAOzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AASpD,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,mBAAmB,EACnB,sBAAsB,EACtB,eAAe,EAEf,iBAAiB,EACjB,oBAAoB,EAErB,MAAM,4BAA4B,CAAC;AAGpC,eAAO,MAAM,0BAA0B,KAAK,CAAC;AA0B7C,qBAAa,sBAAsB;IAGrB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAFvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwD;gBAElD,UAAU,EAAE,UAAU;IAG7C,aAAa,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,SAAS,CAAC;IAkBhE,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,GAAG,IAAI,CAAC;IAsC7E,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAyB/C,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IA4BvD,OAAO,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IA2FvD,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAkB5E,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;YAiBhE,UAAU;YAmCV,gBAAgB;YAahB,YAAY;IAQ1B,OAAO,CAAC,aAAa;CAOtB"}
@@ -1,9 +1,15 @@
1
1
  import { EventQueueModel, JobsOutboxModel } from '@volontariapp/database';
2
2
  import { Logger } from '@volontariapp/logger';
3
+ import { In } from 'typeorm';
3
4
  import { FileStatus } from '../enums/file-status.enum.js';
4
5
  import { ScanStatus } from '../enums/scan-status.enum.js';
5
6
  import { ValidationMode } from '../enums/validation-mode.enum.js';
7
+ import { FileAttachmentRefusedException } from '../exceptions/file-attachment-refused.exception.js';
8
+ import { FileNotFoundException } from '../exceptions/file-not-found.exception.js';
9
+ import { TooManyFilesException } from '../exceptions/too-many-files.exception.js';
6
10
  import { FileModel } from '../models/file.model.js';
11
+ import { classifyFileForAttachment } from '../policies/attachment-validation.rule.js';
12
+ import { getValidationPolicy } from '../policies/get-validation-policy.js';
7
13
  import { buildFileRejectedEvent, buildFileScannedEvent, buildScanFileJob, } from './file-outbox.builders.js';
8
14
  export const RESET_UPLOAD_DELAY_MINUTES = 15;
9
15
  export class PostgresFileRepository {
@@ -75,6 +81,67 @@ export class PostgresFileRepository {
75
81
  this.logTransition('resetToAwaitingUpload', fileId, reset);
76
82
  return reset;
77
83
  }
84
+ async reserve(input) {
85
+ const fileIds = [...new Set(input.fileIds)];
86
+ const { maxPerEntity } = getValidationPolicy(input.entityType);
87
+ if (fileIds.length > maxPerEntity) {
88
+ throw new TooManyFilesException(input.entityType, fileIds.length, maxPerEntity);
89
+ }
90
+ if (fileIds.length === 0)
91
+ return [];
92
+ const label = `${input.entityType} ${input.entityId}`;
93
+ const outcome = await this.runInTransaction('reserve', label, async (manager) => {
94
+ const rows = await manager.query(`SELECT id, owner_id, entity_type, entity_id, status, scan_status
95
+ FROM files
96
+ WHERE id = ANY($1::uuid[])
97
+ ORDER BY id
98
+ FOR UPDATE`, [fileIds]);
99
+ const rowById = new Map(rows.map((row) => [row.id, row]));
100
+ const verdicts = fileIds.map((fileId) => {
101
+ const row = rowById.get(fileId);
102
+ return [
103
+ fileId,
104
+ classifyFileForAttachment(row
105
+ ? {
106
+ ownerId: row.owner_id,
107
+ entityType: row.entity_type,
108
+ entityId: row.entity_id,
109
+ status: row.status,
110
+ scanStatus: row.scan_status,
111
+ }
112
+ : null, input),
113
+ ];
114
+ });
115
+ const missing = verdicts.find(([, verdict]) => verdict.kind === 'NOT_FOUND');
116
+ if (missing)
117
+ return { failure: new FileNotFoundException(missing[0]) };
118
+ for (const [fileId, verdict] of verdicts) {
119
+ if (verdict.kind === 'REFUSED') {
120
+ return {
121
+ failure: new FileAttachmentRefusedException(fileId, verdict.reason, input.entityType, input.entityId),
122
+ };
123
+ }
124
+ }
125
+ const toReserve = verdicts
126
+ .filter(([, verdict]) => verdict.kind === 'RESERVE')
127
+ .map(([fileId]) => fileId);
128
+ if (toReserve.length > 0) {
129
+ await manager.query(`UPDATE files
130
+ SET status = $1, entity_id = $2, reserved_at = now(), updated_at = now()
131
+ WHERE id = ANY($3::uuid[]) AND status = $4`, [FileStatus.RESERVED, input.entityId, toReserve, FileStatus.PENDING]);
132
+ }
133
+ const files = await manager.find(FileModel, { where: { id: In(fileIds) } });
134
+ const fileById = new Map(files.map((file) => [file.id, file]));
135
+ return { files: fileIds.flatMap((fileId) => fileById.get(fileId) ?? []) };
136
+ });
137
+ if ('failure' in outcome) {
138
+ const { failure } = outcome;
139
+ this.logger.warn(`reserve refused for ${label}: ${failure.message}`);
140
+ throw failure;
141
+ }
142
+ this.logger.log(`reserve applied for ${label}: ${String(outcome.files.length)} file(s)`);
143
+ return outcome.files;
144
+ }
78
145
  async completeScan(input) {
79
146
  return this.finishScan({
80
147
  assignments: `scan_status = $1, public_key = $2, scanned_at = now()`,
@@ -1 +1 @@
1
- {"version":3,"file":"postgres-file.repository.js","sourceRoot":"","sources":["../../src/repositories/postgres-file.repository.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"postgres-file.repository.js","sourceRoot":"","sources":["../../src/repositories/postgres-file.repository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attachment-exceptions.unit.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-exceptions.unit.spec.d.ts","sourceRoot":"","sources":["../../src/test/attachment-exceptions.unit.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,26 @@
1
+ import { describe, expect, it } from '@jest/globals';
2
+ import { AttachmentRefusalReason, EntityType, FileAttachmentRefusedException, TooManyFilesException, } from '../index.js';
3
+ describe('Attachment exceptions', () => {
4
+ it('FileAttachmentRefusedException should be a 422 carrying its reason', () => {
5
+ const error = new FileAttachmentRefusedException('file-1', AttachmentRefusalReason.FILE_RELEASED, EntityType.POST, 'post-1');
6
+ expect(error.statusCode).toBe(422);
7
+ expect(error.code).toBe('FILE_ATTACHMENT_REFUSED');
8
+ expect(error.details).toEqual({
9
+ fileId: 'file-1',
10
+ reason: AttachmentRefusalReason.FILE_RELEASED,
11
+ entityType: EntityType.POST,
12
+ entityId: 'post-1',
13
+ });
14
+ });
15
+ it('TooManyFilesException should be a 400 carrying the limit', () => {
16
+ const error = new TooManyFilesException(EntityType.EVENT_COVER, 2, 1);
17
+ expect(error.statusCode).toBe(400);
18
+ expect(error.code).toBe('TOO_MANY_FILES');
19
+ expect(error.details).toEqual({
20
+ entityType: EntityType.EVENT_COVER,
21
+ count: 2,
22
+ maxPerEntity: 1,
23
+ });
24
+ });
25
+ });
26
+ //# sourceMappingURL=attachment-exceptions.unit.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-exceptions.unit.spec.js","sourceRoot":"","sources":["../../src/test/attachment-exceptions.unit.spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACrD,OAAO,EACL,uBAAuB,EACvB,UAAU,EACV,8BAA8B,EAC9B,qBAAqB,GACtB,MAAM,aAAa,CAAC;AAErB,QAAQ,CAAC,uBAAuB,EAAE,GAAG,EAAE;IACrC,EAAE,CAAC,oEAAoE,EAAE,GAAG,EAAE;QAC5E,MAAM,KAAK,GAAG,IAAI,8BAA8B,CAC9C,QAAQ,EACR,uBAAuB,CAAC,aAAa,EACrC,UAAU,CAAC,IAAI,EACf,QAAQ,CACT,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACnD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YAC5B,MAAM,EAAE,QAAQ;YAChB,MAAM,EAAE,uBAAuB,CAAC,aAAa;YAC7C,UAAU,EAAE,UAAU,CAAC,IAAI;YAC3B,QAAQ,EAAE,QAAQ;SACnB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,KAAK,GAAG,IAAI,qBAAqB,CAAC,UAAU,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAEtE,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QAC1C,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC;YAC5B,UAAU,EAAE,UAAU,CAAC,WAAW;YAClC,KAAK,EAAE,CAAC;YACR,YAAY,EAAE,CAAC;SAChB,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=attachment-validation.rule.unit.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-validation.rule.unit.spec.d.ts","sourceRoot":"","sources":["../../src/test/attachment-validation.rule.unit.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,83 @@
1
+ import { describe, expect, it } from '@jest/globals';
2
+ import { AttachmentRefusalReason, EntityType, FileStatus, InvalidEntityTypeException, ScanStatus, classifyFileForAttachment, } from '../index.js';
3
+ import { buildAttachmentCandidate, buildAttachmentTarget } from './factories/attachment.factory.js';
4
+ const refused = (reason) => ({ kind: 'REFUSED', reason });
5
+ describe('classifyFileForAttachment', () => {
6
+ it('should answer NOT_FOUND for an unknown file', () => {
7
+ expect(classifyFileForAttachment(null, buildAttachmentTarget())).toEqual({
8
+ kind: 'NOT_FOUND',
9
+ });
10
+ });
11
+ it('should answer NOT_FOUND for a file of another owner, whatever its state', () => {
12
+ const target = buildAttachmentTarget();
13
+ const other = buildAttachmentCandidate(target, {
14
+ ownerId: buildAttachmentTarget().ownerId,
15
+ entityType: EntityType.USER_AVATAR,
16
+ scanStatus: ScanStatus.REJECTED,
17
+ });
18
+ expect(classifyFileForAttachment(other, target)).toEqual({ kind: 'NOT_FOUND' });
19
+ });
20
+ it('should refuse a file declared for another entity type', () => {
21
+ const target = buildAttachmentTarget({ entityType: EntityType.POST });
22
+ const file = buildAttachmentCandidate(target, { entityType: EntityType.EVENT_COVER });
23
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.ENTITY_TYPE_MISMATCH));
24
+ });
25
+ it.each([ScanStatus.AWAITING_UPLOAD, ScanStatus.REJECTED])('should refuse a %s file', (scanStatus) => {
26
+ const target = buildAttachmentTarget();
27
+ const file = buildAttachmentCandidate(target, { scanStatus });
28
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.SCAN_STATUS_NOT_ACCEPTED));
29
+ });
30
+ it.each([EntityType.POST, EntityType.EVENT_COVER])('should reserve a SCANNING file for %s, which allows ASYNC', (entityType) => {
31
+ const target = buildAttachmentTarget({ entityType });
32
+ const file = buildAttachmentCandidate(target, { scanStatus: ScanStatus.SCANNING });
33
+ expect(classifyFileForAttachment(file, target)).toEqual({ kind: 'RESERVE' });
34
+ });
35
+ it.each([EntityType.USER_AVATAR, EntityType.BADGE_ICON])('should refuse a SCANNING file for %s, which does not allow ASYNC', (entityType) => {
36
+ const target = buildAttachmentTarget({ entityType });
37
+ const file = buildAttachmentCandidate(target, { scanStatus: ScanStatus.SCANNING });
38
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.SCAN_STATUS_NOT_ACCEPTED));
39
+ });
40
+ it.each(Object.values(EntityType))('should reserve a PENDING CLEAN file for %s', (entityType) => {
41
+ const target = buildAttachmentTarget({ entityType });
42
+ expect(classifyFileForAttachment(buildAttachmentCandidate(target), target)).toEqual({
43
+ kind: 'RESERVE',
44
+ });
45
+ });
46
+ it.each([FileStatus.RESERVED, FileStatus.ATTACHED])('should recognize a %s file of the same entity as already held', (status) => {
47
+ const target = buildAttachmentTarget();
48
+ const file = buildAttachmentCandidate(target, {
49
+ status,
50
+ entityId: target.entityId.toUpperCase(),
51
+ });
52
+ expect(classifyFileForAttachment(file, target)).toEqual({ kind: 'ALREADY_HELD' });
53
+ });
54
+ it.each([FileStatus.RESERVED, FileStatus.ATTACHED])('should refuse a %s file held by another entity', (status) => {
55
+ const target = buildAttachmentTarget();
56
+ const file = buildAttachmentCandidate(target, {
57
+ status,
58
+ entityId: buildAttachmentTarget().entityId,
59
+ });
60
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.ATTACHED_TO_ANOTHER_ENTITY));
61
+ });
62
+ it.each([FileStatus.ORPHANED, FileStatus.DELETED])('should refuse a %s file, even for its former entity', (status) => {
63
+ const target = buildAttachmentTarget();
64
+ const file = buildAttachmentCandidate(target, { status, entityId: target.entityId });
65
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.FILE_RELEASED));
66
+ });
67
+ it('should check the scan status before the attachment status', () => {
68
+ const target = buildAttachmentTarget();
69
+ const file = buildAttachmentCandidate(target, {
70
+ status: FileStatus.ATTACHED,
71
+ entityId: target.entityId,
72
+ scanStatus: ScanStatus.REJECTED,
73
+ });
74
+ expect(classifyFileForAttachment(file, target)).toEqual(refused(AttachmentRefusalReason.SCAN_STATUS_NOT_ACCEPTED));
75
+ });
76
+ it('should raise InvalidEntityTypeException for an unknown entity type', () => {
77
+ const target = buildAttachmentTarget();
78
+ const file = buildAttachmentCandidate(target);
79
+ const unknown = buildAttachmentTarget({ ownerId: target.ownerId, entityType: 'NOPE' });
80
+ expect(() => classifyFileForAttachment({ ...file, entityType: unknown.entityType }, unknown)).toThrow(InvalidEntityTypeException);
81
+ });
82
+ });
83
+ //# sourceMappingURL=attachment-validation.rule.unit.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-validation.rule.unit.spec.js","sourceRoot":"","sources":["../../src/test/attachment-validation.rule.unit.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { AttachmentCandidate, AttachmentTarget } from '../../policies/attachment-validation.rule.js';
2
+ export declare const buildAttachmentTarget: (overrides?: Partial<AttachmentTarget>) => AttachmentTarget;
3
+ export declare const buildAttachmentCandidate: (target: AttachmentTarget, overrides?: Partial<AttachmentCandidate>) => AttachmentCandidate;
4
+ //# sourceMappingURL=attachment.factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.factory.d.ts","sourceRoot":"","sources":["../../../src/test/factories/attachment.factory.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,mBAAmB,EACnB,gBAAgB,EACjB,MAAM,8CAA8C,CAAC;AAGtD,eAAO,MAAM,qBAAqB,eACrB,OAAO,CAAC,gBAAgB,CAAC,KACnC,gBAKD,CAAC;AAGH,eAAO,MAAM,wBAAwB,WAC3B,gBAAgB,cACb,OAAO,CAAC,mBAAmB,CAAC,KACtC,mBAOD,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { EntityType } from '../../enums/entity-type.enum.js';
2
+ import { FileStatus } from '../../enums/file-status.enum.js';
3
+ import { ScanStatus } from '../../enums/scan-status.enum.js';
4
+ import { FileId } from '../../value-objects/file-id.vo.js';
5
+ export const buildAttachmentTarget = (overrides = {}) => ({
6
+ ownerId: FileId.generate().getValue(),
7
+ entityType: EntityType.POST,
8
+ entityId: FileId.generate().getValue(),
9
+ ...overrides,
10
+ });
11
+ export const buildAttachmentCandidate = (target, overrides = {}) => ({
12
+ ownerId: target.ownerId,
13
+ entityType: target.entityType,
14
+ entityId: null,
15
+ status: FileStatus.PENDING,
16
+ scanStatus: ScanStatus.CLEAN,
17
+ ...overrides,
18
+ });
19
+ //# sourceMappingURL=attachment.factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment.factory.js","sourceRoot":"","sources":["../../../src/test/factories/attachment.factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAK7D,OAAO,EAAE,MAAM,EAAE,MAAM,mCAAmC,CAAC;AAE3D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CACnC,YAAuC,EAAE,EACvB,EAAE,CAAC,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACrC,UAAU,EAAE,UAAU,CAAC,IAAI;IAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE;IACtC,GAAG,SAAS;CACb,CAAC,CAAC;AAGH,MAAM,CAAC,MAAM,wBAAwB,GAAG,CACtC,MAAwB,EACxB,YAA0C,EAAE,EACvB,EAAE,CAAC,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,OAAO;IACvB,UAAU,EAAE,MAAM,CAAC,UAAU;IAC7B,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,UAAU,CAAC,OAAO;IAC1B,UAAU,EAAE,UAAU,CAAC,KAAK;IAC5B,GAAG,SAAS;CACb,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=postgres-file.repository.reserve.int.spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-file.repository.reserve.int.spec.d.ts","sourceRoot":"","sources":["../../../src/test/integration/postgres-file.repository.reserve.int.spec.ts"],"names":[],"mappings":""}
@@ -0,0 +1,205 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, jest, } from '@jest/globals';
2
+ import { AttachmentRefusalReason, EntityType, FileAttachmentRefusedException, FileId, FileNotFoundException, FileStatus, ScanStatus, TooManyFilesException, } from '../../index.js';
3
+ import { PostgresFileRepository } from '../../repositories/index.js';
4
+ import { closeTestDb, initializeTestDb, testDataSource, truncateAll } from '../data-source.js';
5
+ import { insertFile, readEvents, readFile, readJobs } from '../helpers/file-db.helper.js';
6
+ import { mockFileUpdateFailure } from '../mocks/file-update-failure.mock.js';
7
+ const newId = () => FileId.generate().getValue();
8
+ describe('PostgresFileRepository.reserve() (integration)', () => {
9
+ let repository;
10
+ let restoreUpdates;
11
+ const ownerId = newId();
12
+ const entityId = newId();
13
+ const reserveInput = (fileIds, overrides = {}) => ({
14
+ fileIds,
15
+ entityType: EntityType.POST,
16
+ entityId,
17
+ ownerId,
18
+ ...overrides,
19
+ });
20
+ const cleanFile = async (overrides = {}) => insertFile({ ownerId, scanStatus: ScanStatus.CLEAN, ...overrides });
21
+ beforeAll(async () => {
22
+ await initializeTestDb();
23
+ repository = new PostgresFileRepository(testDataSource);
24
+ });
25
+ afterAll(async () => {
26
+ await closeTestDb();
27
+ });
28
+ beforeEach(async () => {
29
+ await truncateAll();
30
+ });
31
+ afterEach(async () => {
32
+ jest.restoreAllMocks();
33
+ await restoreUpdates?.();
34
+ restoreUpdates = undefined;
35
+ });
36
+ it('reserves CLEAN and SCANNING files of a post, in input order, and writes no event', async () => {
37
+ const clean = await cleanFile();
38
+ const scanning = await cleanFile({ scanStatus: ScanStatus.SCANNING });
39
+ const reserved = await repository.reserve(reserveInput([scanning.id, clean.id]));
40
+ expect(reserved.map((file) => file.id)).toEqual([scanning.id, clean.id]);
41
+ for (const file of reserved) {
42
+ expect(file.status).toBe(FileStatus.RESERVED);
43
+ expect(file.entityId).toBe(entityId);
44
+ expect(file.reservedAt).toBeInstanceOf(Date);
45
+ }
46
+ expect(reserved[0]?.scanStatus).toBe(ScanStatus.SCANNING);
47
+ expect((await readFile(clean.id)).status).toBe(FileStatus.RESERVED);
48
+ expect(await readEvents()).toHaveLength(0);
49
+ expect(await readJobs()).toHaveLength(0);
50
+ });
51
+ it('ignores duplicated ids', async () => {
52
+ const file = await cleanFile();
53
+ const reserved = await repository.reserve(reserveInput([file.id, file.id, file.id]));
54
+ expect(reserved).toHaveLength(1);
55
+ });
56
+ it('does nothing and queries nothing for an empty list', async () => {
57
+ await expect(repository.reserve(reserveInput([]))).resolves.toEqual([]);
58
+ });
59
+ it('refuses more distinct files than the policy allows, before touching anything', async () => {
60
+ const files = [await cleanFile(), await cleanFile()];
61
+ await expect(repository.reserve(reserveInput(files.map((file) => file.id), { entityType: EntityType.EVENT_COVER }))).rejects.toThrow(TooManyFilesException);
62
+ expect((await readFile(files[0]?.id ?? '')).status).toBe(FileStatus.PENDING);
63
+ });
64
+ it('accepts exactly the maximum of the policy', async () => {
65
+ const files = await Promise.all(Array.from({ length: 10 }, () => cleanFile()));
66
+ const reserved = await repository.reserve(reserveInput(files.map((file) => file.id)));
67
+ expect(reserved).toHaveLength(10);
68
+ });
69
+ it('replaces an avatar: a new file can be reserved while the old one is still ATTACHED', async () => {
70
+ const old = await cleanFile({
71
+ entityType: EntityType.USER_AVATAR,
72
+ status: FileStatus.ATTACHED,
73
+ entityId,
74
+ });
75
+ const next = await cleanFile({ entityType: EntityType.USER_AVATAR });
76
+ const reserved = await repository.reserve(reserveInput([next.id], { entityType: EntityType.USER_AVATAR }));
77
+ expect(reserved.map((file) => file.status)).toEqual([FileStatus.RESERVED]);
78
+ expect((await readFile(old.id)).status).toBe(FileStatus.ATTACHED);
79
+ });
80
+ it('answers NOT_FOUND for an unknown file', async () => {
81
+ await expect(repository.reserve(reserveInput([newId()]))).rejects.toThrow(FileNotFoundException);
82
+ });
83
+ it('answers NOT_FOUND for the file of another owner and does not touch it', async () => {
84
+ const foreign = await insertFile({ ownerId: newId(), scanStatus: ScanStatus.CLEAN });
85
+ await expect(repository.reserve(reserveInput([foreign.id]))).rejects.toThrow(FileNotFoundException);
86
+ expect((await readFile(foreign.id)).status).toBe(FileStatus.PENDING);
87
+ });
88
+ it('refuses a file declared for another entity type', async () => {
89
+ const file = await cleanFile({ entityType: EntityType.EVENT_COVER });
90
+ const error = await repository.reserve(reserveInput([file.id])).catch((e) => e);
91
+ expect(error).toBeInstanceOf(FileAttachmentRefusedException);
92
+ expect(error.details?.reason).toBe(AttachmentRefusalReason.ENTITY_TYPE_MISMATCH);
93
+ });
94
+ it.each([ScanStatus.AWAITING_UPLOAD, ScanStatus.REJECTED])('refuses a %s file', async (scanStatus) => {
95
+ const file = await cleanFile({ scanStatus });
96
+ await expect(repository.reserve(reserveInput([file.id]))).rejects.toThrow(FileAttachmentRefusedException);
97
+ expect((await readFile(file.id)).status).toBe(FileStatus.PENDING);
98
+ });
99
+ it('refuses a SCANNING avatar, which must be CLEAN', async () => {
100
+ const file = await cleanFile({
101
+ entityType: EntityType.USER_AVATAR,
102
+ scanStatus: ScanStatus.SCANNING,
103
+ });
104
+ await expect(repository.reserve(reserveInput([file.id], { entityType: EntityType.USER_AVATAR }))).rejects.toThrow(FileAttachmentRefusedException);
105
+ });
106
+ it('refuses a file already reserved or attached for another entity', async () => {
107
+ const reservedElsewhere = await cleanFile({
108
+ status: FileStatus.RESERVED,
109
+ entityId: newId(),
110
+ });
111
+ const attachedElsewhere = await cleanFile({
112
+ status: FileStatus.ATTACHED,
113
+ entityId: newId(),
114
+ });
115
+ for (const file of [reservedElsewhere, attachedElsewhere]) {
116
+ const error = await repository.reserve(reserveInput([file.id])).catch((e) => e);
117
+ expect(error.details?.reason).toBe(AttachmentRefusalReason.ATTACHED_TO_ANOTHER_ENTITY);
118
+ expect((await readFile(file.id)).entityId).not.toBe(entityId);
119
+ }
120
+ });
121
+ it.each([FileStatus.ORPHANED, FileStatus.DELETED])('never brings a %s file back, even for its former entity', async (status) => {
122
+ const file = await cleanFile({ status, entityId });
123
+ const error = await repository.reserve(reserveInput([file.id])).catch((e) => e);
124
+ expect(error.details?.reason).toBe(AttachmentRefusalReason.FILE_RELEASED);
125
+ expect((await readFile(file.id)).status).toBe(status);
126
+ });
127
+ it('is idempotent for the same entity: no second write, same files returned', async () => {
128
+ const file = await cleanFile();
129
+ const first = await repository.reserve(reserveInput([file.id]));
130
+ const reservedAt = first[0]?.reservedAt;
131
+ const replay = await repository.reserve(reserveInput([file.id]));
132
+ expect(replay[0]?.status).toBe(FileStatus.RESERVED);
133
+ expect(replay[0]?.reservedAt).toEqual(reservedAt);
134
+ expect(replay[0]?.updatedAt).toEqual(first[0]?.updatedAt);
135
+ });
136
+ it('recognizes an ATTACHED file of the same entity without writing', async () => {
137
+ const file = await cleanFile({ status: FileStatus.ATTACHED, entityId });
138
+ const before = await readFile(file.id);
139
+ const reserved = await repository.reserve(reserveInput([file.id]));
140
+ expect(reserved[0]?.status).toBe(FileStatus.ATTACHED);
141
+ expect((await readFile(file.id)).updatedAt).toEqual(before.updatedAt);
142
+ });
143
+ it('mixes new and already held files of the same entity', async () => {
144
+ const held = await cleanFile({ status: FileStatus.RESERVED, entityId });
145
+ const fresh = await cleanFile();
146
+ const reserved = await repository.reserve(reserveInput([held.id, fresh.id]));
147
+ expect(reserved.map((file) => file.status)).toEqual([FileStatus.RESERVED, FileStatus.RESERVED]);
148
+ });
149
+ it('is all or nothing: one refused file leaves the valid ones untouched', async () => {
150
+ const valid = await cleanFile();
151
+ const rejected = await cleanFile({ scanStatus: ScanStatus.REJECTED });
152
+ await expect(repository.reserve(reserveInput([valid.id, rejected.id]))).rejects.toThrow(FileAttachmentRefusedException);
153
+ const row = await readFile(valid.id);
154
+ expect(row.status).toBe(FileStatus.PENDING);
155
+ expect(row.entityId).toBeNull();
156
+ expect(row.reservedAt).toBeNull();
157
+ });
158
+ it('answers NOT_FOUND rather than a refusal when both occur', async () => {
159
+ const rejected = await cleanFile({ scanStatus: ScanStatus.REJECTED });
160
+ await expect(repository.reserve(reserveInput([rejected.id, newId()]))).rejects.toThrow(FileNotFoundException);
161
+ });
162
+ it('rolls the whole UPDATE back when one row cannot be written', async () => {
163
+ const first = await cleanFile();
164
+ const second = await cleanFile();
165
+ restoreUpdates = await mockFileUpdateFailure(second.id);
166
+ await expect(repository.reserve(reserveInput([first.id, second.id]))).rejects.toThrow('simulated file update failure');
167
+ expect((await readFile(first.id)).status).toBe(FileStatus.PENDING);
168
+ expect((await readFile(second.id)).status).toBe(FileStatus.PENDING);
169
+ });
170
+ it('lets exactly one of two concurrent reservations of a file for different entities win', async () => {
171
+ const file = await cleanFile();
172
+ const otherEntityId = newId();
173
+ const results = await Promise.allSettled([
174
+ repository.reserve(reserveInput([file.id])),
175
+ repository.reserve({ ...reserveInput([file.id]), entityId: otherEntityId }),
176
+ ]);
177
+ expect(results.filter((result) => result.status === 'fulfilled')).toHaveLength(1);
178
+ const rejected = results.find((result) => result.status === 'rejected');
179
+ expect(rejected?.reason).toBeInstanceOf(FileAttachmentRefusedException);
180
+ const row = await readFile(file.id);
181
+ expect(row.status).toBe(FileStatus.RESERVED);
182
+ expect([entityId, otherEntityId]).toContain(row.entityId);
183
+ });
184
+ it('survives concurrent reservations of overlapping files in opposite order (no deadlock)', async () => {
185
+ const a = await cleanFile();
186
+ const b = await cleanFile();
187
+ const results = await Promise.all([
188
+ repository.reserve(reserveInput([a.id, b.id])),
189
+ repository.reserve(reserveInput([b.id, a.id])),
190
+ ]);
191
+ expect(results.map((files) => files.length)).toEqual([2, 2]);
192
+ });
193
+ it('commutes with the end of the scan: a file reserved while SCANNING is CLEAN afterwards and still RESERVED', async () => {
194
+ const file = await cleanFile({ scanStatus: ScanStatus.SCANNING });
195
+ await repository.reserve(reserveInput([file.id]));
196
+ const completed = await repository.completeScan({ fileId: file.id, publicKey: 'public/x' });
197
+ expect(completed).toEqual({
198
+ fileId: file.id,
199
+ status: FileStatus.RESERVED,
200
+ eventEmitted: false,
201
+ });
202
+ expect((await readFile(file.id)).status).toBe(FileStatus.RESERVED);
203
+ });
204
+ });
205
+ //# sourceMappingURL=postgres-file.repository.reserve.int.spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-file.repository.reserve.int.spec.js","sourceRoot":"","sources":["../../../src/test/integration/postgres-file.repository.reserve.int.spec.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const mockFileUpdateFailure: (fileId: string) => Promise<() => Promise<void>>;
2
+ //# sourceMappingURL=file-update-failure.mock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-update-failure.mock.d.ts","sourceRoot":"","sources":["../../../src/test/mocks/file-update-failure.mock.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,qBAAqB,WAAkB,MAAM,KAAG,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAmBvF,CAAC"}
@@ -0,0 +1,17 @@
1
+ import { testDataSource } from '../data-source.js';
2
+ export const mockFileUpdateFailure = async (fileId) => {
3
+ await testDataSource.query(`CREATE OR REPLACE FUNCTION fail_file_update() RETURNS trigger AS $$
4
+ BEGIN
5
+ IF NEW.id = '${fileId}'::uuid THEN RAISE EXCEPTION 'simulated file update failure'; END IF;
6
+ RETURN NEW;
7
+ END;
8
+ $$ LANGUAGE plpgsql`);
9
+ await testDataSource.query(`DROP TRIGGER IF EXISTS fail_file_update ON files`);
10
+ await testDataSource.query(`CREATE TRIGGER fail_file_update BEFORE UPDATE ON files
11
+ FOR EACH ROW EXECUTE FUNCTION fail_file_update()`);
12
+ return async () => {
13
+ await testDataSource.query(`DROP TRIGGER IF EXISTS fail_file_update ON files`);
14
+ await testDataSource.query(`DROP FUNCTION IF EXISTS fail_file_update()`);
15
+ };
16
+ };
17
+ //# sourceMappingURL=file-update-failure.mock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-update-failure.mock.js","sourceRoot":"","sources":["../../../src/test/mocks/file-update-failure.mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAMnD,MAAM,CAAC,MAAM,qBAAqB,GAAG,KAAK,EAAE,MAAc,EAAgC,EAAE;IAC1F,MAAM,cAAc,CAAC,KAAK,CACxB;;sBAEkB,MAAM;;;yBAGH,CACtB,CAAC;IACF,MAAM,cAAc,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;IAC/E,MAAM,cAAc,CAAC,KAAK,CACxB;sDACkD,CACnD,CAAC;IAEF,OAAO,KAAK,IAAI,EAAE;QAChB,MAAM,cAAc,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QAC/E,MAAM,cAAc,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;IAC3E,CAAC,CAAC;AACJ,CAAC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@volontariapp/domain-storage",
3
- "version": "0.7.0",
3
+ "version": "0.8.0-snap-cde7a1d",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "provenance": true