@antelopejs/dms 0.4.5 → 0.4.6

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 (158) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/hooks/invite-extensions.js +2 -2
  3. package/dist/hooks/invite-extensions.js.map +1 -1
  4. package/dist/implementations/dms/layout-banners.d.ts +18 -0
  5. package/dist/implementations/dms/layout-banners.js +60 -0
  6. package/dist/implementations/dms/layout-banners.js.map +1 -0
  7. package/dist/implementations/dms/page.d.ts +2 -0
  8. package/dist/implementations/dms/page.js +82 -27
  9. package/dist/implementations/dms/page.js.map +1 -1
  10. package/dist/implementations/dms/quick-actions.d.ts +5 -0
  11. package/dist/implementations/dms/quick-actions.js.map +1 -1
  12. package/dist/implementations/dms/resolver-timeout.d.ts +1 -0
  13. package/dist/implementations/dms/resolver-timeout.js +13 -0
  14. package/dist/implementations/dms/resolver-timeout.js.map +1 -0
  15. package/dist/implementations/dms/saas-mode.d.ts +8 -0
  16. package/dist/implementations/dms/saas-mode.js +20 -0
  17. package/dist/implementations/dms/saas-mode.js.map +1 -0
  18. package/dist/implementations/dms-auth/index.d.ts +2 -1
  19. package/dist/implementations/dms-auth/index.js +19 -8
  20. package/dist/implementations/dms-auth/index.js.map +1 -1
  21. package/dist/implementations/dms-html-render/service-jwt.js +2 -1
  22. package/dist/implementations/dms-html-render/service-jwt.js.map +1 -1
  23. package/dist/index.js +2 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/pages/settings/users/index.d.ts +1 -0
  26. package/dist/pages/settings/users/index.js +1 -0
  27. package/dist/pages/settings/users/index.js.map +1 -1
  28. package/dist/pages/settings/users/invite-extension-routes.d.ts +4 -0
  29. package/dist/pages/settings/users/invite-extension-routes.js +57 -0
  30. package/dist/pages/settings/users/invite-extension-routes.js.map +1 -0
  31. package/dist/pages/settings/users/invites.d.ts +2 -1
  32. package/dist/pages/settings/users/invites.js +17 -5
  33. package/dist/pages/settings/users/invites.js.map +1 -1
  34. package/dist/pages/settings/users/members.d.ts +4 -1
  35. package/dist/pages/settings/users/members.js +10 -6
  36. package/dist/pages/settings/users/members.js.map +1 -1
  37. package/dist/pages/settings/users/notifications.js +1 -1
  38. package/dist/pages/settings/users/notifications.js.map +1 -1
  39. package/dist/pages/settings/users/quick-actions.d.ts +1 -0
  40. package/dist/pages/settings/users/quick-actions.js +22 -0
  41. package/dist/pages/settings/users/quick-actions.js.map +1 -0
  42. package/dist/routes/auth/signup.d.ts +2 -0
  43. package/dist/routes/auth/signup.js +7 -2
  44. package/dist/routes/auth/signup.js.map +1 -1
  45. package/dist/test/integration/invite-extension-edit.test.d.ts +1 -0
  46. package/dist/test/integration/invite-extension-edit.test.js +122 -0
  47. package/dist/test/integration/invite-extension-edit.test.js.map +1 -0
  48. package/dist/test/integration/saas-mode-ownership.test.d.ts +1 -0
  49. package/dist/test/integration/saas-mode-ownership.test.js +81 -0
  50. package/dist/test/integration/saas-mode-ownership.test.js.map +1 -0
  51. package/dist/test/integration/tenant-lifecycle.test.js +38 -0
  52. package/dist/test/integration/tenant-lifecycle.test.js.map +1 -1
  53. package/dist/test/unit/implementations/dms/layout-banners.test.d.ts +1 -0
  54. package/dist/test/unit/implementations/dms/layout-banners.test.js +217 -0
  55. package/dist/test/unit/implementations/dms/layout-banners.test.js.map +1 -0
  56. package/dist/test/unit/implementations/dms/quick-actions-button.test.d.ts +1 -0
  57. package/dist/test/unit/implementations/dms/quick-actions-button.test.js +220 -0
  58. package/dist/test/unit/implementations/dms/quick-actions-button.test.js.map +1 -0
  59. package/dist/test/unit/implementations/dms-html-render/generate-html.test.js +1 -1
  60. package/dist/test/unit/implementations/dms-html-render/generate-html.test.js.map +1 -1
  61. package/dist/test/unit/implementations/dms-html-render/service-jwt.test.d.ts +1 -0
  62. package/dist/test/unit/implementations/dms-html-render/service-jwt.test.js +37 -0
  63. package/dist/test/unit/implementations/dms-html-render/service-jwt.test.js.map +1 -0
  64. package/dist/test/unit/interfaces/dms/invite-extension.test.js +138 -12
  65. package/dist/test/unit/interfaces/dms/invite-extension.test.js.map +1 -1
  66. package/dist/test/unit/interfaces/dms/saas-mode.test.d.ts +1 -0
  67. package/dist/test/unit/interfaces/dms/saas-mode.test.js +42 -0
  68. package/dist/test/unit/interfaces/dms/saas-mode.test.js.map +1 -0
  69. package/dist/test/unit/interfaces/dms/tenant-invite-email.test.d.ts +1 -0
  70. package/dist/test/unit/interfaces/dms/tenant-invite-email.test.js +53 -0
  71. package/dist/test/unit/interfaces/dms/tenant-invite-email.test.js.map +1 -0
  72. package/dist/test/unit/interfaces/dms-base/table-view-form-slots.test.d.ts +1 -0
  73. package/dist/test/unit/interfaces/dms-base/table-view-form-slots.test.js +80 -0
  74. package/dist/test/unit/interfaces/dms-base/table-view-form-slots.test.js.map +1 -0
  75. package/dist/test/unit/pages/settings/invite-member-quick-action.test.d.ts +1 -0
  76. package/dist/test/unit/pages/settings/invite-member-quick-action.test.js +104 -0
  77. package/dist/test/unit/pages/settings/invite-member-quick-action.test.js.map +1 -0
  78. package/dist/test/unit/pages/settings/notifications-access-gate.test.d.ts +1 -0
  79. package/dist/test/unit/pages/settings/notifications-access-gate.test.js +78 -0
  80. package/dist/test/unit/pages/settings/notifications-access-gate.test.js.map +1 -0
  81. package/dist/test/unit/signup-account-guard.test.js +20 -2
  82. package/dist/test/unit/signup-account-guard.test.js.map +1 -1
  83. package/dist/test/unit/utils/admin-invite-email.test.d.ts +1 -0
  84. package/dist/test/unit/utils/admin-invite-email.test.js +69 -0
  85. package/dist/test/unit/utils/admin-invite-email.test.js.map +1 -0
  86. package/dist/utils/admin-invite-email.d.ts +14 -0
  87. package/dist/utils/admin-invite-email.js +51 -0
  88. package/dist/utils/admin-invite-email.js.map +1 -0
  89. package/dist/utils/index.d.ts +0 -1
  90. package/dist/utils/index.js +0 -1
  91. package/dist/utils/index.js.map +1 -1
  92. package/dist/validation/auth.schema.d.ts +3 -3
  93. package/dist/validation/auth.schema.js +1 -1
  94. package/dist/validation/auth.schema.js.map +1 -1
  95. package/frontend-vue/layers/dms-auth/app/custom-pages/auth/signup.vue +37 -8
  96. package/frontend-vue/layers/dms-auth/i18n/locales/auth-en-GB.json +3 -1
  97. package/frontend-vue/layers/dms-auth/i18n/locales/auth-fr-FR.json +3 -1
  98. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardBanners.vue +50 -0
  99. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardHeader.vue +16 -13
  100. package/frontend-vue/layers/dms-layout/app/build/components/layout/DashboardSidebar.vue +2 -2
  101. package/frontend-vue/layers/dms-layout/app/build/components/notification/NotificationPopover.vue +11 -5
  102. package/frontend-vue/layers/dms-layout/app/build/components/notification/widgetRequest.ts +20 -0
  103. package/frontend-vue/layers/dms-layout/app/composables/layout/useLayoutBanners.ts +59 -0
  104. package/frontend-vue/layers/dms-layout/app/composables/page/useQuickActions.ts +15 -2
  105. package/frontend-vue/layers/dms-layout/app/custom-layouts/DefaultLayout.vue +2 -0
  106. package/frontend-vue/layers/dms-layout/app/emails/EmailAdminInvite.vue +54 -9
  107. package/frontend-vue/layers/dms-layout/app/error.vue +17 -2
  108. package/frontend-vue/layers/dms-layout/app/types/page.ts +22 -0
  109. package/frontend-vue/layers/dms-layout/app/utils/breadcrumb.ts +48 -0
  110. package/frontend-vue/layers/dms-layout/app/utils/favorites.ts +94 -0
  111. package/frontend-vue/layers/dms-layout/i18n/locales/layout-en-GB.json +21 -2
  112. package/frontend-vue/layers/dms-layout/i18n/locales/layout-fr-FR.json +21 -2
  113. package/frontend-vue/layers/dms-onboarding/app/composables/onboarding/index.ts +1 -1
  114. package/frontend-vue/layers/dms-onboarding/app/composables/onboarding/{useOnboardingMiddleware.ts → useOnboarding.ts} +0 -12
  115. package/frontend-vue/layers/dms-onboarding/app/custom-pages/onboarding.vue +4 -1
  116. package/frontend-vue/layers/dms-onboarding/app/middleware/onboarding.global.ts +21 -4
  117. package/frontend-vue/layers/dms-ui/app/build/components/containers/drawer/DynamicDrawer.vue +13 -3
  118. package/frontend-vue/layers/dms-ui/app/build/components/containers/modal/DynamicModal.vue +13 -3
  119. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/useTableViewConfig.ts +2 -7
  120. package/frontend-vue/layers/dms-ui/app/build/composables/table-view/utils/columnVisibility.ts +13 -0
  121. package/frontend-vue/layers/dms-ui/app/components/PasswordStrength.vue +1 -1
  122. package/frontend-vue/layers/dms-ui/app/components/activity/ActivityItem.vue +1 -1
  123. package/frontend-vue/layers/dms-ui/app/components/banner/Banner.vue +1 -1
  124. package/frontend-vue/layers/dms-ui/app/components/card/NavCard.vue +2 -2
  125. package/frontend-vue/layers/dms-ui/app/components/chart/Chart.vue +6 -16
  126. package/frontend-vue/layers/dms-ui/app/components/chart/ChartCard.vue +2 -2
  127. package/frontend-vue/layers/dms-ui/app/components/chart/internal/TrendBadge.vue +1 -1
  128. package/frontend-vue/layers/dms-ui/app/components/copy/CopyButton.vue +1 -1
  129. package/frontend-vue/layers/dms-ui/app/components/kpi/KpiCard.vue +3 -3
  130. package/frontend-vue/layers/dms-ui/app/components/master-detail/MasterDetail.vue +5 -1
  131. package/frontend-vue/layers/dms-ui/app/components/segmented/Segmented.vue +1 -1
  132. package/frontend-vue/layers/dms-ui/app/components/status/StatusSummary.vue +1 -1
  133. package/frontend-vue/layers/dms-ui/app/components/table-view/TableView.vue +33 -10
  134. package/frontend-vue/layers/dms-ui/app/composables/chart/donutRecords.ts +26 -0
  135. package/frontend-vue/layers/dms-ui/app/composables/tab/types/props.ts +4 -2
  136. package/frontend-vue/layers/dms-ui/app/composables/tab/useTab.ts +3 -3
  137. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/column.ts +1 -1
  138. package/frontend-vue/layers/dms-ui/app/composables/table-view/types/custom-button.ts +2 -0
  139. package/frontend-vue/layers/dms-ui/app/types/quick-actions.ts +38 -3
  140. package/frontend-vue/tests/admin-invite-email.test.ts +86 -0
  141. package/frontend-vue/tests/breadcrumb-target.test.ts +50 -0
  142. package/frontend-vue/tests/chart-nested-donut.test.ts +97 -0
  143. package/frontend-vue/tests/error-page-message.test.ts +83 -0
  144. package/frontend-vue/tests/favorite-page.test.ts +104 -0
  145. package/frontend-vue/tests/icon-aria-hidden.test.ts +29 -0
  146. package/frontend-vue/tests/layout-banners.test.ts +224 -0
  147. package/frontend-vue/tests/notification-popover-errors.test.ts +147 -0
  148. package/frontend-vue/tests/onboarding-middleware.test.ts +103 -0
  149. package/frontend-vue/tests/password-strength-meter.test.ts +33 -0
  150. package/frontend-vue/tests/quick-action-intent.test.ts +74 -0
  151. package/frontend-vue/tests/quick-actions.test.ts +23 -0
  152. package/frontend-vue/tests/signup-invitation-link.test.ts +126 -0
  153. package/frontend-vue/tests/skeleton-paragraph.test.ts +30 -0
  154. package/frontend-vue/tests/tab-without-component-id.test.ts +51 -0
  155. package/frontend-vue/tests/table-column-visibility.test.ts +20 -0
  156. package/frontend-vue/tests/vue-inventory.test.ts +1 -1
  157. package/package.json +2 -2
  158. package/skills/dms/REFERENCE.md +1 -1
