@vertebr/admin 0.8.1 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (148) hide show
  1. package/dist/database/connector.d.ts.map +1 -1
  2. package/dist/database/connector.js +45 -2
  3. package/dist/database/connector.js.map +1 -1
  4. package/dist/database/types.d.ts +5 -0
  5. package/dist/database/types.d.ts.map +1 -1
  6. package/dist/index.d.ts +8 -4
  7. package/dist/index.d.ts.map +1 -1
  8. package/dist/index.js +10 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/runtime/api/adapters/express.d.ts +10 -0
  11. package/dist/runtime/api/adapters/express.d.ts.map +1 -0
  12. package/dist/runtime/api/adapters/express.js +80 -0
  13. package/dist/runtime/api/adapters/express.js.map +1 -0
  14. package/dist/runtime/api/adapters/fastify.d.ts +31 -0
  15. package/dist/runtime/api/adapters/fastify.d.ts.map +1 -0
  16. package/dist/runtime/api/adapters/fastify.js +85 -0
  17. package/dist/runtime/api/adapters/fastify.js.map +1 -0
  18. package/dist/runtime/api/adapters/hapi.d.ts +6 -0
  19. package/dist/runtime/api/adapters/hapi.d.ts.map +1 -0
  20. package/dist/runtime/api/adapters/hapi.js +45 -0
  21. package/dist/runtime/api/adapters/hapi.js.map +1 -0
  22. package/dist/runtime/api/adapters/shared.d.ts +17 -0
  23. package/dist/runtime/api/adapters/shared.d.ts.map +1 -0
  24. package/dist/runtime/api/adapters/shared.js +37 -0
  25. package/dist/runtime/api/adapters/shared.js.map +1 -0
  26. package/dist/runtime/api/audit.d.ts +8 -0
  27. package/dist/runtime/api/audit.d.ts.map +1 -0
  28. package/dist/runtime/api/audit.js +30 -0
  29. package/dist/runtime/api/audit.js.map +1 -0
  30. package/dist/runtime/api/catalog.d.ts +56 -4
  31. package/dist/runtime/api/catalog.d.ts.map +1 -1
  32. package/dist/runtime/api/catalog.js +155 -74
  33. package/dist/runtime/api/catalog.js.map +1 -1
  34. package/dist/runtime/api/configs.d.ts +14 -0
  35. package/dist/runtime/api/configs.d.ts.map +1 -1
  36. package/dist/runtime/api/configs.js +128 -2
  37. package/dist/runtime/api/configs.js.map +1 -1
  38. package/dist/runtime/api/health.d.ts +7 -0
  39. package/dist/runtime/api/health.d.ts.map +1 -0
  40. package/dist/runtime/api/health.js +21 -0
  41. package/dist/runtime/api/health.js.map +1 -0
  42. package/dist/runtime/api/jobs.d.ts +12 -0
  43. package/dist/runtime/api/jobs.d.ts.map +1 -0
  44. package/dist/runtime/api/jobs.js +34 -0
  45. package/dist/runtime/api/jobs.js.map +1 -0
  46. package/dist/runtime/api/metrics.d.ts.map +1 -1
  47. package/dist/runtime/api/metrics.js +2 -0
  48. package/dist/runtime/api/metrics.js.map +1 -1
  49. package/dist/runtime/api/public.d.ts.map +1 -1
  50. package/dist/runtime/api/public.js +12 -4
  51. package/dist/runtime/api/public.js.map +1 -1
  52. package/dist/runtime/api/resources.d.ts +29 -0
  53. package/dist/runtime/api/resources.d.ts.map +1 -1
  54. package/dist/runtime/api/resources.js +247 -7
  55. package/dist/runtime/api/resources.js.map +1 -1
  56. package/dist/runtime/api/revisions.d.ts +35 -0
  57. package/dist/runtime/api/revisions.d.ts.map +1 -0
  58. package/dist/runtime/api/revisions.js +174 -0
  59. package/dist/runtime/api/revisions.js.map +1 -0
  60. package/dist/runtime/api/routes.d.ts +2 -5
  61. package/dist/runtime/api/routes.d.ts.map +1 -1
  62. package/dist/runtime/api/routes.js +62 -40
  63. package/dist/runtime/api/routes.js.map +1 -1
  64. package/dist/runtime/api/sync.d.ts +19 -0
  65. package/dist/runtime/api/sync.d.ts.map +1 -0
  66. package/dist/runtime/api/sync.js +213 -0
  67. package/dist/runtime/api/sync.js.map +1 -0
  68. package/dist/runtime/createAdmin.d.ts.map +1 -1
  69. package/dist/runtime/createAdmin.js +82 -2
  70. package/dist/runtime/createAdmin.js.map +1 -1
  71. package/dist/runtime/errors.d.ts +8 -0
  72. package/dist/runtime/errors.d.ts.map +1 -1
  73. package/dist/runtime/errors.js +17 -1
  74. package/dist/runtime/errors.js.map +1 -1
  75. package/dist/runtime/services/access.d.ts +14 -0
  76. package/dist/runtime/services/access.d.ts.map +1 -0
  77. package/dist/runtime/services/access.js +49 -0
  78. package/dist/runtime/services/access.js.map +1 -0
  79. package/dist/runtime/services/audit.d.ts +16 -0
  80. package/dist/runtime/services/audit.d.ts.map +1 -0
  81. package/dist/runtime/services/audit.js +43 -0
  82. package/dist/runtime/services/audit.js.map +1 -0
  83. package/dist/runtime/services/environment.d.ts +4 -1
  84. package/dist/runtime/services/environment.d.ts.map +1 -1
  85. package/dist/runtime/services/environment.js +16 -2
  86. package/dist/runtime/services/environment.js.map +1 -1
  87. package/dist/runtime/services/state.d.ts +17 -0
  88. package/dist/runtime/services/state.d.ts.map +1 -1
  89. package/dist/runtime/types/access.d.ts +28 -0
  90. package/dist/runtime/types/access.d.ts.map +1 -0
  91. package/dist/runtime/types/access.js +3 -0
  92. package/dist/runtime/types/access.js.map +1 -0
  93. package/dist/runtime/types/actions.d.ts +2 -0
  94. package/dist/runtime/types/actions.d.ts.map +1 -1
  95. package/dist/runtime/types/addon.d.ts +31 -0
  96. package/dist/runtime/types/addon.d.ts.map +1 -0
  97. package/dist/runtime/types/addon.js +9 -0
  98. package/dist/runtime/types/addon.js.map +1 -0
  99. package/dist/runtime/types/admin.d.ts +50 -0
  100. package/dist/runtime/types/admin.d.ts.map +1 -1
  101. package/dist/runtime/types/audit.d.ts +35 -0
  102. package/dist/runtime/types/audit.d.ts.map +1 -0
  103. package/dist/runtime/types/audit.js +3 -0
  104. package/dist/runtime/types/audit.js.map +1 -0
  105. package/dist/runtime/types/auth.d.ts +6 -0
  106. package/dist/runtime/types/auth.d.ts.map +1 -1
  107. package/dist/runtime/types/config.d.ts +1 -1
  108. package/dist/runtime/types/config.d.ts.map +1 -1
  109. package/dist/runtime/types/events.d.ts +63 -0
  110. package/dist/runtime/types/events.d.ts.map +1 -0
  111. package/dist/runtime/types/events.js +3 -0
  112. package/dist/runtime/types/events.js.map +1 -0
  113. package/dist/runtime/types/health.d.ts +18 -0
  114. package/dist/runtime/types/health.d.ts.map +1 -0
  115. package/dist/runtime/types/health.js +3 -0
  116. package/dist/runtime/types/health.js.map +1 -0
  117. package/dist/runtime/types/index.d.ts +10 -2
  118. package/dist/runtime/types/index.d.ts.map +1 -1
  119. package/dist/runtime/types/jobs.d.ts +21 -0
  120. package/dist/runtime/types/jobs.d.ts.map +1 -0
  121. package/dist/runtime/types/jobs.js +3 -0
  122. package/dist/runtime/types/jobs.js.map +1 -0
  123. package/dist/runtime/types/resource.d.ts +30 -1
  124. package/dist/runtime/types/resource.d.ts.map +1 -1
  125. package/dist/runtime/types/revisions.d.ts +33 -0
  126. package/dist/runtime/types/revisions.d.ts.map +1 -0
  127. package/dist/runtime/types/revisions.js +3 -0
  128. package/dist/runtime/types/revisions.js.map +1 -0
  129. package/dist/runtime/types/sync.d.ts +99 -0
  130. package/dist/runtime/types/sync.d.ts.map +1 -0
  131. package/dist/runtime/types/sync.js +3 -0
  132. package/dist/runtime/types/sync.js.map +1 -0
  133. package/dist/runtime/utils/http.d.ts +2 -0
  134. package/dist/runtime/utils/http.d.ts.map +1 -1
  135. package/dist/runtime/utils/http.js +24 -0
  136. package/dist/runtime/utils/http.js.map +1 -1
  137. package/dist/schema.d.ts +20 -1
  138. package/dist/schema.d.ts.map +1 -1
  139. package/dist/store.d.ts +6 -0
  140. package/dist/store.d.ts.map +1 -1
  141. package/dist/store.js +74 -0
  142. package/dist/store.js.map +1 -1
  143. package/package.json +1 -1
  144. package/static/assets/index-DIdeXSPR.js +340 -0
  145. package/static/assets/index-oaieFDp4.css +1 -0
  146. package/static/index.html +2 -2
  147. package/static/assets/index-D5BVgGQP.js +0 -337
  148. package/static/assets/index-DORD_jLa.css +0 -1
