@antelopejs/dms 0.4.3 → 0.4.5

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 (85) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/config.d.ts +1 -0
  3. package/dist/config.js.map +1 -1
  4. package/dist/implementations/dms/page.d.ts +1 -0
  5. package/dist/implementations/dms/page.js +8 -1
  6. package/dist/implementations/dms/page.js.map +1 -1
  7. package/dist/implementations/dms/stale-session.d.ts +2 -0
  8. package/dist/implementations/dms/stale-session.js +16 -0
  9. package/dist/implementations/dms/stale-session.js.map +1 -0
  10. package/dist/implementations/dms-auth/index.d.ts +1 -0
  11. package/dist/implementations/dms-auth/index.js +19 -0
  12. package/dist/implementations/dms-auth/index.js.map +1 -1
  13. package/dist/routes/auth/client-ip.d.ts +7 -0
  14. package/dist/routes/auth/client-ip.js +42 -0
  15. package/dist/routes/auth/client-ip.js.map +1 -0
  16. package/dist/routes/auth/index.d.ts +1 -0
  17. package/dist/routes/auth/index.js +1 -0
  18. package/dist/routes/auth/index.js.map +1 -1
  19. package/dist/routes/auth.d.ts +3 -0
  20. package/dist/routes/auth.js +15 -4
  21. package/dist/routes/auth.js.map +1 -1
  22. package/dist/test/integration/auth/client-ip.test.d.ts +1 -0
  23. package/dist/test/integration/auth/client-ip.test.js +14 -0
  24. package/dist/test/integration/auth/client-ip.test.js.map +1 -0
  25. package/dist/test/integration/page-session.test.d.ts +1 -0
  26. package/dist/test/integration/page-session.test.js +52 -0
  27. package/dist/test/integration/page-session.test.js.map +1 -0
  28. package/dist/test/unit/client-ip.test.d.ts +1 -0
  29. package/dist/test/unit/client-ip.test.js +77 -0
  30. package/dist/test/unit/client-ip.test.js.map +1 -0
  31. package/dist/test/unit/interfaces/dms-base/form-catalog.test.d.ts +1 -0
  32. package/dist/test/unit/interfaces/dms-base/form-catalog.test.js +62 -0
  33. package/dist/test/unit/interfaces/dms-base/form-catalog.test.js.map +1 -0
  34. package/dist/test/unit/interfaces/dms-base/period-selector-catalog.test.d.ts +1 -0
  35. package/dist/test/unit/interfaces/dms-base/period-selector-catalog.test.js +36 -0
  36. package/dist/test/unit/interfaces/dms-base/period-selector-catalog.test.js.map +1 -0
  37. package/dist/test/unit/interfaces/dms-base/resource-form.test.d.ts +1 -0
  38. package/dist/test/unit/interfaces/dms-base/resource-form.test.js +117 -0
  39. package/dist/test/unit/interfaces/dms-base/resource-form.test.js.map +1 -0
  40. package/dist/test/unit/interfaces/dms-base/table-and-card-catalog.test.d.ts +1 -0
  41. package/dist/test/unit/interfaces/dms-base/table-and-card-catalog.test.js +62 -0
  42. package/dist/test/unit/interfaces/dms-base/table-and-card-catalog.test.js.map +1 -0
  43. package/dist/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.d.ts +1 -0
  44. package/dist/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.js +96 -0
  45. package/dist/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.js.map +1 -0
  46. package/frontend-vue/layers/dms-auth/app/middleware/auth.ts +5 -2
  47. package/frontend-vue/layers/dms-core/app/composables/useApiError.ts +27 -2
  48. package/frontend-vue/layers/dms-core/app/utils/menu.ts +26 -10
  49. package/frontend-vue/layers/dms-core/app/utils/routePath.ts +23 -0
  50. package/frontend-vue/layers/dms-core/i18n/locales/core-en-GB.json +3 -0
  51. package/frontend-vue/layers/dms-core/i18n/locales/core-fr-FR.json +3 -0
  52. package/frontend-vue/layers/dms-core/shared/types/runtime-config.d.ts +4 -1
  53. package/frontend-vue/layers/dms-layout/app/app.config.ts +9 -1
  54. package/frontend-vue/layers/dms-layout/app/components/navigation/CollapsedMenuItem.vue +0 -5
  55. package/frontend-vue/layers/dms-layout/app/components/profile/ProfileLanguage.vue +3 -23
  56. package/frontend-vue/layers/dms-layout/app/composables/profile/useUserLanguage.ts +33 -0
  57. package/frontend-vue/layers/dms-layout/app/plugins/command-palette-session.client.ts +2 -1
  58. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/registerDefaults.ts +31 -3
  59. package/frontend-vue/layers/dms-ui/app/build/composables/data-types/relationBadges.ts +36 -0
  60. package/frontend-vue/layers/dms-ui/app/build/types/tree.ts +5 -10
  61. package/frontend-vue/layers/dms-ui/app/components/Placeholder.vue +17 -5
  62. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +14 -9
  63. package/frontend-vue/layers/dms-ui/app/components/form/Form.vue +8 -5
  64. package/frontend-vue/layers/dms-ui/app/components/grid/Grid.vue +15 -5
  65. package/frontend-vue/layers/dms-ui/app/components/grid/GridRow.vue +7 -4
  66. package/frontend-vue/layers/dms-ui/app/components/grid/constants.ts +8 -1
  67. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +14 -9
  68. package/frontend-vue/layers/dms-ui/app/composables/chart/formatValue.ts +15 -0
  69. package/frontend-vue/layers/dms-ui/app/composables/chart/types.ts +4 -2
  70. package/frontend-vue/layers/dms-ui/app/composables/form/types/props.ts +2 -0
  71. package/frontend-vue/layers/dms-ui/app/composables/form/useForm.ts +53 -4
  72. package/frontend-vue/layers/dms-ui/app/composables/tree/useTree.ts +5 -7
  73. package/frontend-vue/layers/dms-ui/i18n/locales/ui-en-GB.json +1 -0
  74. package/frontend-vue/layers/dms-ui/i18n/locales/ui-fr-FR.json +1 -0
  75. package/frontend-vue/tests/api-error-title.test.ts +24 -0
  76. package/frontend-vue/tests/auth-middleware-error.test.ts +58 -0
  77. package/frontend-vue/tests/button-disabled-theme.test.ts +21 -0
  78. package/frontend-vue/tests/chart-absent-value.test.ts +78 -0
  79. package/frontend-vue/tests/form-actions.test.ts +27 -0
  80. package/frontend-vue/tests/form-submit-target.test.ts +28 -0
  81. package/frontend-vue/tests/menu-navigation.test.ts +39 -10
  82. package/frontend-vue/tests/relation-badges.test.ts +32 -0
  83. package/frontend-vue/tests/tree-without-source.test.ts +79 -0
  84. package/frontend-vue/tests/user-language.test.ts +58 -0
  85. package/package.json +1 -1
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const jsonwebtoken_1 = require("jsonwebtoken");
5
+ const auth_1 = require("../helpers/auth");
6
+ const http_1 = require("../helpers/http");
7
+ const HTTP_OK = 200;
8
+ const HTTP_UNAUTHORIZED = 401;
9
+ const SESSION_EXPIRED_ERROR = "error.session_expired";
10
+ const FOREIGN_SECRET = "not-the-dms-secret";
11
+ function rejectedToken() {
12
+ return (0, jsonwebtoken_1.sign)({ id: "missing-user", tenantId: "default", purpose: "access" }, FOREIGN_SECRET);
13
+ }
14
+ async function findPage(client, matches) {
15
+ const response = await client.get("/dms/sitelayout");
16
+ const route = Object.values(response.data.siteLayout.pages).find(matches);
17
+ if (!route)
18
+ throw new Error("no registered page matches");
19
+ return route.fullSlug;
20
+ }
21
+ function fetchPage(client, path) {
22
+ return client.get("/dms/page", { params: { path, shared: "false" } });
23
+ }
24
+ describe("[integration] dms page with a stale session", () => {
25
+ let anonymous;
26
+ let privatePath;
27
+ let publicPath;
28
+ before(async () => {
29
+ anonymous = (0, http_1.createClient)();
30
+ privatePath = await findPage(anonymous, (route) => route.hasAccess === false && !route.publicAccess);
31
+ publicPath = await findPage(anonymous, (route) => !!route.publicAccess);
32
+ });
33
+ it("keeps serving a denied private page to an anonymous visitor", async () => {
34
+ const response = await fetchPage(anonymous, privatePath);
35
+ (0, chai_1.expect)(response.status).to.equal(HTTP_OK);
36
+ (0, chai_1.expect)(response.data.route.hasAccess).to.equal(false);
37
+ });
38
+ it("answers 401 when a rejected bearer is what denies the page", async () => {
39
+ const response = await fetchPage((0, auth_1.authorizedClient)(rejectedToken()), privatePath);
40
+ (0, chai_1.expect)(response.status).to.equal(HTTP_UNAUTHORIZED);
41
+ (0, chai_1.expect)(response.data).to.equal(SESSION_EXPIRED_ERROR);
42
+ });
43
+ it("answers 401 for a bearer that is not a token at all", async () => {
44
+ const response = await fetchPage((0, auth_1.authorizedClient)("garbage"), privatePath);
45
+ (0, chai_1.expect)(response.status).to.equal(HTTP_UNAUTHORIZED);
46
+ });
47
+ it("still serves a public page to a rejected bearer", async () => {
48
+ const response = await fetchPage((0, auth_1.authorizedClient)(rejectedToken()), publicPath);
49
+ (0, chai_1.expect)(response.status).to.equal(HTTP_OK);
50
+ });
51
+ });
52
+ //# sourceMappingURL=page-session.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-session.test.js","sourceRoot":"","sources":["../../../src/test/integration/page-session.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,77 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const client_ip_1 = require("../../routes/auth/client-ip");
5
+ const SOCKET_ADDRESS = "10.0.0.9";
6
+ const CLIENT_ADDRESS = "109.132.199.8";
7
+ const FRONTEND_EGRESS = "195.201.71.66";
8
+ const CDN_EDGE = "104.23.166.64";
9
+ const STAGING_CHAIN = `${CLIENT_ADDRESS},${FRONTEND_EGRESS},${CDN_EDGE}`;
10
+ function authConfig(overrides) {
11
+ return {
12
+ jwtSecret: "",
13
+ emailValidationTokenLifetime: 0,
14
+ passwordRecoverTokenLifetime: 0,
15
+ accessTokenLifetime: 0,
16
+ refreshTokenLifetime: 0,
17
+ userSensitiveKeys: [],
18
+ mustValidateEmail: false,
19
+ ...overrides,
20
+ };
21
+ }
22
+ describe("[unit] resolveClientIp", () => {
23
+ it("records the socket peer and ignores the header without trusted proxies", () => {
24
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: SOCKET_ADDRESS, forwardedFor: STAGING_CHAIN }, 0)).to.equal(SOCKET_ADDRESS);
25
+ });
26
+ it("walks back one entry per trusted proxy from the right", () => {
27
+ const source = {
28
+ socketAddress: SOCKET_ADDRESS,
29
+ forwardedFor: STAGING_CHAIN,
30
+ };
31
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)(source, 1)).to.equal(CDN_EDGE);
32
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)(source, 2)).to.equal(FRONTEND_EGRESS);
33
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)(source, 3)).to.equal(CLIENT_ADDRESS);
34
+ });
35
+ it("never reaches the entries a client wrote ahead of the trusted ones", () => {
36
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({
37
+ socketAddress: SOCKET_ADDRESS,
38
+ forwardedFor: `6.6.6.6, 7.7.7.7, ${CLIENT_ADDRESS}`,
39
+ }, 1)).to.equal(CLIENT_ADDRESS);
40
+ });
41
+ it("yields the leftmost entry of a chain shorter than configured", () => {
42
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: SOCKET_ADDRESS, forwardedFor: CLIENT_ADDRESS }, 3)).to.equal(CLIENT_ADDRESS);
43
+ });
44
+ it("falls back to the socket peer without a header", () => {
45
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: SOCKET_ADDRESS, forwardedFor: undefined }, 2)).to.equal(SOCKET_ADDRESS);
46
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: SOCKET_ADDRESS, forwardedFor: " , " }, 2)).to.equal(SOCKET_ADDRESS);
47
+ });
48
+ it("returns an empty string when nothing is known", () => {
49
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: undefined, forwardedFor: undefined }, 1)).to.equal("");
50
+ });
51
+ it("keeps IPv6 addresses whole and trims the separators", () => {
52
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: "::1", forwardedFor: " 2001:db8::1 , fd00::2 " }, 2)).to.equal("2001:db8::1");
53
+ });
54
+ it("unmaps IPv4-mapped IPv6 addresses", () => {
55
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: "::ffff:127.0.0.1", forwardedFor: undefined }, 0)).to.equal("127.0.0.1");
56
+ (0, chai_1.expect)((0, client_ip_1.resolveClientIp)({ socketAddress: "::ffff:abcd", forwardedFor: "" }, 0)).to.equal("::ffff:abcd");
57
+ });
58
+ });
59
+ describe("[unit] trustedProxyCount", () => {
60
+ it("trusts no proxy by default", () => {
61
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({}))).to.equal(0);
62
+ });
63
+ it("reads trustedProxies", () => {
64
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({ trustedProxies: 3 }))).to.equal(3);
65
+ });
66
+ it("maps the deprecated oauth.trustProxy to one hop", () => {
67
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({ oauth: { trustProxy: true } }))).to.equal(1);
68
+ });
69
+ it("prefers trustedProxies over oauth.trustProxy", () => {
70
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({ trustedProxies: 0, oauth: { trustProxy: true } }))).to.equal(0);
71
+ });
72
+ it("ignores a value that is not a non-negative integer", () => {
73
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({ trustedProxies: -1 }))).to.equal(0);
74
+ (0, chai_1.expect)((0, client_ip_1.trustedProxyCount)(authConfig({ trustedProxies: 1.5 }))).to.equal(0);
75
+ });
76
+ });
77
+ //# sourceMappingURL=client-ip.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client-ip.test.js","sourceRoot":"","sources":["../../../src/test/unit/client-ip.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const block_types_1 = require("@antelopejs/interface-dms/base/block-types");
5
+ describe("[unit] interfaces/dms-base/form — its catalog entry", () => {
6
+ function entryBranches() {
7
+ const declared = (0, block_types_1.ListBlockTypes)().find((block) => block.type === "Form");
8
+ return declared?.config.fields?.items?.oneOf ?? [];
9
+ }
10
+ it("names both kinds of entry a form's fields can hold", () => {
11
+ (0, chai_1.expect)(entryBranches().map((branch) => branch.ui?.label)).to.deep.equal([
12
+ "Group",
13
+ "Field",
14
+ ]);
15
+ });
16
+ it("says a field's key and a group's can be derived from their label", () => {
17
+ const [group, field] = entryBranches();
18
+ (0, chai_1.expect)(field?.properties?.id?.ui?.derivedFrom).to.equal("label");
19
+ (0, chai_1.expect)(group?.properties?.id?.ui?.derivedFrom).to.equal("label");
20
+ });
21
+ it("says a field's default takes the field's own type", () => {
22
+ const [, field] = entryBranches();
23
+ (0, chai_1.expect)(field?.properties?.defaultValue?.ui?.typedBy).to.equal("type");
24
+ });
25
+ it("is placed showing its buttons, a setting of the advanced view", () => {
26
+ const config = (0, block_types_1.ListBlockTypes)().find((block) => block.type === "Form")?.config;
27
+ (0, chai_1.expect)(config?.showActions?.ui).to.include({
28
+ initial: true,
29
+ advanced: true,
30
+ });
31
+ });
32
+ it("leaves its addresses and methods to the advanced view", () => {
33
+ const config = (0, block_types_1.ListBlockTypes)().find((block) => block.type === "Form")?.config;
34
+ for (const key of [
35
+ "fetchUrl",
36
+ "fetchUrlMethod",
37
+ "submitUrl",
38
+ "submitUrlMethod",
39
+ ]) {
40
+ (0, chai_1.expect)(config?.[key]?.ui?.advanced, key).to.equal(true);
41
+ }
42
+ });
43
+ it("names what a group of fields is set up with", () => {
44
+ const [group] = entryBranches();
45
+ (0, chai_1.expect)(group?.properties?.label?.ui?.label).to.equal("Title");
46
+ (0, chai_1.expect)(group?.properties?.fields?.ui?.label).to.equal("Fields");
47
+ });
48
+ for (const type of ["Form", "ResourceForm"]) {
49
+ it(`puts the submit messages of a ${type} behind one switch`, () => {
50
+ const config = (0, block_types_1.ListBlockTypes)().find((block) => block.type === type)?.config;
51
+ (0, chai_1.expect)(config?.successMessage?.ui).to.include({
52
+ optIn: "Custom submit messages",
53
+ placeholder: "Data has been successfully saved",
54
+ });
55
+ (0, chai_1.expect)(config?.errorMessage?.ui).to.include({
56
+ optIn: "Custom submit messages",
57
+ placeholder: "An unknown error occurred",
58
+ });
59
+ });
60
+ }
61
+ });
62
+ //# sourceMappingURL=form-catalog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"form-catalog.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/form-catalog.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const block_types_1 = require("@antelopejs/interface-dms/base/block-types");
5
+ function periodSelectorConfig() {
6
+ const declared = (0, block_types_1.ListBlockTypes)().find((block) => block.type === "PeriodSelector");
7
+ (0, chai_1.expect)(declared, "PeriodSelector is declared").to.not.equal(undefined);
8
+ return declared.config;
9
+ }
10
+ describe("[unit] interfaces/dms-base/period-selector — its catalog entry", () => {
11
+ it("names the ranges a range label can be given for", () => {
12
+ const labels = periodSelectorConfig().presetLabels;
13
+ (0, chai_1.expect)(labels?.type).to.equal("record");
14
+ (0, chai_1.expect)(labels?.ui?.widget, "no longer a JSON box").to.equal(undefined);
15
+ (0, chai_1.expect)(labels?.keys?.enum).to.include("last-30-days");
16
+ (0, chai_1.expect)(labels?.keys?.ui?.valueLabels?.["ytd"]).to.equal("Year to date");
17
+ (0, chai_1.expect)(labels?.values?.type).to.equal("string");
18
+ });
19
+ it("names the comparisons a comparison label can be given for", () => {
20
+ const labels = periodSelectorConfig().comparisonLabels;
21
+ (0, chai_1.expect)(labels?.keys?.enum).to.deep.equal([
22
+ "none",
23
+ "previous-period",
24
+ "previous-year",
25
+ "custom",
26
+ ]);
27
+ (0, chai_1.expect)(labels?.keys?.ui?.valueLabels?.["previous-period"]).to.equal("vs previous period");
28
+ });
29
+ it("names the values of the pickers that choose a range", () => {
30
+ const config = periodSelectorConfig();
31
+ (0, chai_1.expect)(config.defaultPreset?.ui?.label, "its own hints still apply").to.equal("Default range");
32
+ (0, chai_1.expect)(config.defaultPreset?.ui?.valueLabels?.["last-7-days"]).to.equal("Last 7 days");
33
+ (0, chai_1.expect)(config.presets?.items?.ui?.valueLabels?.["today"]).to.equal("Today");
34
+ });
35
+ });
36
+ //# sourceMappingURL=period-selector-catalog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"period-selector-catalog.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/period-selector-catalog.test.ts"],"names":[],"mappings":";;AAAA,+BAA8B;AAC9B,4EAA4E;AAE5E,SAAS,oBAAoB;IAC3B,MAAM,QAAQ,GAAG,IAAA,4BAAc,GAAE,CAAC,IAAI,CACpC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,gBAAgB,CAC3C,CAAC;IACF,IAAA,aAAM,EAAC,QAAQ,EAAE,4BAA4B,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;IACvE,OAAO,QAAS,CAAC,MAAM,CAAC;AAC1B,CAAC;AAOD,QAAQ,CAAC,gEAAgE,EAAE,GAAG,EAAE;IAC9E,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC,YAAY,CAAC;QAEnD,IAAA,aAAM,EAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAA,aAAM,EAAC,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,sBAAsB,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACvE,IAAA,aAAM,EAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QACtD,IAAA,aAAM,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACxE,IAAA,aAAM,EAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC,gBAAgB,CAAC;QAEvD,IAAA,aAAM,EAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;YACvC,MAAM;YACN,iBAAiB;YACjB,eAAe;YACf,QAAQ;SACT,CAAC,CAAC;QACH,IAAA,aAAM,EAAC,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CACjE,oBAAoB,CACrB,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,oBAAoB,EAAE,CAAC;QAEtC,IAAA,aAAM,EACJ,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,KAAK,EAC/B,2BAA2B,CAC5B,CAAC,EAAE,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC5B,IAAA,aAAM,EAAC,MAAM,CAAC,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CACrE,aAAa,CACd,CAAC;QACF,IAAA,aAAM,EAAC,MAAM,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC9E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ const interface_api_1 = require("@antelopejs/interface-api");
13
+ const interface_data_api_1 = require("@antelopejs/interface-data-api");
14
+ const metadata_1 = require("@antelopejs/interface-data-api/metadata");
15
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
16
+ const chai_1 = require("chai");
17
+ const block_types_1 = require("@antelopejs/interface-dms/base/block-types");
18
+ const default_types_1 = require("@antelopejs/interface-dms/base/data-types/default-types");
19
+ const factory_1 = require("@antelopejs/interface-dms/base/table-view/factory");
20
+ const meta_1 = require("@antelopejs/interface-dms/base/table-view/meta");
21
+ const resource_form_1 = require("@antelopejs/interface-dms/base/table-view/resource-form");
22
+ const routes_1 = require("@antelopejs/interface-dms/base/table-view/routes");
23
+ const http_1 = require("@antelopejs/interface-dms/base/types/http");
24
+ const SCHEMA = "resource-form-test";
25
+ const TABLE = "tickets";
26
+ const LOCATION = "/resource-form-test";
27
+ let Ticket = class Ticket extends interface_database_decorators_1.Table {
28
+ };
29
+ __decorate([
30
+ (0, interface_database_decorators_1.Field)("string"),
31
+ __metadata("design:type", String)
32
+ ], Ticket.prototype, "title", void 0);
33
+ __decorate([
34
+ (0, interface_database_decorators_1.Field)("string"),
35
+ __metadata("design:type", String)
36
+ ], Ticket.prototype, "reference", void 0);
37
+ Ticket = __decorate([
38
+ (0, interface_database_decorators_1.RegisterTable)(TABLE, SCHEMA)
39
+ ], Ticket);
40
+ class TicketModel extends (0, interface_database_decorators_1.BasicDataModel)(Ticket, TABLE) {
41
+ }
42
+ let TicketAPI = class TicketAPI extends (0, interface_data_api_1.DataController)(Ticket, routes_1.TableViewRoutes.All, (0, interface_api_1.Controller)(LOCATION)) {
43
+ };
44
+ __decorate([
45
+ (0, metadata_1.ModelReference)(),
46
+ (0, interface_database_decorators_1.Model)(TicketModel),
47
+ __metadata("design:type", TicketModel)
48
+ ], TicketAPI.prototype, "model", void 0);
49
+ __decorate([
50
+ (0, meta_1.Column)({ name: "Title", type: new default_types_1.DefaultDataTypes.StringType() }),
51
+ (0, metadata_1.Access)(metadata_1.AccessMode.ReadWrite),
52
+ __metadata("design:type", String)
53
+ ], TicketAPI.prototype, "title", void 0);
54
+ __decorate([
55
+ (0, meta_1.Column)({ name: "Reference", type: new default_types_1.DefaultDataTypes.StringType() }),
56
+ (0, metadata_1.Access)(metadata_1.AccessMode.ReadOnly),
57
+ __metadata("design:type", String)
58
+ ], TicketAPI.prototype, "reference", void 0);
59
+ TicketAPI = __decorate([
60
+ (0, interface_data_api_1.RegisterDataController)()
61
+ ], TicketAPI);
62
+ function optionsOf(builder) {
63
+ return builder.serializeSync().options;
64
+ }
65
+ function fieldIds(options) {
66
+ return options.fields.map((field) => field.id);
67
+ }
68
+ describe("[unit] interfaces/dms-base/resource-form — a form derived from its table", () => {
69
+ it("is the form a TableView opens for the mode", () => {
70
+ const table = (0, factory_1.TableView)(TicketAPI).serializeSync()
71
+ .options;
72
+ const created = optionsOf((0, resource_form_1.ResourceForm)(TicketAPI, { mode: "new" }));
73
+ (0, chai_1.expect)(created.submitUrl).to.equal(`${LOCATION}/new`);
74
+ (0, chai_1.expect)(created.submitUrlMethod).to.equal(http_1.HttpMethod.post);
75
+ const opened = table.formComponents.new?.options;
76
+ (0, chai_1.expect)(created.fetchUrl).to.equal(opened.fetchUrl);
77
+ (0, chai_1.expect)(fieldIds(created)).to.deep.equal(fieldIds(opened));
78
+ });
79
+ it("opens the row the page's query string names, in edit and view", () => {
80
+ const edited = optionsOf((0, resource_form_1.ResourceForm)(TicketAPI, { mode: "edit" }));
81
+ const shown = optionsOf((0, resource_form_1.ResourceForm)(TicketAPI, { mode: "view" }));
82
+ (0, chai_1.expect)(edited.fetchUrl).to.match(new RegExp(`^${LOCATION}/get\\?id=\\{\\{query\\.id\\}\\}&`));
83
+ (0, chai_1.expect)(edited.submitUrl).to.equal(`${LOCATION}/edit?id={{query.id}}`);
84
+ (0, chai_1.expect)(edited.submitUrlMethod).to.equal(http_1.HttpMethod.put);
85
+ (0, chai_1.expect)(shown.fetchUrl).to.equal(`${LOCATION}/get?id={{query.id}}`);
86
+ });
87
+ it("keeps the TableView's own pages on their :id segment", () => {
88
+ const table = (0, factory_1.TableView)(TicketAPI).serializeSync()
89
+ .options;
90
+ const opened = table.formComponents.edit?.options;
91
+ (0, chai_1.expect)(opened.submitUrl).to.equal(`${LOCATION}/edit?id={{params.id}}`);
92
+ });
93
+ it("reads a row without offering anywhere to send it", () => {
94
+ const shown = optionsOf((0, resource_form_1.ResourceForm)(TicketAPI, { mode: "view" }));
95
+ (0, chai_1.expect)(shown.submitUrl).to.equal(undefined);
96
+ (0, chai_1.expect)(shown.fields.every((field) => field.disabled)).to.equal(true);
97
+ });
98
+ it("carries its own wording and the row it was pointed at", () => {
99
+ const edited = optionsOf((0, resource_form_1.ResourceForm)(TicketAPI, {
100
+ mode: "edit",
101
+ title: "Edit the ticket",
102
+ submitLabel: "Save the ticket",
103
+ rowId: "{{params.ticket}}",
104
+ }));
105
+ (0, chai_1.expect)(edited.title).to.equal("Edit the ticket");
106
+ (0, chai_1.expect)(edited.submitLabel).to.equal("Save the ticket");
107
+ (0, chai_1.expect)(edited.submitUrl).to.equal(`${LOCATION}/edit?id={{params.ticket}}`);
108
+ (0, chai_1.expect)(edited, "the row token is the form's to resolve, not an option").to.not.have.property("rowId");
109
+ });
110
+ it("is declared as a block over a table, picked by mode", () => {
111
+ const declared = (0, block_types_1.ListBlockTypes)().find((block) => block.type === "ResourceForm");
112
+ (0, chai_1.expect)(declared?.controllerArg).to.equal(true);
113
+ (0, chai_1.expect)(declared?.config.mode?.enum).to.deep.equal(["new", "edit", "view"]);
114
+ (0, chai_1.expect)(declared?.config.fields, "fields come from the table").to.equal(undefined);
115
+ });
116
+ });
117
+ //# sourceMappingURL=resource-form.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-form.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/resource-form.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const chai_1 = require("chai");
4
+ const block_types_1 = require("@antelopejs/interface-dms/base/block-types");
5
+ function configOf(type) {
6
+ const declared = (0, block_types_1.ListBlockTypes)().find((block) => block.type === type);
7
+ (0, chai_1.expect)(declared, `${type} is declared`).to.not.equal(undefined);
8
+ return declared.config;
9
+ }
10
+ describe("[unit] interfaces/dms-base/table-view — its row actions in the catalog", () => {
11
+ const actions = () => configOf("TableView").rowActions?.properties ?? {};
12
+ it("says the actions a table offers by itself are on", () => {
13
+ for (const action of ["add", "edit", "delete", "duplicate", "copyLink"]) {
14
+ (0, chai_1.expect)(actions()[action]?.default, action).to.equal(true);
15
+ }
16
+ });
17
+ it("says when an action depends on another one", () => {
18
+ (0, chai_1.expect)(actions().details?.default).to.equal(undefined);
19
+ (0, chai_1.expect)(actions().details?.description).to.match(/editing is off/);
20
+ (0, chai_1.expect)(actions().archive?.default).to.equal(true);
21
+ (0, chai_1.expect)(actions().archive?.description).to.match(/ghost delete/);
22
+ });
23
+ it("leaves row selection off until it is turned on", () => {
24
+ (0, chai_1.expect)(actions().hasSelection?.default).to.equal(undefined);
25
+ });
26
+ });
27
+ describe("[unit] interfaces/dms-base/chart-card — the chart it wraps, in the catalog", () => {
28
+ it("names the options of its chart it supplies itself", () => {
29
+ const supplied = configOf("ChartCard").chart?.ui?.supplies;
30
+ (0, chai_1.expect)(supplied).to.include.members([
31
+ "fetchUrl",
32
+ "fetchUrlMethod",
33
+ "periodScope",
34
+ "title",
35
+ ]);
36
+ });
37
+ it("keeps a chart's backend-only settings for the advanced view", () => {
38
+ const chart = configOf("ChartLine");
39
+ (0, chai_1.expect)(chart.realtimeTopic?.ui?.advanced).to.equal(true);
40
+ (0, chai_1.expect)(chart.syncGroup?.ui?.advanced).to.equal(true);
41
+ (0, chai_1.expect)(chart.annotations?.ui?.advanced).to.equal(true);
42
+ (0, chai_1.expect)(chart.showGrid?.ui?.advanced, "a setting anyone reads").to.equal(undefined);
43
+ });
44
+ });
45
+ describe("[unit] interfaces/dms-base/chart-card — the switches it draws on", () => {
46
+ it("says a card shows its variation and its legend", () => {
47
+ const card = configOf("ChartCard");
48
+ (0, chai_1.expect)(card.showDelta?.default).to.equal(true);
49
+ (0, chai_1.expect)(card.showLegend?.default).to.equal(true);
50
+ });
51
+ it("says a chart shows what it draws unless told not to", () => {
52
+ const chart = configOf("ChartColumn");
53
+ for (const option of ["showTooltip", "showGrid", "roundedCorners"]) {
54
+ (0, chai_1.expect)(chart[option]?.default, option).to.equal(true);
55
+ }
56
+ (0, chai_1.expect)(configOf("ChartLine").smooth?.default).to.equal(true);
57
+ });
58
+ it("leaves what it only does when asked unset", () => {
59
+ (0, chai_1.expect)(configOf("ChartColumn").stacked?.default).to.equal(undefined);
60
+ });
61
+ });
62
+ //# sourceMappingURL=table-and-card-catalog.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-and-card-catalog.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-and-card-catalog.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ const interface_api_1 = require("@antelopejs/interface-api");
10
+ const interface_data_api_1 = require("@antelopejs/interface-data-api");
11
+ const interface_database_decorators_1 = require("@antelopejs/interface-database-decorators");
12
+ const chai_1 = require("chai");
13
+ const constants_1 = require("@antelopejs/interface-dms/constants");
14
+ const table_view_1 = require("@antelopejs/interface-dms/base/table-view");
15
+ const logging_1 = require("../../../helpers/logging");
16
+ const TABLE = "tab-count-warning-rows";
17
+ const MISSING_ROUTE = "count/batch";
18
+ const TABS = [
19
+ {
20
+ id: "open",
21
+ label: "Open",
22
+ filters: [{ accessorKey: "status", value: "open", mode: "is" }],
23
+ },
24
+ ];
25
+ let Row = class Row extends interface_database_decorators_1.Table {
26
+ };
27
+ Row = __decorate([
28
+ (0, interface_database_decorators_1.RegisterTable)(TABLE, constants_1.CORE_SCHEMA_NAME)
29
+ ], Row);
30
+ let CountOnlyAPI = class CountOnlyAPI extends (0, interface_data_api_1.DataController)(Row, { list: table_view_1.TableViewRoutes.List, count: table_view_1.TableViewRoutes.Count }, (0, interface_api_1.Controller)("/api/tab-count-warning/count-only")) {
31
+ };
32
+ CountOnlyAPI = __decorate([
33
+ (0, interface_data_api_1.RegisterDataController)()
34
+ ], CountOnlyAPI);
35
+ let RepeatedAPI = class RepeatedAPI extends (0, interface_data_api_1.DataController)(Row, { list: table_view_1.TableViewRoutes.List }, (0, interface_api_1.Controller)("/api/tab-count-warning/repeated")) {
36
+ };
37
+ RepeatedAPI = __decorate([
38
+ (0, interface_data_api_1.RegisterDataController)()
39
+ ], RepeatedAPI);
40
+ let BatchAPI = class BatchAPI extends (0, interface_data_api_1.DataController)(Row, { list: table_view_1.TableViewRoutes.List, countBatch: table_view_1.TableViewRoutes.CountBatch }, (0, interface_api_1.Controller)("/api/tab-count-warning/batch")) {
41
+ };
42
+ BatchAPI = __decorate([
43
+ (0, interface_data_api_1.RegisterDataController)()
44
+ ], BatchAPI);
45
+ let RenamedBatchAPI = class RenamedBatchAPI extends (0, interface_data_api_1.DataController)(Row, { list: table_view_1.TableViewRoutes.List, tabCounters: table_view_1.TableViewRoutes.CountBatch }, (0, interface_api_1.Controller)("/api/tab-count-warning/renamed")) {
46
+ };
47
+ RenamedBatchAPI = __decorate([
48
+ (0, interface_data_api_1.RegisterDataController)()
49
+ ], RenamedBatchAPI);
50
+ let NoTabsAPI = class NoTabsAPI extends (0, interface_data_api_1.DataController)(Row, { list: table_view_1.TableViewRoutes.List }, (0, interface_api_1.Controller)("/api/tab-count-warning/no-tabs")) {
51
+ };
52
+ NoTabsAPI = __decorate([
53
+ (0, interface_data_api_1.RegisterDataController)()
54
+ ], NoTabsAPI);
55
+ function countBatchWarnings(register) {
56
+ const captured = (0, logging_1.captureWarnings)();
57
+ try {
58
+ register();
59
+ }
60
+ finally {
61
+ captured.restore();
62
+ }
63
+ return captured.messages.filter((message) => message.includes(MISSING_ROUTE));
64
+ }
65
+ describe("[unit] interfaces/dms-base/table-view — filter tabs require countBatch", () => {
66
+ it("warns when a table with tabs is mounted on a controller without countBatch", () => {
67
+ const warnings = countBatchWarnings(() => (0, table_view_1.TableView)(CountOnlyAPI, { tabs: TABS, realtime: false }));
68
+ (0, chai_1.expect)(warnings).to.have.length(1);
69
+ (0, chai_1.expect)(warnings[0]).to.include("CountOnlyAPI");
70
+ (0, chai_1.expect)(warnings[0]).to.include("/api/tab-count-warning/count-only");
71
+ (0, chai_1.expect)(warnings[0]).to.include("TableViewRoutes.CountBatch");
72
+ });
73
+ it("warns once per controller however many tables mount it", () => {
74
+ const warnings = countBatchWarnings(() => {
75
+ (0, table_view_1.TableView)(RepeatedAPI, { tabs: TABS, realtime: false });
76
+ (0, table_view_1.TableView)(RepeatedAPI, { tabs: TABS, realtime: false });
77
+ });
78
+ (0, chai_1.expect)(warnings).to.have.length(1);
79
+ });
80
+ it("stays silent when the controller mounts countBatch", () => {
81
+ const warnings = countBatchWarnings(() => (0, table_view_1.TableView)(BatchAPI, { tabs: TABS, realtime: false }));
82
+ (0, chai_1.expect)(warnings).to.be.empty;
83
+ });
84
+ it("stays silent when countBatch is mounted under another key", () => {
85
+ const warnings = countBatchWarnings(() => (0, table_view_1.TableView)(RenamedBatchAPI, { tabs: TABS, realtime: false }));
86
+ (0, chai_1.expect)(warnings).to.be.empty;
87
+ });
88
+ it("stays silent when the table declares no tabs", () => {
89
+ const warnings = countBatchWarnings(() => {
90
+ (0, table_view_1.TableView)(NoTabsAPI, { realtime: false });
91
+ (0, table_view_1.TableView)(NoTabsAPI, { tabs: [], realtime: false });
92
+ });
93
+ (0, chai_1.expect)(warnings).to.be.empty;
94
+ });
95
+ });
96
+ //# sourceMappingURL=table-view-tab-count-warning.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-view-tab-count-warning.test.js","sourceRoot":"","sources":["../../../../../src/test/unit/interfaces/dms-base/table-view-tab-count-warning.test.ts"],"names":[],"mappings":";;;;;;;;AAAA,6DAAuD;AACvD,uEAGwC;AACxC,6FAGmD;AACnD,+BAA8B;AAC9B,mEAAuE;AACvE,0EAImD;AACnD,sDAA2D;AAE3D,MAAM,KAAK,GAAG,wBAAwB,CAAC;AACvC,MAAM,aAAa,GAAG,aAAa,CAAC;AAEpC,MAAM,IAAI,GAAmB;IAC3B;QACE,EAAE,EAAE,MAAM;QACV,KAAK,EAAE,MAAM;QACb,OAAO,EAAE,CAAC,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;KAChE;CACF,CAAC;AAGF,IAAM,GAAG,GAAT,MAAM,GAAI,SAAQ,qCAAK;CAAG,CAAA;AAApB,GAAG;IADR,IAAA,6CAAa,EAAC,KAAK,EAAE,4BAAgB,CAAC;GACjC,GAAG,CAAiB;AAG1B,IAAM,YAAY,GAAlB,MAAM,YAAa,SAAQ,IAAA,mCAAc,EACvC,GAAG,EACH,EAAE,IAAI,EAAE,4BAAe,CAAC,IAAI,EAAE,KAAK,EAAE,4BAAe,CAAC,KAAK,EAAE,EAC5D,IAAA,0BAAU,EAAC,mCAAmC,CAAC,CAChD;CAAG,CAAA;AAJE,YAAY;IADjB,IAAA,2CAAsB,GAAE;GACnB,YAAY,CAId;AAGJ,IAAM,WAAW,GAAjB,MAAM,WAAY,SAAQ,IAAA,mCAAc,EACtC,GAAG,EACH,EAAE,IAAI,EAAE,4BAAe,CAAC,IAAI,EAAE,EAC9B,IAAA,0BAAU,EAAC,iCAAiC,CAAC,CAC9C;CAAG,CAAA;AAJE,WAAW;IADhB,IAAA,2CAAsB,GAAE;GACnB,WAAW,CAIb;AAGJ,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,IAAA,mCAAc,EACnC,GAAG,EACH,EAAE,IAAI,EAAE,4BAAe,CAAC,IAAI,EAAE,UAAU,EAAE,4BAAe,CAAC,UAAU,EAAE,EACtE,IAAA,0BAAU,EAAC,8BAA8B,CAAC,CAC3C;CAAG,CAAA;AAJE,QAAQ;IADb,IAAA,2CAAsB,GAAE;GACnB,QAAQ,CAIV;AAIJ,IAAM,eAAe,GAArB,MAAM,eAAgB,SAAQ,IAAA,mCAAc,EAC1C,GAAG,EACH,EAAE,IAAI,EAAE,4BAAe,CAAC,IAAI,EAAE,WAAW,EAAE,4BAAe,CAAC,UAAU,EAAE,EACvE,IAAA,0BAAU,EAAC,gCAAgC,CAAC,CAC7C;CAAG,CAAA;AAJE,eAAe;IADpB,IAAA,2CAAsB,GAAE;GACnB,eAAe,CAIjB;AAGJ,IAAM,SAAS,GAAf,MAAM,SAAU,SAAQ,IAAA,mCAAc,EACpC,GAAG,EACH,EAAE,IAAI,EAAE,4BAAe,CAAC,IAAI,EAAE,EAC9B,IAAA,0BAAU,EAAC,gCAAgC,CAAC,CAC7C;CAAG,CAAA;AAJE,SAAS;IADd,IAAA,2CAAsB,GAAE;GACnB,SAAS,CAIX;AAEJ,SAAS,kBAAkB,CAAC,QAAoB;IAC9C,MAAM,QAAQ,GAAG,IAAA,yBAAe,GAAE,CAAC;IACnC,IAAI,CAAC;QACH,QAAQ,EAAE,CAAC;IACb,CAAC;YAAS,CAAC;QACT,QAAQ,CAAC,OAAO,EAAE,CAAC;IACrB,CAAC;IACD,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;AAChF,CAAC;AAED,QAAQ,CAAC,wEAAwE,EAAE,GAAG,EAAE;IACtF,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,CACvC,IAAA,sBAAS,EAAC,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CACzD,CAAC;QACF,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnC,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC/C,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;QACpE,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,4BAA4B,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE;YACvC,IAAA,sBAAS,EAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YACxD,IAAA,sBAAS,EAAC,WAAW,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1D,CAAC,CAAC,CAAC;QACH,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,CACvC,IAAA,sBAAS,EAAC,QAAQ,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CACrD,CAAC;QACF,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,GAAG,EAAE;QACnE,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE,CACvC,IAAA,sBAAS,EAAC,eAAe,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAC5D,CAAC;QACF,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC/B,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,GAAG,EAAE;YACvC,IAAA,sBAAS,EAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;YAC1C,IAAA,sBAAS,EAAC,SAAS,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,IAAA,aAAM,EAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;IAC/B,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -72,8 +72,11 @@ async function isPublicAccessRoute(to: ReturnType<typeof useDmsRoute>) {
72
72
  export default defineDmsMiddleware(async (to) => {
73
73
  if (to.matched.length === 0) return;
74
74
 
75
- const error = useError();
76
- if (error.value) throw showError(error.value);
75
+ // An error the page already raised (a failed `validation`, a missing page)
76
+ // is committed and rendered with its own status. Re-throwing it here would
77
+ // reject the pending navigation the SSR render awaits, turning that 404 into
78
+ // a 500 fallback render.
79
+ if (useError().value) return abortNavigation();
77
80
 
78
81
  const options = to.meta.auth as MiddlewareMeta | undefined;
79
82
  if (!options) return;