@@ -0,0 +1,126 @@
1
+ // @vitest-environment jsdom
2
+ import { afterEach, beforeEach, expect, it, vi } from "vitest";
3
+ import {
4
+ computed,
5
+ createApp,
6
+ defineComponent,
7
+ h,
8
+ reactive,
9
+ ref,
10
+ type App,
11
+ } from "vue";
12
+ import * as z from "zod";
13
+ import SignupPage from "../layers/dms-auth/app/custom-pages/auth/signup.vue";
14
+
15
+ const route = reactive<{ query: Record<string, unknown> }>({ query: {} });
16
+ let app: App;
17
+ let host: HTMLDivElement;
18
+ const locale = ref("en");
19
+ const setLocale = vi.fn(async (code: string) => {
20
+ locale.value = code;
21
+ });
22
+
23
+ const Passthrough = defineComponent({
24
+ inheritAttrs: false,
25
+ setup:
26
+ (_, { attrs, slots }) =>
27
+ () =>
28
+ h("div", { "data-testid": attrs["data-testid"] }, slots.default?.()),
29
+ });
30
+
31
+ const LinkButton = defineComponent({
32
+ props: { label: String, to: String },
33
+ setup: (props) => () => h("a", { href: props.to }, props.label),
34
+ });
35
+
36
+ function installRuntime() {
37
+ Object.entries({ computed, ref, reactive }).forEach(([key, value]) =>
38
+ vi.stubGlobal(key, value),
39
+ );
40
+ vi.stubGlobal("useI18n", () => ({
41
+ locale,
42
+ locales: ref([{ code: "en" }, { code: "fr" }]),
43
+ setLocale,
44
+ }));
45
+ vi.stubGlobal("useDmsRuntimeConfig", () => ({
46
+ public: { dms: { mustValidateEmail: false } },
47
+ }));
48
+ vi.stubGlobal("useHomepage", () => "/");
49
+ vi.stubGlobal("useDmsRoute", () => route);
50
+ vi.stubGlobal("passwordSchema", z.string());
51
+ vi.stubGlobal("usePasswordStrength", () => ({
52
+ strength: ref([]),
53
+ score: ref(0),
54
+ color: ref("error"),
55
+ }));
56
+ }
57
+
58
+ function mountSignup(query: Record<string, unknown>) {
59
+ route.query = query;
60
+ app = createApp(SignupPage);
61
+ app.config.globalProperties.$t = (key: string) => key;
62
+ for (const name of [
63
+ "DmsCard",
64
+ "UIcon",
65
+ "UForm",
66
+ "UFormField",
67
+ "UInput",
68
+ "DmsOAuthButtons",
69
+ "DmsPasswordStrength",
70
+ "DmsLink",
71
+ ]) {
72
+ app.component(name, Passthrough);
73
+ }
74
+ app.component("UButton", LinkButton);
75
+ app.mount(host);
76
+ }
77
+
78
+ beforeEach(() => {
79
+ locale.value = "en";
80
+ setLocale.mockClear();
81
+ installRuntime();
82
+ host = document.createElement("div");
83
+ });
84
+ afterEach(() => {
85
+ app?.unmount();
86
+ vi.unstubAllGlobals();
87
+ });
88
+
89
+ it.each([{}, { token: "" }, { token: ["a", "b"] }])(
90
+ "explains an invitation link without its token (%o)",
91
+ (query) => {
92
+ expect(() => mountSignup(query)).not.toThrow();
93
+ expect(
94
+ host.querySelector('[data-testid="signup-invalid-invitation"]'),
95
+ ).not.toBe(null);
96
+ expect(host.textContent).toContain(
97
+ "page.signup.invalid_invitation_description",
98
+ );
99
+ expect(host.querySelector('a[href="/auth"]')?.textContent).toBe(
100
+ "button.login",
101
+ );
102
+ },
103
+ );
104
+
105
+ it("shows the signup form for an invitation link with its token", () => {
106
+ mountSignup({ token: "invite-token", email: "new@local.test" });
107
+ expect(host.querySelector('[data-testid="signup-invalid-invitation"]')).toBe(
108
+ null,
109
+ );
110
+ expect(host.textContent).toContain("page.signup.create_account_title");
111
+ });
112
+
113
+ it("opens in the language the invitation was written in", () => {
114
+ mountSignup({ token: "invite-token", email: "new@local.test", lang: "fr" });
115
+ expect(setLocale).toHaveBeenCalledWith("fr");
116
+ expect(locale.value).toBe("fr");
117
+ });
118
+
119
+ it.each([{}, { lang: "en" }, { lang: "de" }, { lang: ["fr", "en"] }])(
120
+ "keeps the current language for an invitation link carrying %o",
121
+ (query) => {
122
+ mountSignup({ token: "invite-token", email: "new@local.test", ...query });
123
+ expect(setLocale).not.toHaveBeenCalled();
124
+ expect(locale.value).toBe("en");
125
+ },
126
+ );
@@ -0,0 +1,30 @@
1
+ import { readFileSync, readdirSync, statSync } from "node:fs";
2
+ import { join, relative } from "node:path";
3
+ import { describe, expect, it } from "vitest";
4
+
5
+ const PARAGRAPH = /<p\b[^>]*>(.*?)<\/p>/gs;
6
+ const SKELETON = /<USkeleton\b/;
7
+
8
+ function walk(directory: string): string[] {
9
+ return readdirSync(directory).flatMap((name) => {
10
+ const path = join(directory, name);
11
+ return statSync(path).isDirectory() ? walk(path) : [path];
12
+ });
13
+ }
14
+
15
+ describe("skeleton placement", () => {
16
+ // The skeleton renders a <div>. The browser's parser closes an open <p>
17
+ // before a <div>, so the server markup no longer matches the client tree
18
+ // and hydration reports a mismatch.
19
+ it("keeps skeletons out of paragraphs", () => {
20
+ const offenders = walk(join(process.cwd(), "layers"))
21
+ .filter((path) => path.endsWith(".vue"))
22
+ .flatMap((path) =>
23
+ [...readFileSync(path, "utf8").matchAll(PARAGRAPH)]
24
+ .filter(([, content]) => SKELETON.test(content ?? ""))
25
+ .map(() => relative(process.cwd(), path)),
26
+ );
27
+
28
+ expect(offenders).toEqual([]);
29
+ });
30
+ });
@@ -0,0 +1,51 @@
1
+ import { afterEach, beforeEach, expect, it, vi } from "vitest";
2
+ import { computed, nextTick, reactive, ref, watch } from "vue";
3
+ import { useTab } from "../layers/dms-ui/app/composables/tab/useTab";
4
+ import { TabEvents } from "../layers/dms-ui/app/composables/tab/types/events";
5
+ import type { TabProps } from "../layers/dms-ui/app/composables/tab/types";
6
+
7
+ const TAB_COUNT = 3;
8
+ const sendComponentEvent = vi.fn();
9
+
10
+ beforeEach(() => {
11
+ sendComponentEvent.mockClear();
12
+ Object.entries({ computed, ref, watch, TabEvents }).forEach(([key, value]) =>
13
+ vi.stubGlobal(key, value),
14
+ );
15
+ vi.stubGlobal("isNumber", (value: unknown) => typeof value === "number");
16
+ vi.stubGlobal("isString", (value: unknown) => typeof value === "string");
17
+ vi.stubGlobal("useComponentEvent", () => ({ sendComponentEvent }));
18
+ vi.stubGlobal("useWatch", () => ({ isLoading: ref(false), state: ref({}) }));
19
+ vi.stubGlobal("useDmsRoute", () => reactive({ query: {} }));
20
+ vi.stubGlobal("useDmsRouter", () => ({ push: vi.fn() }));
21
+ });
22
+ afterEach(() => {
23
+ vi.unstubAllGlobals();
24
+ });
25
+
26
+ it("switches tabs without announcing them when no component owns the set", async () => {
27
+ const { activeTab, goToTab } = useTab(TAB_COUNT, { items: [] } as TabProps);
28
+
29
+ goToTab(1);
30
+ await nextTick();
31
+
32
+ expect(activeTab.value).toBe("1");
33
+ expect(sendComponentEvent).not.toHaveBeenCalled();
34
+ });
35
+
36
+ it("announces a tab change for a registered component", async () => {
37
+ const { goToTab } = useTab(TAB_COUNT, {
38
+ items: [],
39
+ componentId: "settings.tabs",
40
+ pageId: "settings",
41
+ } as TabProps);
42
+
43
+ goToTab(2);
44
+ await nextTick();
45
+
46
+ expect(sendComponentEvent).toHaveBeenCalledWith(
47
+ TabEvents.TAB_CHANGE,
48
+ "settings.tabs",
49
+ { previousTab: 0, currentTab: 2 },
50
+ );
51
+ });
@@ -0,0 +1,20 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { buildInitialColumnVisibility } from "../layers/dms-ui/app/build/composables/table-view/utils/columnVisibility";
3
+
4
+ describe("buildInitialColumnVisibility", () => {
5
+ it("hides the columns declared isVisible: false", () => {
6
+ expect(
7
+ buildInitialColumnVisibility([
8
+ { id: "number" },
9
+ { id: "amount", isVisible: true },
10
+ { id: "stripeId", isVisible: false },
11
+ ]),
12
+ ).toEqual({ number: true, amount: true, stripeId: false });
13
+ });
14
+
15
+ it("keeps every column visible when none opts out", () => {
16
+ expect(buildInitialColumnVisibility([{ id: "name" }])).toEqual({
17
+ name: true,
18
+ });
19
+ });
20
+ });
@@ -2,7 +2,7 @@ import { readFileSync, readdirSync, statSync } from "node:fs";
2
2
  import { join, relative } from "node:path";
