@orthacms/content-server 0.4.2 → 0.4.3

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 (135) hide show
  1. package/dist/index.d.ts +15 -0
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +38 -1
  4. package/dist/lib/content.module.d.ts.map +1 -1
  5. package/dist/lib/content.module.js +23 -1
  6. package/dist/lib/entries/http/controllers/create-entry.controller.d.ts.map +1 -1
  7. package/dist/lib/entries/http/controllers/create-entry.controller.js +1 -1
  8. package/dist/lib/entries/http/controllers/update-entry.controller.d.ts.map +1 -1
  9. package/dist/lib/entries/http/controllers/update-entry.controller.js +1 -1
  10. package/dist/lib/entries/http/dto/extension-bag.validator.d.ts +14 -0
  11. package/dist/lib/entries/http/dto/extension-bag.validator.d.ts.map +1 -0
  12. package/dist/lib/entries/http/dto/extension-bag.validator.js +42 -0
  13. package/dist/lib/entries/http/dto/save-entry.dto.d.ts +16 -0
  14. package/dist/lib/entries/http/dto/save-entry.dto.d.ts.map +1 -1
  15. package/dist/lib/entries/http/dto/save-entry.dto.js +30 -0
  16. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts +28 -2
  17. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.d.ts.map +1 -1
  18. package/dist/lib/entries/infrastructure/persistence/entry-writer.service.js +112 -15
  19. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts +38 -5
  20. package/dist/lib/entries/infrastructure/persistence/relation-link.service.d.ts.map +1 -1
  21. package/dist/lib/entries/infrastructure/persistence/relation-link.service.js +38 -6
  22. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts +3 -1
  23. package/dist/lib/entries/infrastructure/queries/entries.service.d.ts.map +1 -1
  24. package/dist/lib/entries/infrastructure/queries/entries.service.js +17 -5
  25. package/dist/lib/entries/infrastructure/queries/entry-match.query.d.ts +82 -0
  26. package/dist/lib/entries/infrastructure/queries/entry-match.query.d.ts.map +1 -0
  27. package/dist/lib/entries/infrastructure/queries/entry-match.query.js +152 -0
  28. package/dist/lib/extension/entry-access-source.d.ts +112 -0
  29. package/dist/lib/extension/entry-access-source.d.ts.map +1 -0
  30. package/dist/lib/extension/entry-filter-provider.d.ts +79 -0
  31. package/dist/lib/extension/entry-filter-provider.d.ts.map +1 -0
  32. package/dist/lib/extension/entry-filter-provider.js +149 -0
  33. package/dist/lib/extension/entry-write-extension.d.ts +185 -0
  34. package/dist/lib/extension/entry-write-extension.d.ts.map +1 -0
  35. package/dist/lib/extension/entry-write-extension.js +182 -0
  36. package/dist/lib/extension/entry-write-hook.d.ts +98 -0
  37. package/dist/lib/extension/entry-write-hook.d.ts.map +1 -0
  38. package/dist/lib/extension/read-scope.d.ts +107 -0
  39. package/dist/lib/extension/read-scope.d.ts.map +1 -0
  40. package/dist/lib/extension/read-scope.js +131 -0
  41. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts +14 -1
  42. package/dist/lib/public-api/infrastructure/public-entries.query.d.ts.map +1 -1
  43. package/dist/lib/public-api/infrastructure/public-entries.query.js +20 -3
  44. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts +16 -4
  45. package/dist/lib/public-api/infrastructure/public-expansion.query.d.ts.map +1 -1
  46. package/dist/lib/public-api/infrastructure/public-expansion.query.js +29 -9
  47. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.d.ts.map +1 -1
  48. package/dist/lib/revisions/application/use-cases/restore-revision.use-case.js +12 -1
  49. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts +7 -1
  50. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.d.ts.map +1 -1
  51. package/dist/lib/revisions/infrastructure/persistence/revision-snapshot.js +9 -2
  52. package/dist/lib/revisions/types/revision-view.d.ts +11 -0
  53. package/dist/lib/revisions/types/revision-view.d.ts.map +1 -1
  54. package/dist/lib/utils/content-views-plugin.d.ts +28 -0
  55. package/dist/lib/utils/content-views-plugin.d.ts.map +1 -0
  56. package/dist/lib/utils/content-views-plugin.js +29 -0
  57. package/dist/lib/views/application/queries/saved-views.query.d.ts +16 -0
  58. package/dist/lib/views/application/queries/saved-views.query.d.ts.map +1 -0
  59. package/dist/lib/views/application/queries/saved-views.query.js +46 -0
  60. package/dist/lib/views/application/saved-view-access.service.d.ts +30 -0
  61. package/dist/lib/views/application/saved-view-access.service.d.ts.map +1 -0
  62. package/dist/lib/views/application/saved-view-access.service.js +55 -0
  63. package/dist/lib/views/application/use-cases/create-saved-view.use-case.d.ts +27 -0
  64. package/dist/lib/views/application/use-cases/create-saved-view.use-case.d.ts.map +1 -0
  65. package/dist/lib/views/application/use-cases/create-saved-view.use-case.js +57 -0
  66. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.d.ts +15 -0
  67. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.d.ts.map +1 -0
  68. package/dist/lib/views/application/use-cases/delete-saved-view.use-case.js +35 -0
  69. package/dist/lib/views/application/use-cases/set-default-view.use-case.d.ts +23 -0
  70. package/dist/lib/views/application/use-cases/set-default-view.use-case.d.ts.map +1 -0
  71. package/dist/lib/views/application/use-cases/set-default-view.use-case.js +51 -0
  72. package/dist/lib/views/application/use-cases/update-saved-view.use-case.d.ts +21 -0
  73. package/dist/lib/views/application/use-cases/update-saved-view.use-case.d.ts.map +1 -0
  74. package/dist/lib/views/application/use-cases/update-saved-view.use-case.js +61 -0
  75. package/dist/lib/views/application/view-scope.service.d.ts +25 -0
  76. package/dist/lib/views/application/view-scope.service.d.ts.map +1 -0
  77. package/dist/lib/views/application/view-scope.service.js +45 -0
  78. package/dist/lib/views/content-views.module.d.ts +22 -0
  79. package/dist/lib/views/content-views.module.d.ts.map +1 -0
  80. package/dist/lib/views/content-views.module.js +63 -0
  81. package/dist/lib/views/domain/errors/index.d.ts +6 -0
  82. package/dist/lib/views/domain/errors/index.d.ts.map +1 -0
  83. package/dist/lib/views/domain/errors/index.js +12 -0
  84. package/dist/lib/views/domain/errors/saved-view-forbidden.error.d.ts +10 -0
  85. package/dist/lib/views/domain/errors/saved-view-forbidden.error.d.ts.map +1 -0
  86. package/dist/lib/views/domain/errors/saved-view-forbidden.error.js +16 -0
  87. package/dist/lib/views/domain/errors/saved-view-limit-error.d.ts +9 -0
  88. package/dist/lib/views/domain/errors/saved-view-limit-error.d.ts.map +1 -0
  89. package/dist/lib/views/domain/errors/saved-view-limit-error.js +16 -0
  90. package/dist/lib/views/domain/errors/saved-view-name-taken.error.d.ts +5 -0
  91. package/dist/lib/views/domain/errors/saved-view-name-taken.error.d.ts.map +1 -0
  92. package/dist/lib/views/domain/errors/saved-view-name-taken.error.js +11 -0
  93. package/dist/lib/views/domain/errors/saved-view-not-found.error.d.ts +9 -0
  94. package/dist/lib/views/domain/errors/saved-view-not-found.error.d.ts.map +1 -0
  95. package/dist/lib/views/domain/errors/saved-view-not-found.error.js +15 -0
  96. package/dist/lib/views/domain/saved-view.d.ts +66 -0
  97. package/dist/lib/views/domain/saved-view.d.ts.map +1 -0
  98. package/dist/lib/views/domain/saved-view.js +18 -0
  99. package/dist/lib/views/domain/saved-view.repository.d.ts +77 -0
  100. package/dist/lib/views/domain/saved-view.repository.d.ts.map +1 -0
  101. package/dist/lib/views/domain/saved-view.repository.js +5 -0
  102. package/dist/lib/views/http/controllers/saved-views.controller.d.ts +45 -0
  103. package/dist/lib/views/http/controllers/saved-views.controller.d.ts.map +1 -0
  104. package/dist/lib/views/http/controllers/saved-views.controller.js +216 -0
  105. package/dist/lib/views/http/controllers/to-http-error.d.ts +10 -0
  106. package/dist/lib/views/http/controllers/to-http-error.d.ts.map +1 -0
  107. package/dist/lib/views/http/controllers/to-http-error.js +26 -0
  108. package/dist/lib/views/http/dto/save-view.dto.d.ts +54 -0
  109. package/dist/lib/views/http/dto/save-view.dto.d.ts.map +1 -0
  110. package/dist/lib/views/http/dto/save-view.dto.js +230 -0
  111. package/dist/lib/views/http/dto/view-payload.validator.d.ts +20 -0
  112. package/dist/lib/views/http/dto/view-payload.validator.d.ts.map +1 -0
  113. package/dist/lib/views/http/dto/view-payload.validator.js +52 -0
  114. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.d.ts +17 -0
  115. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.d.ts.map +1 -0
  116. package/dist/lib/views/infrastructure/persistence/drizzle-saved-view.repository.js +125 -0
  117. package/dist/lib/views/infrastructure/schema/external-refs.d.ts +68 -0
  118. package/dist/lib/views/infrastructure/schema/external-refs.d.ts.map +1 -0
  119. package/dist/lib/views/infrastructure/schema/external-refs.js +29 -0
  120. package/dist/lib/views/infrastructure/schema/index.d.ts +8 -0
  121. package/dist/lib/views/infrastructure/schema/index.d.ts.map +1 -0
  122. package/dist/lib/views/infrastructure/schema/index.js +13 -0
  123. package/dist/lib/views/infrastructure/schema/saved-views.d.ts +275 -0
  124. package/dist/lib/views/infrastructure/schema/saved-views.d.ts.map +1 -0
  125. package/dist/lib/views/infrastructure/schema/saved-views.js +87 -0
  126. package/dist/lib/views/views.constants.d.ts +26 -0
  127. package/dist/lib/views/views.constants.d.ts.map +1 -0
  128. package/dist/lib/views/views.constants.js +28 -0
  129. package/dist/lib/views/views.tokens.d.ts +17 -0
  130. package/dist/lib/views/views.tokens.d.ts.map +1 -0
  131. package/dist/lib/views/views.tokens.js +21 -0
  132. package/migrations/0000_saved_views.sql +29 -0
  133. package/migrations/meta/0000_snapshot.json +256 -0
  134. package/migrations/meta/_journal.json +13 -0
  135. package/package.json +13 -12
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saved-view-access.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/views/application/saved-view-access.service.ts"],"names":[],"mappings":"AACA,OAAO,EACH,YAAY,EAGZ,kBAAkB,EAClB,KAAK,UAAU,EAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAmB,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAC5E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGvE;;;;;;;;;;;;;GAaG;AACH,qBACa,sBAAsB;IAE3B,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBADZ,WAAW,EAAE,kBAAkB,EAC/B,YAAY,EAAE,YAAY;IAG/C,wCAAwC;IACxC,WAAW,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI;IAQ1D;;;OAGG;IACG,sBAAsB,CACxB,UAAU,EAAE,cAAc,EAC1B,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC;CAanB"}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SavedViewAccessService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const identity_server_1 = require("@orthacms/identity-server");
7
+ const saved_view_1 = require("../domain/saved-view");
8
+ const errors_1 = require("../domain/errors");
9
+ /**
10
+ * The two authorization rules saved views add on top of the route guards.
11
+ *
12
+ * The guards already establish that the caller is authenticated, a member of
13
+ * the open workspace, and may read content. What is left is per-row and
14
+ * per-visibility, so it cannot live in a decorator:
15
+ *
16
+ * - **Only the owner writes.** Editing or deleting someone else's view is a
17
+ * 403 even for an administrator — a shared view is its author's, and the
18
+ * remedy for disagreeing with one is "Save as new", not a silent rewrite.
19
+ * - **Sharing is a permission.** Making a view workspace-visible needs
20
+ * `views:share`; a member without it still saves as many private views as
21
+ * they like.
22
+ */
23
+ let SavedViewAccessService = class SavedViewAccessService {
24
+ permissions;
25
+ accessPolicy;
26
+ constructor(permissions, accessPolicy) {
27
+ this.permissions = permissions;
28
+ this.accessPolicy = accessPolicy;
29
+ }
30
+ /** Throws unless `user` owns `view`. */
31
+ assertOwned(view, user) {
32
+ if (view.ownerId !== user.id) {
33
+ throw new errors_1.SavedViewForbiddenError('Only the person who saved a view can change it. Use “Save as new” instead.');
34
+ }
35
+ }
36
+ /**
37
+ * Throws unless `user` may store a view at `visibility`. Private views need
38
+ * nothing beyond membership; workspace-visible ones need `views:share`.
39
+ */
40
+ async assertCanUseVisibility(visibility, user) {
41
+ if (visibility !== saved_view_1.VIEW_VISIBILITY.Workspace)
42
+ return;
43
+ const granted = await this.permissions.forRole(user.roleId);
44
+ const allowed = this.accessPolicy.can({ userId: user.id, grantedPermissions: new Set(granted) }, identity_server_1.Permission.create(identity_server_1.PERMISSIONS.VIEWS_SHARE));
45
+ if (!allowed) {
46
+ throw new errors_1.SavedViewForbiddenError('Sharing a view with the workspace requires the “views:share” permission.');
47
+ }
48
+ }
49
+ };
50
+ exports.SavedViewAccessService = SavedViewAccessService;
51
+ exports.SavedViewAccessService = SavedViewAccessService = tslib_1.__decorate([
52
+ (0, common_1.Injectable)(),
53
+ tslib_1.__metadata("design:paramtypes", [identity_server_1.PermissionsService,
54
+ identity_server_1.AccessPolicy])
55
+ ], SavedViewAccessService);
@@ -0,0 +1,27 @@
1
+ import type { PublicUser } from '@orthacms/identity-server';
2
+ import type { SavedView, SavedViewPayload, ViewVisibility } from '../../domain/saved-view';
3
+ import { type SavedViewRepository } from '../../domain/saved-view.repository';
4
+ import { SavedViewAccessService } from '../saved-view-access.service';
5
+ /** Input for {@link CreateSavedViewUseCase}. */
6
+ export interface CreateSavedViewInput {
7
+ /** The workspace the view belongs to. */
8
+ workspaceId: string;
9
+ /** The list it is over (`content:<typeName>`). */
10
+ scope: string;
11
+ /** Display name, already trimmed by the DTO. */
12
+ name: string;
13
+ /** Who may see it. */
14
+ visibility: ViewVisibility;
15
+ /** The slice it restores. */
16
+ payload: SavedViewPayload;
17
+ /** Whether to make it the caller's default for this scope. */
18
+ makeDefault?: boolean;
19
+ }
20
+ /** Saves a new view for the calling user. */
21
+ export declare class CreateSavedViewUseCase {
22
+ private readonly repository;
23
+ private readonly access;
24
+ constructor(repository: SavedViewRepository, access: SavedViewAccessService);
25
+ execute(input: CreateSavedViewInput, user: PublicUser): Promise<SavedView>;
26
+ }
27
+ //# sourceMappingURL=create-saved-view.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-saved-view.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/application/use-cases/create-saved-view.use-case.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,KAAK,EACR,SAAS,EACT,gBAAgB,EAChB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,oCAAoC,CAAC;AAM5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,gDAAgD;AAChD,MAAM,WAAW,oBAAoB;IACjC,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,UAAU,EAAE,cAAc,CAAC;IAC3B,6BAA6B;IAC7B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,8DAA8D;IAC9D,WAAW,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,6CAA6C;AAC7C,qBACa,sBAAsB;IAG3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,UAAU,EAAE,mBAAmB,EAC/B,MAAM,EAAE,sBAAsB;IAG7C,OAAO,CACT,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,SAAS,CAAC;CAwCxB"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CreateSavedViewUseCase = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const utils_server_1 = require("@orthacms/utils-server");
7
+ const saved_view_repository_1 = require("../../domain/saved-view.repository");
8
+ const errors_1 = require("../../domain/errors");
9
+ const views_constants_1 = require("../../views.constants");
10
+ const saved_view_access_service_1 = require("../saved-view-access.service");
11
+ const saved_views_query_1 = require("../queries/saved-views.query");
12
+ /** Saves a new view for the calling user. */
13
+ let CreateSavedViewUseCase = class CreateSavedViewUseCase {
14
+ repository;
15
+ access;
16
+ constructor(repository, access) {
17
+ this.repository = repository;
18
+ this.access = access;
19
+ }
20
+ async execute(input, user) {
21
+ await this.access.assertCanUseVisibility(input.visibility, user);
22
+ const held = await this.repository.countForOwner(input.workspaceId, input.scope, user.id);
23
+ if (held >= views_constants_1.VIEW_MAX_PER_SCOPE)
24
+ throw new errors_1.SavedViewLimitError();
25
+ // The unique index is the arbiter, not the count above: two concurrent
26
+ // saves of the same name both pass a read-then-write check and one of
27
+ // them has to lose at the constraint. Translate that loss into the same
28
+ // 409 a sequential duplicate gets.
29
+ let created;
30
+ try {
31
+ created = await this.repository.create({
32
+ workspaceId: input.workspaceId,
33
+ scope: input.scope,
34
+ ownerId: user.id,
35
+ visibility: input.visibility,
36
+ name: input.name,
37
+ payload: input.payload
38
+ });
39
+ }
40
+ catch (error) {
41
+ if ((0, utils_server_1.isUniqueViolation)(error)) {
42
+ throw new errors_1.SavedViewNameTakenError(input.name);
43
+ }
44
+ throw error;
45
+ }
46
+ if (input.makeDefault) {
47
+ await this.repository.setDefault(user.id, input.scope, created.id);
48
+ }
49
+ return (0, saved_views_query_1.toSavedView)(created, user.id, input.makeDefault ? created.id : null);
50
+ }
51
+ };
52
+ exports.CreateSavedViewUseCase = CreateSavedViewUseCase;
53
+ exports.CreateSavedViewUseCase = CreateSavedViewUseCase = tslib_1.__decorate([
54
+ (0, common_1.Injectable)(),
55
+ tslib_1.__param(0, (0, common_1.Inject)(saved_view_repository_1.SAVED_VIEW_REPOSITORY)),
56
+ tslib_1.__metadata("design:paramtypes", [Object, saved_view_access_service_1.SavedViewAccessService])
57
+ ], CreateSavedViewUseCase);
@@ -0,0 +1,15 @@
1
+ import type { PublicUser } from '@orthacms/identity-server';
2
+ import { type SavedViewRepository } from '../../domain/saved-view.repository';
3
+ import { SavedViewAccessService } from '../saved-view-access.service';
4
+ /**
5
+ * Deletes a view the caller owns. Anyone else's default pointing at it is
6
+ * cascaded away by the FK, so they fall back to the unfiltered list rather than
7
+ * to a dangling id.
8
+ */
9
+ export declare class DeleteSavedViewUseCase {
10
+ private readonly repository;
11
+ private readonly access;
12
+ constructor(repository: SavedViewRepository, access: SavedViewAccessService);
13
+ execute(id: string, workspaceId: string, user: PublicUser): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=delete-saved-view.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"delete-saved-view.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/application/use-cases/delete-saved-view.use-case.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,oCAAoC,CAAC;AAE5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAEtE;;;;GAIG;AACH,qBACa,sBAAsB;IAG3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,UAAU,EAAE,mBAAmB,EAC/B,MAAM,EAAE,sBAAsB;IAG7C,OAAO,CACT,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC;CAQnB"}
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DeleteSavedViewUseCase = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const saved_view_repository_1 = require("../../domain/saved-view.repository");
7
+ const errors_1 = require("../../domain/errors");
8
+ const saved_view_access_service_1 = require("../saved-view-access.service");
9
+ /**
10
+ * Deletes a view the caller owns. Anyone else's default pointing at it is
11
+ * cascaded away by the FK, so they fall back to the unfiltered list rather than
12
+ * to a dangling id.
13
+ */
14
+ let DeleteSavedViewUseCase = class DeleteSavedViewUseCase {
15
+ repository;
16
+ access;
17
+ constructor(repository, access) {
18
+ this.repository = repository;
19
+ this.access = access;
20
+ }
21
+ async execute(id, workspaceId, user) {
22
+ const existing = await this.repository.findById(id);
23
+ if (!existing || existing.workspaceId !== workspaceId) {
24
+ throw new errors_1.SavedViewNotFoundError(id);
25
+ }
26
+ this.access.assertOwned(existing, user);
27
+ await this.repository.delete(id);
28
+ }
29
+ };
30
+ exports.DeleteSavedViewUseCase = DeleteSavedViewUseCase;
31
+ exports.DeleteSavedViewUseCase = DeleteSavedViewUseCase = tslib_1.__decorate([
32
+ (0, common_1.Injectable)(),
33
+ tslib_1.__param(0, (0, common_1.Inject)(saved_view_repository_1.SAVED_VIEW_REPOSITORY)),
34
+ tslib_1.__metadata("design:paramtypes", [Object, saved_view_access_service_1.SavedViewAccessService])
35
+ ], DeleteSavedViewUseCase);
@@ -0,0 +1,23 @@
1
+ import type { PublicUser } from '@orthacms/identity-server';
2
+ import { type SavedViewRepository } from '../../domain/saved-view.repository';
3
+ /**
4
+ * Points a user's default for one list at a view, or clears it.
5
+ *
6
+ * Deliberately **not** owner-gated: a default is the reader's own landing
7
+ * choice, so anyone who can see a shared view may land on it. What is gated is
8
+ * visibility — the view has to be one this caller can actually read, which is
9
+ * what the ownership-or-shared check below establishes.
10
+ */
11
+ export declare class SetDefaultViewUseCase {
12
+ private readonly repository;
13
+ constructor(repository: SavedViewRepository);
14
+ execute(id: string, workspaceId: string, user: PublicUser): Promise<void>;
15
+ /**
16
+ * Clears the caller's default for the scope `id` belongs to. Addressed by
17
+ * view id rather than by scope so the route sits beside its `PUT`
18
+ * counterpart instead of colliding with `DELETE /views/:id`. Idempotent:
19
+ * clearing when the default points elsewhere, or nowhere, still succeeds.
20
+ */
21
+ executeClear(id: string, workspaceId: string, user: PublicUser): Promise<void>;
22
+ }
23
+ //# sourceMappingURL=set-default-view.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-default-view.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/application/use-cases/set-default-view.use-case.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,oCAAoC,CAAC;AAG5C;;;;;;;GAOG;AACH,qBACa,qBAAqB;IAG1B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAAV,UAAU,EAAE,mBAAmB;IAG9C,OAAO,CACT,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC;IAWhB;;;;;OAKG;IACG,YAAY,CACd,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,IAAI,CAAC;CAOnB"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SetDefaultViewUseCase = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const saved_view_1 = require("../../domain/saved-view");
7
+ const saved_view_repository_1 = require("../../domain/saved-view.repository");
8
+ const errors_1 = require("../../domain/errors");
9
+ /**
10
+ * Points a user's default for one list at a view, or clears it.
11
+ *
12
+ * Deliberately **not** owner-gated: a default is the reader's own landing
13
+ * choice, so anyone who can see a shared view may land on it. What is gated is
14
+ * visibility — the view has to be one this caller can actually read, which is
15
+ * what the ownership-or-shared check below establishes.
16
+ */
17
+ let SetDefaultViewUseCase = class SetDefaultViewUseCase {
18
+ repository;
19
+ constructor(repository) {
20
+ this.repository = repository;
21
+ }
22
+ async execute(id, workspaceId, user) {
23
+ const existing = await this.repository.findById(id);
24
+ const readable = existing &&
25
+ existing.workspaceId === workspaceId &&
26
+ (existing.ownerId === user.id ||
27
+ existing.visibility === saved_view_1.VIEW_VISIBILITY.Workspace);
28
+ if (!existing || !readable)
29
+ throw new errors_1.SavedViewNotFoundError(id);
30
+ await this.repository.setDefault(user.id, existing.scope, id);
31
+ }
32
+ /**
33
+ * Clears the caller's default for the scope `id` belongs to. Addressed by
34
+ * view id rather than by scope so the route sits beside its `PUT`
35
+ * counterpart instead of colliding with `DELETE /views/:id`. Idempotent:
36
+ * clearing when the default points elsewhere, or nowhere, still succeeds.
37
+ */
38
+ async executeClear(id, workspaceId, user) {
39
+ const existing = await this.repository.findById(id);
40
+ if (!existing || existing.workspaceId !== workspaceId) {
41
+ throw new errors_1.SavedViewNotFoundError(id);
42
+ }
43
+ await this.repository.clearDefault(user.id, existing.scope);
44
+ }
45
+ };
46
+ exports.SetDefaultViewUseCase = SetDefaultViewUseCase;
47
+ exports.SetDefaultViewUseCase = SetDefaultViewUseCase = tslib_1.__decorate([
48
+ (0, common_1.Injectable)(),
49
+ tslib_1.__param(0, (0, common_1.Inject)(saved_view_repository_1.SAVED_VIEW_REPOSITORY)),
50
+ tslib_1.__metadata("design:paramtypes", [Object])
51
+ ], SetDefaultViewUseCase);
@@ -0,0 +1,21 @@
1
+ import type { PublicUser } from '@orthacms/identity-server';
2
+ import type { SavedView, SavedViewPayload, ViewVisibility } from '../../domain/saved-view';
3
+ import { type SavedViewRepository } from '../../domain/saved-view.repository';
4
+ import { SavedViewAccessService } from '../saved-view-access.service';
5
+ /** The fields `PATCH /api/views/:id` may change. */
6
+ export interface UpdateSavedViewInput {
7
+ /** New display name. */
8
+ name?: string;
9
+ /** New visibility. */
10
+ visibility?: ViewVisibility;
11
+ /** New slice. */
12
+ payload?: SavedViewPayload;
13
+ }
14
+ /** Renames, re-shares, or re-captures an existing view. */
15
+ export declare class UpdateSavedViewUseCase {
16
+ private readonly repository;
17
+ private readonly access;
18
+ constructor(repository: SavedViewRepository, access: SavedViewAccessService);
19
+ execute(id: string, workspaceId: string, input: UpdateSavedViewInput, user: PublicUser): Promise<SavedView>;
20
+ }
21
+ //# sourceMappingURL=update-saved-view.use-case.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"update-saved-view.use-case.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/application/use-cases/update-saved-view.use-case.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAE5D,OAAO,KAAK,EACR,SAAS,EACT,gBAAgB,EAChB,cAAc,EACjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAEH,KAAK,mBAAmB,EAC3B,MAAM,oCAAoC,CAAC;AAK5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAGtE,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACjC,wBAAwB;IACxB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sBAAsB;IACtB,UAAU,CAAC,EAAE,cAAc,CAAC;IAC5B,iBAAiB;IACjB,OAAO,CAAC,EAAE,gBAAgB,CAAC;CAC9B;AAED,2DAA2D;AAC3D,qBACa,sBAAsB;IAG3B,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,UAAU,EAAE,mBAAmB,EAC/B,MAAM,EAAE,sBAAsB;IAG7C,OAAO,CACT,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,oBAAoB,EAC3B,IAAI,EAAE,UAAU,GACjB,OAAO,CAAC,SAAS,CAAC;CA4CxB"}
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UpdateSavedViewUseCase = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const utils_server_1 = require("@orthacms/utils-server");
7
+ const saved_view_repository_1 = require("../../domain/saved-view.repository");
8
+ const errors_1 = require("../../domain/errors");
9
+ const saved_view_access_service_1 = require("../saved-view-access.service");
10
+ const saved_views_query_1 = require("../queries/saved-views.query");
11
+ /** Renames, re-shares, or re-captures an existing view. */
12
+ let UpdateSavedViewUseCase = class UpdateSavedViewUseCase {
13
+ repository;
14
+ access;
15
+ constructor(repository, access) {
16
+ this.repository = repository;
17
+ this.access = access;
18
+ }
19
+ async execute(id, workspaceId, input, user) {
20
+ const existing = await this.repository.findById(id);
21
+ // The workspace check is part of the not-found decision, not a separate
22
+ // 403: an id from another workspace must read exactly like an unknown
23
+ // one, or the endpoint becomes a probe for views elsewhere.
24
+ if (!existing || existing.workspaceId !== workspaceId) {
25
+ throw new errors_1.SavedViewNotFoundError(id);
26
+ }
27
+ this.access.assertOwned(existing, user);
28
+ if (input.visibility !== undefined) {
29
+ await this.access.assertCanUseVisibility(input.visibility, user);
30
+ }
31
+ // Every field is optional, so `{}` is a valid body — and it would reach
32
+ // Drizzle as `.set({})`, which throws rather than updating nothing.
33
+ // Answer the row unchanged instead: a patch that asks for no change has
34
+ // already got what it asked for.
35
+ const changes = input.name !== undefined ||
36
+ input.visibility !== undefined ||
37
+ input.payload !== undefined;
38
+ if (!changes) {
39
+ const currentDefault = await this.repository.findDefaultId(user.id, existing.scope);
40
+ return (0, saved_views_query_1.toSavedView)(existing, user.id, currentDefault);
41
+ }
42
+ let updated;
43
+ try {
44
+ updated = await this.repository.update(id, input);
45
+ }
46
+ catch (error) {
47
+ if ((0, utils_server_1.isUniqueViolation)(error)) {
48
+ throw new errors_1.SavedViewNameTakenError(input.name ?? existing.name);
49
+ }
50
+ throw error;
51
+ }
52
+ const defaultId = await this.repository.findDefaultId(user.id, updated.scope);
53
+ return (0, saved_views_query_1.toSavedView)(updated, user.id, defaultId);
54
+ }
55
+ };
56
+ exports.UpdateSavedViewUseCase = UpdateSavedViewUseCase;
57
+ exports.UpdateSavedViewUseCase = UpdateSavedViewUseCase = tslib_1.__decorate([
58
+ (0, common_1.Injectable)(),
59
+ tslib_1.__param(0, (0, common_1.Inject)(saved_view_repository_1.SAVED_VIEW_REPOSITORY)),
60
+ tslib_1.__metadata("design:paramtypes", [Object, saved_view_access_service_1.SavedViewAccessService])
61
+ ], UpdateSavedViewUseCase);
@@ -0,0 +1,25 @@
1
+ import type { ContentTypeRegistry } from '../../registry/content-type-registry';
2
+ import { WorkspaceGrantsQuery } from '../../content-types/queries/workspace-grants.query';
3
+ /**
4
+ * Resolves a view's `scope` to a content type the open workspace may actually
5
+ * reach.
6
+ *
7
+ * Without this the views endpoint would be a way around
8
+ * {@link ContentGrantGuard}: `scope` names a content type, and an unchecked one
9
+ * lets a caller confirm that `content:salaries` exists in some workspace by
10
+ * saving a view over it. So the answer for an unknown type and for an ungranted
11
+ * one is the **same 404** the entries routes give — grants read before any
12
+ * registry decision, same status, same message.
13
+ */
14
+ export declare class ViewScopeService {
15
+ private readonly registry;
16
+ private readonly grants;
17
+ constructor(registry: ContentTypeRegistry, grants: WorkspaceGrantsQuery);
18
+ /**
19
+ * Throws `NotFoundException` unless `scope` names a content type this
20
+ * workspace was granted. The DTO has already enforced the
21
+ * `content:<typeName>` shape.
22
+ */
23
+ assertReachable(scope: string, workspaceId: string): Promise<void>;
24
+ }
25
+ //# sourceMappingURL=view-scope.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-scope.service.d.ts","sourceRoot":"","sources":["../../../../src/lib/views/application/view-scope.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAChF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oDAAoD,CAAC;AAG1F;;;;;;;;;;GAUG;AACH,qBACa,gBAAgB;IAGrB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,QAAQ,EAAE,mBAAmB,EAC7B,MAAM,EAAE,oBAAoB;IAGjD;;;;OAIG;IACG,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAO3E"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ViewScopeService = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const common_1 = require("@nestjs/common");
6
+ const views_tokens_1 = require("../views.tokens");
7
+ const workspace_grants_query_1 = require("../../content-types/queries/workspace-grants.query");
8
+ const views_constants_1 = require("../views.constants");
9
+ /**
10
+ * Resolves a view's `scope` to a content type the open workspace may actually
11
+ * reach.
12
+ *
13
+ * Without this the views endpoint would be a way around
14
+ * {@link ContentGrantGuard}: `scope` names a content type, and an unchecked one
15
+ * lets a caller confirm that `content:salaries` exists in some workspace by
16
+ * saving a view over it. So the answer for an unknown type and for an ungranted
17
+ * one is the **same 404** the entries routes give — grants read before any
18
+ * registry decision, same status, same message.
19
+ */
20
+ let ViewScopeService = class ViewScopeService {
21
+ registry;
22
+ grants;
23
+ constructor(registry, grants) {
24
+ this.registry = registry;
25
+ this.grants = grants;
26
+ }
27
+ /**
28
+ * Throws `NotFoundException` unless `scope` names a content type this
29
+ * workspace was granted. The DTO has already enforced the
30
+ * `content:<typeName>` shape.
31
+ */
32
+ async assertReachable(scope, workspaceId) {
33
+ const typeName = scope.slice(views_constants_1.CONTENT_SCOPE_PREFIX.length);
34
+ const granted = await this.grants.grantedSlugs(workspaceId);
35
+ if (!granted.has(typeName) || !this.registry.get(typeName)) {
36
+ throw new common_1.NotFoundException(`Unknown content type "${typeName}".`);
37
+ }
38
+ }
39
+ };
40
+ exports.ViewScopeService = ViewScopeService;
41
+ exports.ViewScopeService = ViewScopeService = tslib_1.__decorate([
42
+ (0, common_1.Injectable)(),
43
+ tslib_1.__param(0, (0, views_tokens_1.InjectViewContentRegistry)()),
44
+ tslib_1.__metadata("design:paramtypes", [Function, workspace_grants_query_1.WorkspaceGrantsQuery])
45
+ ], ViewScopeService);
@@ -0,0 +1,22 @@
1
+ import { type DynamicModule } from '@nestjs/common';
2
+ import type { ContentTypeRegistry } from '../registry/content-type-registry';
3
+ /**
4
+ * The saved-views module.
5
+ *
6
+ * A **second** module from this package rather than a branch of
7
+ * `ContentModule`, because it needs its own `ServerPlugin` entry — the contract
8
+ * carries exactly one `migrations` descriptor per plugin, and content's is
9
+ * already spent on the host-owned generated collection tables. Splitting the
10
+ * module keeps that seam honest: the views feature owns fixed tables it ships
11
+ * migrations for, and the content model's tables stay the host's.
12
+ *
13
+ * It provides the registry the plugin factory hands it under its **own** token
14
+ * (`VIEW_CONTENT_REGISTRY`), so `ViewScopeService` can resolve a scope without
15
+ * importing `ContentModule` — which would make the two plugins' load order
16
+ * load-bearing — and without two global modules both claiming
17
+ * `CONTENT_REGISTRY`.
18
+ */
19
+ export declare class ContentViewsModule {
20
+ static forRoot(registry: ContentTypeRegistry): DynamicModule;
21
+ }
22
+ //# sourceMappingURL=content-views.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-views.module.d.ts","sourceRoot":"","sources":["../../../src/lib/views/content-views.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAa7E;;;;;;;;;;;;;;;GAeG;AACH,qBACa,kBAAkB;IAC3B,MAAM,CAAC,OAAO,CAAC,QAAQ,EAAE,mBAAmB,GAAG,aAAa;CAuB/D"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var ContentViewsModule_1;
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ContentViewsModule = void 0;
5
+ const tslib_1 = require("tslib");
6
+ const common_1 = require("@nestjs/common");
7
+ const workspace_grants_query_1 = require("../content-types/queries/workspace-grants.query");
8
+ const views_tokens_1 = require("./views.tokens");
9
+ const saved_view_repository_1 = require("./domain/saved-view.repository");
10
+ const drizzle_saved_view_repository_1 = require("./infrastructure/persistence/drizzle-saved-view.repository");
11
+ const saved_views_query_1 = require("./application/queries/saved-views.query");
12
+ const saved_view_access_service_1 = require("./application/saved-view-access.service");
13
+ const view_scope_service_1 = require("./application/view-scope.service");
14
+ const create_saved_view_use_case_1 = require("./application/use-cases/create-saved-view.use-case");
15
+ const update_saved_view_use_case_1 = require("./application/use-cases/update-saved-view.use-case");
16
+ const delete_saved_view_use_case_1 = require("./application/use-cases/delete-saved-view.use-case");
17
+ const set_default_view_use_case_1 = require("./application/use-cases/set-default-view.use-case");
18
+ const saved_views_controller_1 = require("./http/controllers/saved-views.controller");
19
+ /**
20
+ * The saved-views module.
21
+ *
22
+ * A **second** module from this package rather than a branch of
23
+ * `ContentModule`, because it needs its own `ServerPlugin` entry — the contract
24
+ * carries exactly one `migrations` descriptor per plugin, and content's is
25
+ * already spent on the host-owned generated collection tables. Splitting the
26
+ * module keeps that seam honest: the views feature owns fixed tables it ships
27
+ * migrations for, and the content model's tables stay the host's.
28
+ *
29
+ * It provides the registry the plugin factory hands it under its **own** token
30
+ * (`VIEW_CONTENT_REGISTRY`), so `ViewScopeService` can resolve a scope without
31
+ * importing `ContentModule` — which would make the two plugins' load order
32
+ * load-bearing — and without two global modules both claiming
33
+ * `CONTENT_REGISTRY`.
34
+ */
35
+ let ContentViewsModule = ContentViewsModule_1 = class ContentViewsModule {
36
+ static forRoot(registry) {
37
+ return {
38
+ module: ContentViewsModule_1,
39
+ global: true,
40
+ controllers: [saved_views_controller_1.SavedViewsController],
41
+ providers: [
42
+ { provide: views_tokens_1.VIEW_CONTENT_REGISTRY, useValue: registry },
43
+ {
44
+ provide: saved_view_repository_1.SAVED_VIEW_REPOSITORY,
45
+ useClass: drizzle_saved_view_repository_1.DrizzleSavedViewRepository
46
+ },
47
+ workspace_grants_query_1.WorkspaceGrantsQuery,
48
+ saved_views_query_1.SavedViewsQuery,
49
+ saved_view_access_service_1.SavedViewAccessService,
50
+ view_scope_service_1.ViewScopeService,
51
+ create_saved_view_use_case_1.CreateSavedViewUseCase,
52
+ update_saved_view_use_case_1.UpdateSavedViewUseCase,
53
+ delete_saved_view_use_case_1.DeleteSavedViewUseCase,
54
+ set_default_view_use_case_1.SetDefaultViewUseCase
55
+ ],
56
+ exports: [saved_views_query_1.SavedViewsQuery]
57
+ };
58
+ }
59
+ };
60
+ exports.ContentViewsModule = ContentViewsModule;
61
+ exports.ContentViewsModule = ContentViewsModule = ContentViewsModule_1 = tslib_1.__decorate([
62
+ (0, common_1.Module)({})
63
+ ], ContentViewsModule);
@@ -0,0 +1,6 @@
1
+ /** Transport-agnostic domain errors for saved views. */
2
+ export { SavedViewNotFoundError } from './saved-view-not-found.error';
3
+ export { SavedViewForbiddenError } from './saved-view-forbidden.error';
4
+ export { SavedViewNameTakenError } from './saved-view-name-taken.error';
5
+ export { SavedViewLimitError } from './saved-view-limit-error';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/domain/errors/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AACxD,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AACxE,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SavedViewLimitError = exports.SavedViewNameTakenError = exports.SavedViewForbiddenError = exports.SavedViewNotFoundError = void 0;
4
+ /** Transport-agnostic domain errors for saved views. */
5
+ var saved_view_not_found_error_1 = require("./saved-view-not-found.error");
6
+ Object.defineProperty(exports, "SavedViewNotFoundError", { enumerable: true, get: function () { return saved_view_not_found_error_1.SavedViewNotFoundError; } });
7
+ var saved_view_forbidden_error_1 = require("./saved-view-forbidden.error");
8
+ Object.defineProperty(exports, "SavedViewForbiddenError", { enumerable: true, get: function () { return saved_view_forbidden_error_1.SavedViewForbiddenError; } });
9
+ var saved_view_name_taken_error_1 = require("./saved-view-name-taken.error");
10
+ Object.defineProperty(exports, "SavedViewNameTakenError", { enumerable: true, get: function () { return saved_view_name_taken_error_1.SavedViewNameTakenError; } });
11
+ var saved_view_limit_error_1 = require("./saved-view-limit-error");
12
+ Object.defineProperty(exports, "SavedViewLimitError", { enumerable: true, get: function () { return saved_view_limit_error_1.SavedViewLimitError; } });
@@ -0,0 +1,10 @@
1
+ /**
2
+ * The caller may read the view but not perform this write — editing or deleting
3
+ * someone else's view, or sharing one without `views:share`. Distinct from
4
+ * {@link SavedViewNotFoundError} because the view's existence is already known
5
+ * to the caller (it is listed for them), so a 403 discloses nothing new.
6
+ */
7
+ export declare class SavedViewForbiddenError extends Error {
8
+ constructor(reason: string);
9
+ }
10
+ //# sourceMappingURL=saved-view-forbidden.error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saved-view-forbidden.error.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/domain/errors/saved-view-forbidden.error.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,qBAAa,uBAAwB,SAAQ,KAAK;gBAClC,MAAM,EAAE,MAAM;CAI7B"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SavedViewForbiddenError = void 0;
4
+ /**
5
+ * The caller may read the view but not perform this write — editing or deleting
6
+ * someone else's view, or sharing one without `views:share`. Distinct from
7
+ * {@link SavedViewNotFoundError} because the view's existence is already known
8
+ * to the caller (it is listed for them), so a 403 discloses nothing new.
9
+ */
10
+ class SavedViewForbiddenError extends Error {
11
+ constructor(reason) {
12
+ super(reason);
13
+ this.name = 'SavedViewForbiddenError';
14
+ }
15
+ }
16
+ exports.SavedViewForbiddenError = SavedViewForbiddenError;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The caller has hit {@link VIEW_MAX_PER_SCOPE} views for one workspace + scope.
3
+ * A bound rather than a business rule: it keeps one account from filling the
4
+ * table, and the number is far above any realistic list of saved slices.
5
+ */
6
+ export declare class SavedViewLimitError extends Error {
7
+ constructor();
8
+ }
9
+ //# sourceMappingURL=saved-view-limit-error.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saved-view-limit-error.d.ts","sourceRoot":"","sources":["../../../../../src/lib/views/domain/errors/saved-view-limit-error.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,qBAAa,mBAAoB,SAAQ,KAAK;;CAK7C"}
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SavedViewLimitError = void 0;
4
+ const views_constants_1 = require("../../views.constants");
5
+ /**
6
+ * The caller has hit {@link VIEW_MAX_PER_SCOPE} views for one workspace + scope.
7
+ * A bound rather than a business rule: it keeps one account from filling the
8
+ * table, and the number is far above any realistic list of saved slices.
9
+ */
10
+ class SavedViewLimitError extends Error {
11
+ constructor() {
12
+ super(`You can save at most ${views_constants_1.VIEW_MAX_PER_SCOPE} views for one list.`);
13
+ this.name = 'SavedViewLimitError';
14
+ }
15
+ }
16
+ exports.SavedViewLimitError = SavedViewLimitError;