@@ -0,0 +1,7 @@
1
+ import type { AdminState } from "../services/state";
2
+ export declare function healthHandler(state: AdminState, request: unknown): Promise<{
3
+ ok: boolean;
4
+ environment: string;
5
+ checks: import("../types").HealthCheck[];
6
+ }>;
7
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/health.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAEpD,wBAAsB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;GAatE"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.healthHandler = healthHandler;
4
+ const errors_1 = require("../errors");
5
+ const access_1 = require("../services/access");
6
+ const environment_1 = require("../services/environment");
7
+ async function healthHandler(state, request) {
8
+ return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
9
+ (0, access_1.assertCapability)(ctx, "health.read");
10
+ if (!state.healthDef) {
11
+ throw new errors_1.VertebrNotFoundError("Health is not configured");
12
+ }
13
+ const checks = await state.healthDef.load(ctx);
14
+ return {
15
+ ok: true,
16
+ environment: ctx.env,
17
+ checks,
18
+ };
19
+ });
20
+ }
21
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../../src/runtime/api/health.ts"],"names":[],"mappings":";;AAKA,sCAaC;AAlBD,sCAAiD;AACjD,+CAAsD;AACtD,yDAAyD;AAGlD,KAAK,UAAU,aAAa,CAAC,KAAiB,EAAE,OAAgB;IACrE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,IAAA,yBAAgB,EAAC,GAAG,EAAE,aAAa,CAAC,CAAC;QACrC,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;YACrB,MAAM,IAAI,6BAAoB,CAAC,0BAA0B,CAAC,CAAC;QAC7D,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/C,OAAO;YACL,EAAE,EAAE,IAAI;YACR,WAAW,EAAE,GAAG,CAAC,GAAG;YACpB,MAAM;SACP,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { AdminState } from "../services/state";
2
+ export declare function listJobsHandler(state: AdminState, request: unknown): Promise<{
3
+ ok: boolean;
4
+ environment: string;
5
+ items: import("../types").Job[];
6
+ }>;
7
+ export declare function getJobHandler(state: AdminState, request: unknown): Promise<{
8
+ ok: boolean;
9
+ environment: string;
10
+ job: import("../types").Job;
11
+ }>;
12
+ //# sourceMappingURL=jobs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/jobs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAsB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;GASxE;AAED,wBAAsB,aAAa,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;GAYtE"}
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.listJobsHandler = listJobsHandler;
4
+ exports.getJobHandler = getJobHandler;
5
+ const errors_1 = require("../errors");
6
+ const access_1 = require("../services/access");
7
+ const environment_1 = require("../services/environment");
8
+ const request_1 = require("./request");
9
+ async function listJobsHandler(state, request) {
10
+ return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
11
+ (0, access_1.assertCapability)(ctx, "jobs.read");
12
+ if (!state.jobsDef) {
13
+ throw new errors_1.VertebrNotFoundError("Jobs are not configured");
14
+ }
15
+ const items = await state.jobsDef.list(ctx);
16
+ return { ok: true, environment: ctx.env, items };
17
+ });
18
+ }
19
+ async function getJobHandler(state, request) {
20
+ return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
21
+ (0, access_1.assertCapability)(ctx, "jobs.read");
22
+ if (!state.jobsDef) {
23
+ throw new errors_1.VertebrNotFoundError("Jobs are not configured");
24
+ }
25
+ const id = (0, request_1.requestParam)(request, "id");
26
+ if (!id)
27
+ throw new errors_1.VertebrNotFoundError("Missing job id");
28
+ const job = await state.jobsDef.get(id, ctx);
29
+ if (!job)
30
+ throw new errors_1.VertebrNotFoundError(`Job "${id}" not found`);
31
+ return { ok: true, environment: ctx.env, job };
32
+ });
33
+ }
34
+ //# sourceMappingURL=jobs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jobs.js","sourceRoot":"","sources":["../../../src/runtime/api/jobs.ts"],"names":[],"mappings":";;AAMA,0CASC;AAED,sCAYC;AA7BD,sCAAiD;AACjD,+CAAsD;AACtD,yDAAyD;AAEzD,uCAAyC;AAElC,KAAK,UAAU,eAAe,CAAC,KAAiB,EAAE,OAAgB;IACvE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,IAAA,yBAAgB,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,6BAAoB,CAAC,yBAAyB,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,KAAK,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC;IACnD,CAAC,CAAC,CAAC;AACL,CAAC;AAEM,KAAK,UAAU,aAAa,CAAC,KAAiB,EAAE,OAAgB;IACrE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,IAAA,yBAAgB,EAAC,GAAG,EAAE,WAAW,CAAC,CAAC;QACnC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;YACnB,MAAM,IAAI,6BAAoB,CAAC,yBAAyB,CAAC,CAAC;QAC5D,CAAC;QACD,MAAM,EAAE,GAAG,IAAA,sBAAY,EAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,EAAE;YAAE,MAAM,IAAI,6BAAoB,CAAC,gBAAgB,CAAC,CAAC;QAC1D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;QAC7C,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,6BAAoB,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;QAClE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/metrics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,wBAAsB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;GAgCvE"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/metrics.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,wBAAsB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;GAiCvE"}
@@ -2,8 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.metricsHandler = metricsHandler;
4
4
  const environment_1 = require("../services/environment");