3
3
  import { describe, expect, it } from "vitest";
4
4
 
5
- const EXPECTED_VUE_FILES = 143;
5
+ const EXPECTED_VUE_FILES = 144;
6
6
 
7
7
  function walk(directory: string): string[] {
8
8
  return readdirSync(directory).flatMap((name) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@antelopejs/dms",
3
- "version": "0.4.5",
3
+ "version": "0.4.6",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/AntelopeJS/dms.git"
@@ -36,7 +36,7 @@
36
36
  "@antelopejs/interface-data-api": ">=0.1.9 <1.0.0",
37
37
  "@antelopejs/interface-database": ">=0.1.7 <1.0.0",
38
38
  "@antelopejs/interface-database-decorators": ">=0.1.6 <1.0.0",
39
- "@antelopejs/interface-dms": ">=0.2.0 <1.0.0",
39
+ "@antelopejs/interface-dms": ">=0.2.5 <1.0.0",
40
40
  "@antelopejs/interface-email": ">=0.0.5 <1.0.0",
41
41
  "@antelopejs/interface-file-storage": ">=0.1.3 <1.0.0",
42
42
  "archiver": "^7.0.1",
@@ -21,7 +21,7 @@ List a section to see its files:
21
21
 
22
22
  Everything the DMS exposes to a consumer ships in **one** package, `@antelopejs/interface-dms`,
23
23
  split into subpaths: `/page`, `/component`, `/permissions`, `/guards`, `/db`, `/hooks`, `/realtime`,
24
- `/quick-actions`, `/auth` (+ `/auth/db`), `/base` (+ `/base/form`, `/base/table-view`,
24
+ `/quick-actions`, `/layout-banners`, `/auth` (+ `/auth/db`), `/base` (+ `/base/form`, `/base/table-view`,
25
25
  `/base/data-types`, `/base/types`, …), `/notifications`, `/html-render`. There is no separate
26
26
  `dms-auth` or `dms-base` interface, and nothing is imported through the runtime package
27
27
  `@antelopejs/dms`. Other modules follow the same shape: one `interface-<name>` package per module.