5
+ const access_1 = require("../services/access");
5
6
  async function metricsHandler(state, request) {
6
7
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
8
+ (0, access_1.assertCapability)(ctx, "overview.read");
7
9
  if (!state.metricsDef) {
8
10
  return {
9
11
  ok: true,
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/runtime/api/metrics.ts"],"names":[],"mappings":";;AAIA,wCAgCC;AApCD,yDAAyD;AAIlD,KAAK,UAAU,cAAc,CAAC,KAAiB,EAAE,OAAgB;IACtE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,EAAE,EAAE,UAAU;gBACd,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,GAAG,CAAC,GAAG;gBACpB,OAAO,EAAE,EAAE;gBACX,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,CAAC,CAAC;gBACE,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAmB;gBAC3B,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,SAAS;aACxB;YACH,CAAC,CAAC,MAAM,CAAC;QACX,OAAO;YACL,EAAE,EAAE,IAAI;YACR,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU;YACrC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,IAAI,UAAU;YAC3C,WAAW,EAAE,GAAG,CAAC,GAAG;YACpB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;SAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"metrics.js","sourceRoot":"","sources":["../../../src/runtime/api/metrics.ts"],"names":[],"mappings":";;AAKA,wCAiCC;AAtCD,yDAAyD;AACzD,+CAAsD;AAI/C,KAAK,UAAU,cAAc,CAAC,KAAiB,EAAE,OAAgB;IACtE,OAAO,IAAA,4BAAc,EAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,IAAA,yBAAgB,EAAC,GAAG,EAAE,eAAe,CAAC,CAAC;QACvC,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;YACtB,OAAO;gBACL,EAAE,EAAE,IAAI;gBACR,EAAE,EAAE,UAAU;gBACd,KAAK,EAAE,UAAU;gBACjB,WAAW,EAAE,GAAG,CAAC,GAAG;gBACpB,OAAO,EAAE,EAAE;gBACX,MAAM,EAAE,EAAE;aACX,CAAC;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YACnC,CAAC,CAAC;gBACE,OAAO,EAAE,MAAM;gBACf,MAAM,EAAE,EAAmB;gBAC3B,WAAW,EAAE,SAAS;gBACtB,YAAY,EAAE,SAAS;aACxB;YACH,CAAC,CAAC,MAAM,CAAC;QACX,OAAO;YACL,EAAE,EAAE,IAAI;YACR,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,IAAI,UAAU;YACrC,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,KAAK,IAAI,UAAU;YAC3C,WAAW,EAAE,GAAG,CAAC,GAAG;YACpB,WAAW,EAAE,OAAO,CAAC,WAAW;YAChC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,OAAO,EAAE,OAAO,CAAC,OAAO,IAAI,EAAE;YAC9B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,EAAE;SAC7B,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAiBjB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAoBjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAuBjB"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/public.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAGpD,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAwBjB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAwBjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAwBjB"}
@@ -11,14 +11,17 @@ async function publicControlsHandler(state, request) {
11
11
  return (0, environment_1.withPublicEnvContext)(state, request, async (ctx) => {
12
12
  const entries = await Promise.all([...state.controlMeta.entries()]
13
13
  .filter(([, meta]) => meta.public)
14
- .map(async ([id]) => {
14
+ .map(async ([id, meta]) => {
15
15
  const value = await (0, registry_1.readConfigValue)(state, id, ctx.env);
16
+ if (meta.addon && meta.gatePublic !== false && value.enabled === false) {
17
+ return null;
18
+ }
16
19
  return [id, value];
17
20
  }));
18
21
  return {
19
22
  ok: true,
20
23
  environment: ctx.env,
21
- configs: Object.fromEntries(entries),
24
+ configs: Object.fromEntries(entries.filter((entry) => entry !== null)),
22
25
  };
23
26
  });
24
27
  }
@@ -32,13 +35,17 @@ async function publicConfigHandler(state, request) {
32
35
  if (!meta?.public) {
33
36
  throw new errors_1.VertebrNotFoundError(`Public control "${id}" not found`);
34
37
  }
38
+ const value = await (0, registry_1.readConfigValue)(state, id, ctx.env);
39
+ if (meta.addon && meta.gatePublic !== false && value.enabled === false) {
40
+ throw new errors_1.VertebrNotFoundError(`Public control "${id}" not found`);
41
+ }
35
42
  const config = (0, registry_1.findConfig)(state, id);
36
43
  return {
37
44
  ok: true,
38
45
  id,
39
46
  label: config.label,
40
47
  environment: ctx.env,
41
- value: await (0, registry_1.readConfigValue)(state, id, ctx.env),
48
+ value,
42
49
  };
43
50
  });
44
51
  }
@@ -53,7 +60,8 @@ async function publicResourceHandler(state, request) {
53
60
  throw new errors_1.VertebrNotFoundError(`Public resource "${id}" not found`);
54
61
  }
55
62
  const listed = resource.list ? await resource.list(ctx) : [];
56
- const items = listed.filter((row) => {
63
+ const rows = Array.isArray(listed) ? listed : listed.items ?? [];
64
+ const items = rows.filter((row) => {
57
65
  if (!row || typeof row !== "object")
58
66
  return false;
59
67
  return row.active !== false;
@@ -1 +1 @@
1
- {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/runtime/api/public.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"public.js","sourceRoot":"","sources":["../../../src/runtime/api/public.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,18 @@
1
1
  import type { FieldSchema, ResourceUploadResult } from "../../schema";
2
2
  import type { AdminState } from "../services/state";
3
3
  export declare function listResourceHandler(state: AdminState, request: unknown): Promise<{
4
+ listQuery?: boolean | Record<string, FieldSchema> | undefined;
5
+ query?: {
6
+ filters?: Record<string, string> | undefined;
7
+ cursor?: string | undefined;
8
+ offset?: number | undefined;
9
+ limit?: number | undefined;
10
+ order?: "asc" | "desc" | undefined;
11
+ sort?: string | undefined;
12
+ q?: string | undefined;
13
+ } | undefined;
14
+ cursor?: string | undefined;
15
+ total?: number | undefined;
4
16
  id: string;
5
17
  label: string;
6
18
  schema: Record<string, FieldSchema>;
@@ -14,6 +26,11 @@ export declare function listResourceHandler(state: AdminState, request: unknown)
14
26
  label: string;
15
27
  input?: Record<string, FieldSchema>;
16
28
  mail?: boolean;
29
+ bulk?: boolean;
30
+ }>;
31
+ bulkActions: Record<string, {
32
+ label: string;
33
+ input?: Record<string, FieldSchema>;
17
34
  }>;
18
35
  collectionActions: Record<string, {
19
36
  label: string;
@@ -65,6 +82,18 @@ export declare function resourceActionHandler(state: AdminState, request: unknow
65
82
  environment: string;
66
83
  result: unknown;
67
84
  }>;
85
+ export declare function bulkActionHandler(state: AdminState, request: unknown): Promise<{
86
+ ok: boolean;
87
+ id: string;
88
+ actionId: string;
89
+ environment: string;
90
+ results: {
91
+ rowId: string;
92
+ ok: boolean;
93
+ result?: unknown;
94
+ error?: string;
95
+ }[];
96
+ }>;
68
97
  export declare function mailPreviewHandler(state: AdminState, request: unknown): Promise<{
69
98
  to: string | string[];
70
99
  subject: string;
@@ -1 +1 @@
1
- {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/resources.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EAGX,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAGtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAoIpD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;;;;;eA5DP,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;eAAS,OAAO;;;eAwCzD,MAAM;kBAAY,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;;;GAyCzE;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;GAajB;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAuBjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAgBjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAejB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAejB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;GAwBjB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;;;;GAqCjB;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAuBjB"}
1
+ {"version":3,"file":"resources.d.ts","sourceRoot":"","sources":["../../../src/runtime/api/resources.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACV,WAAW,EAGX,oBAAoB,EACrB,MAAM,cAAc,CAAC;AAKtB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAqNpD,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;eAnGP,MAAM;gBACL,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;eAC5B,OAAO;eACP,OAAO;;;eAqBS,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;;eAuDzD,MAAM;kBAAY,MAAM;gBAAU,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC;;;;GAsDzE;AAED,wBAAsB,yBAAyB,CAC7C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;GAcjB;AAED,wBAAsB,0BAA0B,CAC9C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAwBjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAiCjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAqCjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;GAgCjB;AAED,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;GAiDjB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;eA8BL,MAAM;YACT,OAAO;iBACF,OAAO;gBACR,MAAM;;GAqCnB;AAED,wBAAsB,kBAAkB,CACtC,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;;;;;GAsCjB;AAED,wBAAsB,uBAAuB,CAC3C,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,OAAO;;;;;;GAsCjB"}
@@ -7,15 +7,54 @@ exports.updateResourceHandler = updateResourceHandler;
7
7
  exports.createResourceHandler = createResourceHandler;
8
8
  exports.deleteResourceHandler = deleteResourceHandler;
9
9
  exports.resourceActionHandler = resourceActionHandler;
10
+ exports.bulkActionHandler = bulkActionHandler;
10
11
  exports.mailPreviewHandler = mailPreviewHandler;
11
12
  exports.collectionActionHandler = collectionActionHandler;
12
13
  const constants_1 = require("../constants");
13
14
  const errors_1 = require("../errors");
15
+ const access_1 = require("../services/access");
16
+ const audit_1 = require("../services/audit");
14
17
  const environment_1 = require("../services/environment");
15
18
  const registry_1 = require("../services/registry");
16
19
  const uploads_1 = require("../utils/uploads");
17
20
  const mail_1 = require("../mail");
18
21
  const request_1 = require("./request");
22
+ function normalizeListResult(raw) {
23
+ if (Array.isArray(raw))
24
+ return { items: raw };
25
+ return {
26
+ items: raw.items ?? [],
27
+ ...(raw.total != null ? { total: raw.total } : {}),
28
+ ...(raw.cursor ? { cursor: raw.cursor } : {}),
29
+ };
30
+ }
31
+ function parseListQuery(query) {
32
+ if (!query)
33
+ return {};
34
+ const filters = {};
35
+ for (const [key, value] of Object.entries(query)) {
36
+ if (key.startsWith("filter.") || key.startsWith("filters.")) {
37
+ const field = key.replace(/^filters?\./, "");
38
+ if (field)
39
+ filters[field] = value;
40
+ }
41
+ }
42
+ return {
43
+ ...(query.q ? { q: query.q } : {}),
44
+ ...(query.sort ? { sort: query.sort } : {}),
45
+ ...(query.order === "asc" || query.order === "desc"
46
+ ? { order: query.order }
47
+ : {}),
48
+ ...(query.limit && Number.isFinite(Number(query.limit))
49
+ ? { limit: Number(query.limit) }
50
+ : {}),
51
+ ...(query.offset && Number.isFinite(Number(query.offset))
52
+ ? { offset: Number(query.offset) }
53
+ : {}),
54
+ ...(query.cursor ? { cursor: query.cursor } : {}),
55
+ ...(Object.keys(filters).length ? { filters } : {}),
56
+ };
57
+ }
19
58
  async function runFieldUpload(resource, field, file, ctx) {
20
59
  const def = resource.uploads?.[field];
21
60
  if (!def) {
@@ -58,18 +97,46 @@ function resolvedActions(state, resource) {
58
97
  {
59
98
  label: action.label,
60
99
  input: (0, mail_1.normalizeActionInput)(action.input),
100
+ ...(action.bulk ? { bulk: true } : {}),
61
101
  },
62
102
  ]))
63
103
  : {};
64
104
  return { ...fromMail, ...fromResource };
65
105
  }
106
+ function resolvedBulkActions(resource) {
107
+ const fromBulk = resource.bulkActions
108
+ ? Object.fromEntries(Object.entries(resource.bulkActions).map(([key, action]) => [
109
+ key,
110
+ {
111
+ label: action.label,
112
+ input: (0, mail_1.normalizeActionInput)(action.input),
113
+ },
114
+ ]))
115
+ : {};
116
+ const fromRow = resource.actions
117
+ ? Object.fromEntries(Object.entries(resource.actions)
118
+ .filter(([, action]) => action.bulk)
119
+ .map(([key, action]) => [
120
+ key,
121
+ {
122
+ label: action.label,
123
+ input: (0, mail_1.normalizeActionInput)(action.input),
124
+ },
125
+ ]))
126
+ : {};
127
+ return { ...fromRow, ...fromBulk };
128
+ }
66
129
  async function loadResourceRow(resource, rowId, ctx) {
67
- const row = resource.get
68
- ? await resource.get(rowId, ctx)
69
- : (await (resource.list?.(ctx) ?? [])).find((item) => String(item.id ?? "") === rowId ||
70
- String(item.slug ?? "") === rowId ||
71
- String(item.uid ?? "") === rowId ||
72
- String(item.email ?? "") === rowId);
130
+ if (resource.get) {
131
+ const row = await resource.get(rowId, ctx);
132
+ return row;
133
+ }
134
+ const raw = await (resource.list?.(ctx) ?? []);
135
+ const items = normalizeListResult(raw).items;
136
+ const row = items.find((item) => String(item.id ?? "") === rowId ||
137
+ String(item.slug ?? "") === rowId ||
138
+ String(item.uid ?? "") === rowId ||
139
+ String(item.email ?? "") === rowId);
73
140
  return row;
74
141
  }
75
142
  async function resolvedCollectionActions(resource, ctx) {
@@ -88,12 +155,15 @@ async function resolvedCollectionActions(resource, ctx) {
88
155
  }
89
156
  async function listResourceHandler(state, request) {
90
157
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
158
+ (0, access_1.assertCapability)(ctx, "resource.read");
91
159
  const id = (0, request_1.requestParam)(request, "id");
92
160
  if (!id) {
93
161
  throw new errors_1.VertebrNotFoundError("Missing resource id");
94
162
  }
95
163
  const resource = (0, registry_1.findResource)(state, id);
96
- const items = resource.list ? await resource.list(ctx) : [];
164
+ const raw = resource.list ? await resource.list(ctx) : [];
165
+ const { items, total, cursor } = normalizeListResult(raw);
166
+ const parsedQuery = parseListQuery(ctx.query);
97
167
  return {
98
168
  id: resource.id,
99
169
  label: resource.label,
@@ -101,14 +171,24 @@ async function listResourceHandler(state, request) {
101
171
  environment: ctx.env,
102
172
  permissions: await resolvedPermissions(resource, ctx),
103
173
  actions: resolvedActions(state, resource),
174
+ bulkActions: resolvedBulkActions(resource),
104
175
  collectionActions: await resolvedCollectionActions(resource, ctx),
105
176
  uploads: (0, uploads_1.publicUploads)(resource),
106
177
  items,
178
+ ...(total != null ? { total } : {}),
179
+ ...(cursor ? { cursor } : {}),
180
+ ...(Object.keys(parsedQuery).length ? { query: parsedQuery } : {}),
181
+ ...(resource.listQuery != null
182
+ ? {
183
+ listQuery: resource.listQuery === true ? true : resource.listQuery,
184
+ }
185
+ : {}),
107
186
  };
108
187
  });
109
188
  }
110
189
  async function uploadResourceFileHandler(state, request) {
111
190
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
191
+ (0, access_1.assertCapability)(ctx, "resource.write");
112
192
  const id = (0, request_1.requestParam)(request, "id");
113
193
  const field = (0, request_1.requestParam)(request, "field");
114
194
  if (!id || !field) {
@@ -122,6 +202,7 @@ async function uploadResourceFileHandler(state, request) {
122
202
  }
123
203
  async function uploadResourceFilesHandler(state, request) {
124
204
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
205
+ (0, access_1.assertCapability)(ctx, "resource.write");
125
206
  const id = (0, request_1.requestParam)(request, "id");
126
207
  const field = (0, request_1.requestParam)(request, "field");
127
208
  if (!id || !field) {
@@ -145,6 +226,7 @@ async function uploadResourceFilesHandler(state, request) {
145
226
  }
146
227
  async function updateResourceHandler(state, request) {
147
228
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
229
+ (0, access_1.assertCapability)(ctx, "resource.write");
148
230
  const id = (0, request_1.requestParam)(request, "id");
149
231
  const rowId = (0, request_1.requestParam)(request, "rowId");
150
232
  if (!id || !rowId) {
@@ -156,11 +238,28 @@ async function updateResourceHandler(state, request) {
156
238
  }
157
239
  const value = (0, request_1.requestObjectPayload)(request);
158
240
  const item = await resource.update(rowId, value, ctx);
241
+ await (0, audit_1.afterMutation)(state, ctx, {
242
+ audit: {
243
+ action: "resource.update",
244
+ targetType: "resource",
245
+ targetId: `${id}/${rowId}`,
246
+ summary: `Updated ${resource.label} row ${rowId}`,
247
+ },
248
+ event: {
249
+ type: "resource.written",
250
+ resourceId: id,
251
+ rowId,
252
+ op: "update",
253
+ env: ctx.env,
254
+ actor: (0, audit_1.eventActor)(ctx),
255
+ },
256
+ });
159
257
  return { ok: true, id, rowId, environment: ctx.env, item };
160
258
  });
161
259
  }
162
260
  async function createResourceHandler(state, request) {
163
261
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
262
+ (0, access_1.assertCapability)(ctx, "resource.write");
164
263
  const id = (0, request_1.requestParam)(request, "id");
165
264
  if (!id) {
166
265
  throw new errors_1.VertebrNotFoundError("Missing resource id");
@@ -171,11 +270,31 @@ async function createResourceHandler(state, request) {
171
270
  }
172
271
  const value = (0, request_1.requestObjectPayload)(request);
173
272
  const item = await resource.create(value, ctx);
273
+ const rowId = String(item?.id ??
274
+ item?.slug ??
275
+ "");
276
+ await (0, audit_1.afterMutation)(state, ctx, {
277
+ audit: {
278
+ action: "resource.create",
279
+ targetType: "resource",
280
+ targetId: `${id}/${rowId || "new"}`,
281
+ summary: `Created ${resource.label} row`,
282
+ },
283
+ event: {
284
+ type: "resource.written",
285
+ resourceId: id,
286
+ rowId: rowId || "new",
287
+ op: "create",
288
+ env: ctx.env,
289
+ actor: (0, audit_1.eventActor)(ctx),
290
+ },
291
+ });
174
292
  return { ok: true, id, environment: ctx.env, item };
175
293
  });
176
294
  }
177
295
  async function deleteResourceHandler(state, request) {
178
296
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
297
+ (0, access_1.assertCapability)(ctx, "resource.delete");
179
298
  const id = (0, request_1.requestParam)(request, "id");
180
299
  const rowId = (0, request_1.requestParam)(request, "rowId");
181
300
  if (!id || !rowId) {
@@ -186,11 +305,28 @@ async function deleteResourceHandler(state, request) {
186
305
  throw new errors_1.VertebrNotFoundError(`Resource "${id}" cannot delete`);
187
306
  }
188
307
  await resource.remove(rowId, ctx);
308
+ await (0, audit_1.afterMutation)(state, ctx, {
309
+ audit: {
310
+ action: "resource.delete",
311
+ targetType: "resource",
312
+ targetId: `${id}/${rowId}`,
313
+ summary: `Deleted ${resource.label} row ${rowId}`,
314
+ },
315
+ event: {
316
+ type: "resource.written",
317
+ resourceId: id,
318
+ rowId,
319
+ op: "delete",
320
+ env: ctx.env,
321
+ actor: (0, audit_1.eventActor)(ctx),
322
+ },
323
+ });
189
324
  return { ok: true, id, rowId, environment: ctx.env };
190
325
  });
191
326
  }
192
327
  async function resourceActionHandler(state, request) {
193
328
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
329
+ (0, access_1.assertCapability)(ctx, "resource.action");
194
330
  const id = (0, request_1.requestParam)(request, "id");
195
331
  const rowId = (0, request_1.requestParam)(request, "rowId");
196
332
  const actionId = (0, request_1.requestParam)(request, "actionId");
@@ -209,11 +345,99 @@ async function resourceActionHandler(state, request) {
209
345
  }
210
346
  const input = (0, request_1.requestOptionalObjectPayload)(request);
211
347
  const result = await action.run(row, input, ctx);
348
+ const jobId = result &&
349
+ typeof result === "object" &&
350
+ typeof result.jobId === "string"
351
+ ? result.jobId
352
+ : undefined;
353
+ await (0, audit_1.afterMutation)(state, ctx, {
354
+ audit: {
355
+ action: `resource.action.${actionId}`,
356
+ targetType: "resource",
357
+ targetId: `${id}/${rowId}`,
358
+ summary: `Ran ${action.label} on ${rowId}`,
359
+ ...(jobId ? { meta: { jobId } } : {}),
360
+ },
361
+ event: {
362
+ type: "resource.action",
363
+ resourceId: id,
364
+ rowId,
365
+ actionId,
366
+ env: ctx.env,
367
+ actor: (0, audit_1.eventActor)(ctx),
368
+ ...(jobId ? { jobId } : {}),
369
+ },
370
+ });
212
371
  return { ok: true, id, rowId, actionId, environment: ctx.env, result };
213
372
  });
214
373
  }
374
+ async function bulkActionHandler(state, request) {
375
+ return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
376
+ (0, access_1.assertCapability)(ctx, "resource.action");
377
+ const id = (0, request_1.requestParam)(request, "id");
378
+ const actionId = (0, request_1.requestParam)(request, "actionId");
379
+ if (!id || !actionId) {
380
+ throw new errors_1.VertebrNotFoundError("Missing resource or action id");
381
+ }
382
+ const resource = (0, registry_1.findResource)(state, id);
383
+ const action = resource.bulkActions?.[actionId] ??
384
+ (resource.actions?.[actionId]?.bulk
385
+ ? resource.actions[actionId]
386
+ : undefined);
387
+ if (!action) {
388
+ throw new errors_1.VertebrNotFoundError(`Bulk action "${actionId}" not found`);
389
+ }
390
+ const body = (0, request_1.requestObjectPayload)(request);
391
+ const rowIds = Array.isArray(body.rowIds)
392
+ ? body.rowIds.map(String)
393
+ : [];
394
+ if (!rowIds.length) {
395
+ throw new errors_1.VertebrBadRequestError("Provide rowIds: string[]");
396
+ }
397
+ const input = body.input && typeof body.input === "object"
398
+ ? body.input
399
+ : undefined;
400
+ const results = [];
401
+ for (const rowId of rowIds) {
402
+ try {
403
+ const row = await loadResourceRow(resource, rowId, ctx);
404
+ if (!row) {
405
+ results.push({ rowId, ok: false, error: "Not found" });
406
+ continue;
407
+ }
408
+ const result = await action.run(row, input, ctx);
409
+ results.push({ rowId, ok: true, result });
410
+ }
411
+ catch (error) {
412
+ results.push({
413
+ rowId,
414
+ ok: false,
415
+ error: error instanceof Error ? error.message : "Failed",
416
+ });
417
+ }
418
+ }
419
+ await (0, audit_1.afterMutation)(state, ctx, {
420
+ audit: {
421
+ action: `resource.bulk.${actionId}`,
422
+ targetType: "resource",
423
+ targetId: id,
424
+ summary: `Bulk ${action.label} on ${rowIds.length} rows`,
425
+ meta: { rowIds },
426
+ },
427
+ event: {
428
+ type: "resource.action",
429
+ resourceId: id,
430
+ actionId,
431
+ env: ctx.env,
432
+ actor: (0, audit_1.eventActor)(ctx),
433
+ },
434
+ });
435
+ return { ok: true, id, actionId, environment: ctx.env, results };
436
+ });
437
+ }
215
438
  async function mailPreviewHandler(state, request) {
216
439
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
440
+ (0, access_1.assertCapability)(ctx, "emails.read");
217
441
  const id = (0, request_1.requestParam)(request, "id");
218
442
  const rowId = (0, request_1.requestParam)(request, "rowId");
219
443
  const templateId = (0, request_1.requestParam)(request, "templateId");
@@ -244,6 +468,7 @@ async function mailPreviewHandler(state, request) {
244
468
  }
245
469
  async function collectionActionHandler(state, request) {
246
470
  return (0, environment_1.withEnvContext)(state, request, async (ctx) => {
471
+ (0, access_1.assertCapability)(ctx, "resource.action");
247
472
  const id = (0, request_1.requestParam)(request, "id");
248
473
  const actionId = (0, request_1.requestParam)(request, "actionId");
249
474
  if (!id || !actionId) {
@@ -261,6 +486,21 @@ async function collectionActionHandler(state, request) {
261
486
  }
262
487
  const input = (0, request_1.requestOptionalObjectPayload)(request);
263
488
  const result = await action.run(input, ctx);
489
+ await (0, audit_1.afterMutation)(state, ctx, {
490
+ audit: {
491
+ action: `resource.collection.${actionId}`,
492
+ targetType: "resource",
493
+ targetId: id,
494
+ summary: `Ran collection action ${action.label}`,
495
+ },
496
+ event: {
497
+ type: "resource.action",
498
+ resourceId: id,
499
+ actionId,
500
+ env: ctx.env,
501
+ actor: (0, audit_1.eventActor)(ctx),
502
+ },
503
+ });
264
504
  return { ok: true, id, actionId, environment: ctx.env, result };
265
505
  });
266
506
  }