@saasicat/ui-vue 0.3.0 → 0.5.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 (109) hide show
  1. package/README.md +47 -4
  2. package/dist/action-registry-CQ2wL3R-.d.cts +85 -0
  3. package/dist/action-registry-CQ2wL3R-.d.ts +85 -0
  4. package/dist/chunk-3YP2ZAOD.js +63 -0
  5. package/dist/chunk-EH7TOD4H.js +718 -0
  6. package/dist/chunk-LVGUSD3T.js +26 -0
  7. package/dist/client/index.cjs +785 -0
  8. package/dist/client/index.d.cts +295 -0
  9. package/dist/client/index.d.ts +295 -0
  10. package/dist/client/index.js +52 -0
  11. package/dist/index.cjs +787 -834
  12. package/dist/index.d.cts +267 -841
  13. package/dist/index.d.ts +267 -841
  14. package/dist/index.js +284 -1059
  15. package/dist/quasar/index.cjs +159 -0
  16. package/dist/quasar/index.d.cts +86 -0
  17. package/dist/quasar/index.d.ts +86 -0
  18. package/dist/quasar/index.js +91 -0
  19. package/dist/ui-notify-COUzXEQ4.d.ts +178 -0
  20. package/dist/ui-notify-D_eAAwRh.d.cts +178 -0
  21. package/package.json +23 -3
  22. package/src/client/index.ts +25 -0
  23. package/src/components/FeatureGate.vue +1 -1
  24. package/src/components/plan/PlanCycleToggle.vue +1 -1
  25. package/src/components/plan/PlanGrid.vue +2 -2
  26. package/src/components/plan/PriceSummary.vue +1 -1
  27. package/src/components/plan/PromoCodeInput.vue +1 -1
  28. package/src/components/plan/PublicBundleGrid.vue +1 -1
  29. package/src/index.ts +82 -79
  30. package/src/pages-standard/AdminLayout.vue +2 -2
  31. package/src/pages-standard/DashboardPage.vue +2 -2
  32. package/src/pages-standard/EmailHistoryPage.vue +9 -13
  33. package/src/pages-standard/MarketingCatalogPage.vue +5 -5
  34. package/src/pages-standard/PilotsPage.vue +9 -13
  35. package/src/pages-standard/PlanVersionsPage.vue +2 -2
  36. package/src/pages-standard/PlansPage.vue +2 -2
  37. package/src/pages-standard/PlatformEmailPage.vue +7 -5
  38. package/src/pages-standard/PromoCodesPage.vue +8 -22
  39. package/src/pages-standard/SuperAdminLoginPage.vue +3 -3
  40. package/src/pages-standard/SuperAdminSetupWizard.vue +2 -2
  41. package/src/pages-standard/TenantDetailPage.vue +4 -4
  42. package/src/pages-standard/TenantsPage.vue +3 -3
  43. package/src/pages-standard/UsersPage.vue +6 -12
  44. package/src/pages-standard/plan-versions/PlanVersionHeader.vue +1 -1
  45. package/src/pages-standard/plan-versions/PlanVersionsAudit.vue +1 -1
  46. package/src/pages-standard/plan-versions/PlanVersionsDiff.vue +1 -1
  47. package/src/pages-standard/plan-versions/PlanVersionsList.vue +1 -1
  48. package/src/pages-standard/plan-versions/PlanVersionsMatrix.vue +1 -1
  49. package/src/pages-standard/plan-versions/PlanVersionsTimeline.vue +1 -1
  50. package/src/pages-tenant/MySubscriptionBundlesPage.vue +1 -1
  51. package/src/pages-tenant/OnboardingConfigurator.vue +3 -3
  52. package/src/pages-tenant/PackageSnapshotPanel.vue +1 -1
  53. package/src/pages-tenant/PlanChangeWizard.vue +2 -2
  54. package/src/pages-tenant/TenantPlanSection.vue +3 -3
  55. package/src/pages-tenant/tenant-plan-section/BundlePreviewDialog.vue +1 -1
  56. package/src/pages-tenant/tenant-plan-section/TenantBundleStore.vue +2 -2
  57. package/src/pages-tenant/tenant-plan-section/TenantPlanCardHeader.vue +1 -1
  58. package/src/pages-tenant/tenant-plan-section/TenantUsageGrid.vue +1 -1
  59. package/src/quasar/create-super-admin-app.ts +173 -0
  60. package/src/quasar/index.ts +11 -0
  61. package/src/quasar/notify.ts +30 -0
  62. package/src/{manifest-store-factory.ts → vue/manifest-store-factory.ts} +1 -1
  63. package/src/{platform-loaders.ts → vue/platform-loaders.ts} +4 -4
  64. package/src/{project-page-host.ts → vue/project-page-host.ts} +1 -1
  65. package/src/{create-super-admin-app.ts → vue/super-admin-context.ts} +20 -139
  66. package/src/vue/ui-notify.ts +30 -0
  67. package/src/{use-actions.ts → vue/use-actions.ts} +1 -1
  68. package/src/{use-api-list.ts → vue/use-api-list.ts} +1 -1
  69. package/src/{use-batch-columns.ts → vue/use-batch-columns.ts} +1 -1
  70. package/src/{use-bulk-publish.ts → vue/use-bulk-publish.ts} +1 -1
  71. package/src/{use-bundle-versions-map.ts → vue/use-bundle-versions-map.ts} +1 -1
  72. package/src/{use-bundles.ts → vue/use-bundles.ts} +1 -1
  73. package/src/{use-business-types.ts → vue/use-business-types.ts} +1 -1
  74. package/src/{use-catalog-entries.ts → vue/use-catalog-entries.ts} +1 -1
  75. package/src/{use-discovery.ts → vue/use-discovery.ts} +1 -1
  76. package/src/{use-entitlement.ts → vue/use-entitlement.ts} +1 -1
  77. package/src/{use-live-plan-versions.ts → vue/use-live-plan-versions.ts} +1 -1
  78. package/src/{use-manifest.ts → vue/use-manifest.ts} +1 -1
  79. package/src/{use-marketing-projections.ts → vue/use-marketing-projections.ts} +1 -1
  80. package/src/{use-nav.ts → vue/use-nav.ts} +1 -1
  81. package/src/{use-plans.ts → vue/use-plans.ts} +1 -1
  82. package/src/{use-promotions.ts → vue/use-promotions.ts} +1 -1
  83. package/src/{use-public-boot.ts → vue/use-public-boot.ts} +1 -1
  84. package/src/{use-super-admin-context.ts → vue/use-super-admin-context.ts} +2 -2
  85. package/src/{use-tenant-action-flow.ts → vue/use-tenant-action-flow.ts} +1 -1
  86. package/src/{use-tenant-billing-catalog.ts → vue/use-tenant-billing-catalog.ts} +2 -2
  87. package/src/{use-tenant-billing.ts → vue/use-tenant-billing.ts} +2 -2
  88. package/src/{use-tenant-manifest.ts → vue/use-tenant-manifest.ts} +1 -1
  89. package/src/{use-tenant-subscription-bundles.ts → vue/use-tenant-subscription-bundles.ts} +1 -1
  90. package/dist/testing-e2e/admin-pages-suite.d.cts +0 -37
  91. package/dist/testing-e2e/admin-pages-suite.d.ts +0 -37
  92. /package/src/{action-registry.ts → client/action-registry.ts} +0 -0
  93. /package/src/{batch-column-fetcher.ts → client/batch-column-fetcher.ts} +0 -0
  94. /package/src/{boot-loader.ts → client/boot-loader.ts} +0 -0
  95. /package/src/{http-json.ts → client/http-json.ts} +0 -0
  96. /package/src/{manifest-loader.ts → client/manifest-loader.ts} +0 -0
  97. /package/src/{nav-builder.ts → client/nav-builder.ts} +0 -0
  98. /package/src/{plan-versions-catalog.ts → client/plan-versions-catalog.ts} +0 -0
  99. /package/src/{types.ts → client/types.ts} +0 -0
  100. /package/src/{version.ts → client/version.ts} +0 -0
  101. /package/src/{create-admin-routes.ts → vue/create-admin-routes.ts} +0 -0
  102. /package/src/{entitlement-provider.ts → vue/entitlement-provider.ts} +0 -0
  103. /package/src/{feature-router-guard.ts → vue/feature-router-guard.ts} +0 -0
  104. /package/src/{use-audit-entries.ts → vue/use-audit-entries.ts} +0 -0
  105. /package/src/{use-plan-editor.ts → vue/use-plan-editor.ts} +0 -0
  106. /package/src/{use-plan-versions.ts → vue/use-plan-versions.ts} +0 -0
  107. /package/src/{use-platform-tenant-actions.ts → vue/use-platform-tenant-actions.ts} +0 -0
  108. /package/src/{use-subscription-draft.ts → vue/use-subscription-draft.ts} +0 -0
  109. /package/src/{use-tenants.ts → vue/use-tenants.ts} +0 -0
@@ -0,0 +1,178 @@
1
+ import { Component, App, InjectionKey } from 'vue';
2
+ import { NavigationGuardWithThis } from 'vue-router';
3
+ import { ActionKey, ComponentKey, AdminManifest } from '@saasicat/types';
4
+ import { A as ActionHandler, H as HttpClient } from './action-registry-CQ2wL3R-.cjs';
5
+
6
+ /**
7
+ * App-specific branding data that the platform `AdminLayout` and other
8
+ * consumers read via `useSuperAdminBrand()`.
9
+ */
10
+ interface SuperAdminBrand {
11
+ /** 2-letter abbreviation in the logo badge (`'ma'`, `'da'`, …). */
12
+ logoText: string;
13
+ /** Full display name (`'DemoApp'`, `'ClubApp'`, …). */
14
+ name: string;
15
+ /** Optional: tag to the right of the name, default `'SuperAdmin'`. */
16
+ tag?: string;
17
+ }
18
+ /**
19
+ * Endpoint configuration. `apiBase` is the shared prefix under which
20
+ * `/manifest`, `/boot` and extra routes live.
21
+ */
22
+ interface SuperAdminEndpoints {
23
+ /** Shared prefix, e.g. `'/api/admin'` or `'/api/v1/admin'`. */
24
+ apiBase: string;
25
+ /** Pre-login branding endpoint, default `${apiBase}/boot`. */
26
+ publicBootEndpoint?: string;
27
+ /** Post-login full-manifest endpoint, default `${apiBase}/manifest`. */
28
+ manifestEndpoint?: string;
29
+ }
30
+ type ExtensionLoader = () => Promise<Component | {
31
+ default: Component;
32
+ }>;
33
+ type ExtensionsMap = Record<ComponentKey, ExtensionLoader>;
34
+ type ActionsMap = Record<ActionKey, ActionHandler>;
35
+ interface SuperAdminAuthGuardOptions {
36
+ /** App provides: is the user currently logged in? */
37
+ isAuthenticated: () => boolean;
38
+ /** App provides: does the user have the SuperAdmin role? Default: only check `isAuthenticated`. */
39
+ isSuperAdmin?: () => boolean;
40
+ /** App provides: redirect path for unauthenticated calls (e.g. `'/login'`). */
41
+ onUnauthenticated: () => string;
42
+ }
43
+ /**
44
+ * Result of a login attempt. Apps pass this back from their auth store to the
45
+ * platform LoginPage; the page renders an appropriate error message.
46
+ *
47
+ * `ok: true` → login succeeded, page redirects to `redirectAfterLogin`.
48
+ * `ok: false` → page shows `message` or a translation derived from `code`.
49
+ *
50
+ * Known codes:
51
+ * - `BAD_CREDENTIALS` — wrong email/password combination.
52
+ * - `NOT_SUPER_ADMIN` — account does not have the SuperAdmin role.
53
+ * - otherwise — app-specific; `message` is displayed directly.
54
+ */
55
+ type SuperAdminLoginResult = {
56
+ ok: true;
57
+ } | {
58
+ ok: false;
59
+ code?: 'BAD_CREDENTIALS' | 'NOT_SUPER_ADMIN' | string;
60
+ message?: string;
61
+ };
62
+ /**
63
+ * Login adapter. The app passes its auth-store call through here. The platform
64
+ * LoginPage consumes it via `useSuperAdminLoginAdapter()`, without knowledge
65
+ * of app-specific stores (Pinia, auth API routes, MFA hooks).
66
+ */
67
+ interface SuperAdminLoginAdapter {
68
+ /**
69
+ * Performs the login. The app store encapsulates the API call, token
70
+ * storage, MFA hops etc.
71
+ */
72
+ login(email: string, password: string): Promise<SuperAdminLoginResult>;
73
+ /**
74
+ * Target route after a successful login. Default: `/admin/dashboard`
75
+ * (platform convention for the standard pages — apps with a different
76
+ * default mount override this here).
77
+ */
78
+ redirectAfterLogin?: string;
79
+ /**
80
+ * Optional: dev hint (test account), shown below the form. Deliberately
81
+ * rendered only when `environment !== 'production'`.
82
+ */
83
+ devHint?: {
84
+ email: string;
85
+ password: string;
86
+ };
87
+ }
88
+ interface SuperAdminManifestGuardOptions {
89
+ /**
90
+ * App provides: loads the manifest into the app store. The router guard
91
+ * `await`s the promise before the route is resolved.
92
+ *
93
+ * **On loader error:** the promise REJECTS. The router guard catches the
94
+ * rejection and decides depending on `errorRoute`:
95
+ * - `errorRoute` set → redirect to this route (fail-closed).
96
+ * - `errorRoute` not set → `console.error` + render allowed
97
+ * (defensive default behavior; the app must render the manifest gap
98
+ * itself).
99
+ */
100
+ ensureLoaded: () => Promise<void>;
101
+ /**
102
+ * Optional: read accessor on the loaded manifest. When set, it is exposed
103
+ * via `provide(SUPER_ADMIN_MANIFEST_KEY)` — the `<ProjectPageHost>`
104
+ * resolves manifest `projectPages` through it against the
105
+ * `extensions:` map.
106
+ */
107
+ getManifest?: () => AdminManifest | null;
108
+ /**
109
+ * Optional: path that the router guard redirects to on a manifest load
110
+ * error (fail-closed mode). The app must register the route in `appRoutes`
111
+ * and mark it as `meta.public = true`, otherwise it runs through the
112
+ * manifest guard again and produces a redirect loop.
113
+ */
114
+ errorRoute?: string;
115
+ }
116
+ /**
117
+ * Guard configuration shared by `buildNavigationGuard()` and
118
+ * `createSuperAdminApp()` (which embeds both fields in its options).
119
+ */
120
+ interface SuperAdminGuardOptions {
121
+ /**
122
+ * Optional: auth guard. When set, `router.beforeEach` is wired up
123
+ * automatically — `to.meta.public === true` bypasses the guard.
124
+ */
125
+ authGuard?: SuperAdminAuthGuardOptions;
126
+ /**
127
+ * Optional: manifest guard. Runs after a successful auth guard, blocks the
128
+ * render until the manifest is loaded (prevents sidebar flicker).
129
+ */
130
+ manifestGuard?: SuperAdminManifestGuardOptions;
131
+ }
132
+ /** Vue inject key for `useSuperAdminBrand()`. */
133
+ declare const SUPER_ADMIN_BRAND_KEY: InjectionKey<SuperAdminBrand>;
134
+ /** Vue inject key for `useSuperAdminEndpoints()`. */
135
+ declare const SUPER_ADMIN_ENDPOINTS_KEY: InjectionKey<Required<SuperAdminEndpoints>>;
136
+ /** Vue inject key for `useSuperAdminExtensions()`. */
137
+ declare const SUPER_ADMIN_EXTENSIONS_KEY: InjectionKey<ExtensionsMap>;
138
+ /** Vue inject key for `useSuperAdminActions()`. */
139
+ declare const SUPER_ADMIN_ACTIONS_KEY: InjectionKey<ActionsMap>;
140
+ /**
141
+ * Vue inject key for the manifest accessor. Only provided when
142
+ * `manifestGuard.getManifest` was passed to `createSuperAdminApp()` — the
143
+ * `<ProjectPageHost>` needs it to resolve project pages.
144
+ */
145
+ declare const SUPER_ADMIN_MANIFEST_KEY: InjectionKey<() => AdminManifest | null>;
146
+ /** Vue inject key for `useSuperAdminLoginAdapter()`. */
147
+ declare const SUPER_ADMIN_LOGIN_ADAPTER_KEY: InjectionKey<SuperAdminLoginAdapter>;
148
+ /** Vue inject key for `useSuperAdminHttp()` (pre-login HttpClient). */
149
+ declare const SUPER_ADMIN_HTTP_KEY: InjectionKey<HttpClient>;
150
+ /**
151
+ * Additional Vue plugins (e.g. an app's own NotificationCenter) that a
152
+ * bootstrap installs after the platform setup, before the mount.
153
+ */
154
+ type InstallPlugin = (app: App) => void;
155
+ /**
156
+ * Internal helper, exported for isolated unit tests of the navigation
157
+ * behavior (auth redirect, manifest fail-closed path). Consumers should call
158
+ * `createSuperAdminApp()`, not this helper directly.
159
+ */
160
+ declare function buildNavigationGuard(options: SuperAdminGuardOptions): NavigationGuardWithThis<undefined> | null;
161
+
162
+ /**
163
+ * Feedback kind, aligned with the established page conventions
164
+ * (`positive` = success, `negative` = error).
165
+ */
166
+ type UiNotifyKind = 'positive' | 'negative' | 'warning' | 'info';
167
+ interface UiNotifyOptions {
168
+ /** Secondary line below the message (e.g. changed fields, one-time password). */
169
+ caption?: string;
170
+ /** Display duration in ms; implementations fall back to their default when unset. */
171
+ timeoutMs?: number;
172
+ }
173
+ /** Notify port. Compatible with the `(kind, message)` callbacks pages already accept. */
174
+ type UiNotify = (kind: UiNotifyKind, message: string, options?: UiNotifyOptions) => void;
175
+ /** Vue inject key for the notify port (see `Symbol.for` note in super-admin-context.ts). */
176
+ declare const SUPER_ADMIN_NOTIFY_KEY: InjectionKey<UiNotify>;
177
+
178
+ export { type ActionsMap as A, type ExtensionsMap as E, type InstallPlugin as I, type SuperAdminGuardOptions as S, type UiNotify as U, type SuperAdminBrand as a, type SuperAdminEndpoints as b, type SuperAdminLoginAdapter as c, type ExtensionLoader as d, SUPER_ADMIN_ACTIONS_KEY as e, SUPER_ADMIN_BRAND_KEY as f, SUPER_ADMIN_ENDPOINTS_KEY as g, SUPER_ADMIN_EXTENSIONS_KEY as h, SUPER_ADMIN_HTTP_KEY as i, SUPER_ADMIN_LOGIN_ADAPTER_KEY as j, SUPER_ADMIN_MANIFEST_KEY as k, SUPER_ADMIN_NOTIFY_KEY as l, type SuperAdminAuthGuardOptions as m, type SuperAdminLoginResult as n, type SuperAdminManifestGuardOptions as o, type UiNotifyKind as p, type UiNotifyOptions as q, buildNavigationGuard as r };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saasicat/ui-vue",
3
- "version": "0.3.0",
3
+ "version": "0.5.0",
4
4
  "description": "Vue 3 components + composables for the SuperAdmin UI shell. Provides boot loader, manifest loader (ETag cache), nav builder, action registry and standard pages.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -17,6 +17,26 @@
17
17
  "default": "./dist/index.cjs"
18
18
  }
19
19
  },
20
+ "./client": {
21
+ "import": {
22
+ "types": "./dist/client/index.d.ts",
23
+ "default": "./dist/client/index.js"
24
+ },
25
+ "require": {
26
+ "types": "./dist/client/index.d.cts",
27
+ "default": "./dist/client/index.cjs"
28
+ }
29
+ },
30
+ "./quasar": {
31
+ "import": {
32
+ "types": "./dist/quasar/index.d.ts",
33
+ "default": "./dist/quasar/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/quasar/index.d.cts",
37
+ "default": "./dist/quasar/index.cjs"
38
+ }
39
+ },
20
40
  "./pages/*": "./src/pages-standard/*",
21
41
  "./pages-standard/*": "./src/pages-standard/*",
22
42
  "./pages-tenant/*": "./src/pages-tenant/*",
@@ -33,7 +53,7 @@
33
53
  "src"
34
54
  ],
35
55
  "dependencies": {
36
- "@saasicat/types": "^0.3.0"
56
+ "@saasicat/types": "^0.5.0"
37
57
  },
38
58
  "peerDependencies": {
39
59
  "pinia": "^2.0.0 || ^3.0.0",
@@ -78,7 +98,7 @@
78
98
  "access": "public"
79
99
  },
80
100
  "scripts": {
81
- "build": "tsup src/index.ts --format esm,cjs --dts --clean --external @saasicat/types --external vue --external vue-router --external pinia --external quasar && tsup src/testing-e2e/admin-pages-suite.ts --format esm,cjs --dts --out-dir dist/testing-e2e --external @playwright/test",
101
+ "build": "tsup",
82
102
  "typecheck": "vue-tsc --noEmit -p tsconfig.json",
83
103
  "pretest": "pnpm run build",
84
104
  "test": "node --test tests/**/*.test.js",
@@ -0,0 +1,25 @@
1
+ // @saasicat/ui-vue/client — the framework-free core of the SuperAdmin UI
2
+ // package. No Vue, no Pinia, no Quasar: only `@saasicat/types` and the
3
+ // platform HTTP contract. Usable from any framework binding or plain
4
+ // TypeScript (Node scripts, other UI stacks).
5
+ //
6
+ // Contents:
7
+ // - types: HttpClient, KvStore, defaultHttpClient, defaultKvStore
8
+ // - http-json: JSON fetch helper over HttpClient
9
+ // - boot-loader: BootLoader + BootLoadError
10
+ // - manifest-loader: ManifestLoader with ETag cache + ManifestLoadError
11
+ // - nav-builder: buildRoutes, buildSidebar, resolveExtension
12
+ // - action-registry: ActionRegistry, MissingHandlerError, ActionDefNotInManifestError
13
+ // - batch-column-fetcher: BatchColumnFetcher + BatchColumnDriftError
14
+ // - plan-versions-catalog: plan-version list/diff helpers
15
+ // - version: ADMIN_UI_VERSION
16
+
17
+ export * from './version.js';
18
+ export * from './types.js';
19
+ export * from './http-json.js';
20
+ export * from './boot-loader.js';
21
+ export * from './manifest-loader.js';
22
+ export * from './nav-builder.js';
23
+ export * from './action-registry.js';
24
+ export * from './batch-column-fetcher.js';
25
+ export * from './plan-versions-catalog.js';
@@ -35,7 +35,7 @@
35
35
  // instead of returning `null`. (Strict mode comes later; currently default = lenient.)
36
36
 
37
37
  import { computed } from 'vue';
38
- import { useInjectedEntitlement } from '../entitlement-provider.js';
38
+ import { useInjectedEntitlement } from '../vue/entitlement-provider.js';
39
39
 
40
40
  interface Props {
41
41
  /** A single FeatureKey or several as a logical OR. */
@@ -25,7 +25,7 @@
25
25
  </template>
26
26
 
27
27
  <script setup lang="ts">
28
- import type { BillingCycleStr } from '../../use-tenant-billing.js';
28
+ import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
29
29
 
30
30
  interface I18n {
31
31
  ariaLabel: string;
@@ -48,8 +48,8 @@
48
48
  </template>
49
49
 
50
50
  <script setup lang="ts">
51
- import type { CatalogPlan } from '../../use-tenant-billing-catalog.js';
52
- import type { BillingCycleStr } from '../../use-tenant-billing.js';
51
+ import type { CatalogPlan } from '../../vue/use-tenant-billing-catalog.js';
52
+ import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
53
53
 
54
54
  interface I18n {
55
55
  popular: string;
@@ -90,7 +90,7 @@
90
90
  </template>
91
91
 
92
92
  <script setup lang="ts">
93
- import type { DraftPricing } from '../../use-subscription-draft.js';
93
+ import type { DraftPricing } from '../../vue/use-subscription-draft.js';
94
94
 
95
95
  interface I18n {
96
96
  noPlan: string;
@@ -46,7 +46,7 @@
46
46
 
47
47
  <script setup lang="ts">
48
48
  import { ref, watch } from 'vue';
49
- import type { PromoState } from '../../use-subscription-draft.js';
49
+ import type { PromoState } from '../../vue/use-subscription-draft.js';
50
50
 
51
51
  interface I18n {
52
52
  openLabel: string;
@@ -76,7 +76,7 @@ import {
76
76
  type BundleAvailabilityState,
77
77
  type PublicMarketingBundle,
78
78
  } from '@saasicat/types';
79
- import type { BillingCycleStr } from '../../use-tenant-billing.js';
79
+ import type { BillingCycleStr } from '../../vue/use-tenant-billing.js';
80
80
 
81
81
  interface I18n {
82
82
  perMonth: string;
package/src/index.ts CHANGED
@@ -1,75 +1,88 @@
1
- // @saasicat/ui-vue — Vue 3 components + composables for the
2
- // SuperAdmin UI shell.
1
+ // @saasicat/ui-vue — Vue 3 composables + loaders for the SuperAdmin UI shell.
3
2
  //
4
- // P4.1 (Phase 30): public boot loader + manifest loader (ETag cache).
5
- // P4.2 (Phase 31): nav builder + extension host + action registry.
6
- // P4.3 (Phase 32): batch column fetcher.
7
- // P4.4 (Phase 33): composables for standard pages (Tenants, Audit, Entitlement).
8
- // P4.5 (Phase 34): plan-versions list composables + bulk-publish orchestration.
3
+ // The package is layered; each layer has its own entry:
9
4
  //
10
- // Contents:
11
- // - types: HttpClient, KvStore, defaultHttpClient, defaultKvStore
12
- // - boot-loader: BootLoader (framework-agnostic) + BootLoadError
13
- // - manifest-loader: ManifestLoader with ETag cache + ManifestLoadError
14
- // - nav-builder: buildRoutes, buildSidebar, resolveExtension
15
- // - action-registry: ActionRegistry, MissingHandlerError, ActionDefNotInManifestError
16
- // - batch-column-fetcher: BatchColumnFetcher + BatchColumnDriftError
17
- // - use-api-list: useApiList<T> generic list composable
18
- // - use-tenants: useTenants typed wrapper
19
- // - use-audit-entries: useAuditEntries typed wrapper
20
- // - use-entitlement: useEntitlement composable
21
- // - use-plan-versions: usePlanVersionsCatalog
22
- // - use-bulk-publish: useBulkPublish (parallel publishes with status tracking)
23
- // - use-plan-editor: usePlanEditor composable (feature discovery, plannedOnly filter)
24
- // - use-public-boot: usePublicBoot composable
25
- // - use-manifest: useManifest composable
26
- // - use-nav: useNav composable
27
- // - use-actions: useActions composable
28
- // - use-batch-columns: useBatchColumns composable
5
+ // - `@saasicat/ui-vue/client` (`src/client/`) — framework-free core:
6
+ // loaders, nav builder, action registry, HTTP contract. No Vue, no
7
+ // Pinia, no Quasar.
8
+ // - `@saasicat/ui-vue` (this entry, `src/vue/`) Vue bindings: composables,
9
+ // router guards, injection keys, optional Pinia store factory. Re-exports
10
+ // the client layer. No Quasar.
11
+ // - `@saasicat/ui-vue/quasar` (`src/quasar/`) — Quasar bootstrap:
12
+ // `createSuperAdminApp()` and the Quasar notify port implementation.
13
+ // - Quasar standard pages/components — raw SFCs via the
14
+ // `./pages-standard/*`, `./pages-tenant/*` and `./components/*` subpath
15
+ // exports (tsup ignores `.vue`).
16
+ //
17
+ // Layer rule (enforced via ESLint `no-restricted-imports`): client imports
18
+ // nothing framework-specific; vue never imports quasar; this entry never
19
+ // reaches the quasar layer or the SFC directories (except the whitelisted
20
+ // framework-free type/i18n modules below).
21
+
22
+ // ---------------------------------------------------------------------------
23
+ // Client layer (framework-free core).
24
+ // ---------------------------------------------------------------------------
25
+ export * from './client/index.js';
26
+
27
+ // ---------------------------------------------------------------------------
28
+ // Vue layer: shell contract (injection keys, option types, navigation guard)
29
+ // and the UI notify port. `createSuperAdminApp()` itself lives in
30
+ // `@saasicat/ui-vue/quasar`.
31
+ // ---------------------------------------------------------------------------
32
+ export * from './vue/super-admin-context.js';
33
+ export * from './vue/ui-notify.js';
34
+ export * from './vue/use-super-admin-context.js';
29
35
 
30
- export * from './version.js';
31
- export * from './types.js';
32
- export * from './http-json.js';
33
- export * from './create-admin-routes.js';
34
- export * from './boot-loader.js';
35
- export * from './manifest-loader.js';
36
- export * from './nav-builder.js';
37
- export * from './action-registry.js';
38
- export * from './batch-column-fetcher.js';
39
- export * from './use-api-list.js';
40
- export * from './use-tenants.js';
41
- export * from './use-audit-entries.js';
42
- export * from './use-entitlement.js';
43
- export * from './use-tenant-manifest.js';
44
- export * from './entitlement-provider.js';
45
- export * from './feature-router-guard.js';
36
+ // ---------------------------------------------------------------------------
37
+ // Vue layer: composables, guards, hosts, store factory.
38
+ // ---------------------------------------------------------------------------
39
+ export * from './vue/create-admin-routes.js';
40
+ export * from './vue/use-api-list.js';
41
+ export * from './vue/use-tenants.js';
42
+ export * from './vue/use-audit-entries.js';
43
+ export * from './vue/use-entitlement.js';
44
+ export * from './vue/use-tenant-manifest.js';
45
+ export * from './vue/entitlement-provider.js';
46
+ export * from './vue/feature-router-guard.js';
46
47
  // FeatureGate.vue is not bundled — consumers import it directly:
47
48
  // import FeatureGate from '@saasicat/ui-vue/components/FeatureGate.vue';
48
- export * from './use-tenant-billing-catalog.js';
49
- export * from './use-tenant-billing.js';
50
- export * from './use-subscription-draft.js';
51
- export * from './pages-tenant/default-i18n.js';
52
- export * from './use-plan-versions.js';
53
- export * from './use-bulk-publish.js';
54
- export * from './use-plan-editor.js';
55
- export * from './use-public-boot.js';
56
- export * from './use-discovery.js';
57
- export * from './use-catalog-entries.js';
58
- export * from './use-bundles.js';
59
- export * from './use-bundle-versions-map.js';
60
- export * from './use-tenant-subscription-bundles.js';
61
- export * from './use-business-types.js';
62
- export * from './use-marketing-projections.js';
63
- export * from './use-promotions.js';
64
- export * from './use-plans.js';
65
- export * from './use-live-plan-versions.js';
66
- export * from './use-manifest.js';
67
- export * from './use-nav.js';
68
- export * from './use-actions.js';
69
- export * from './use-tenant-action-flow.js';
70
- export * from './use-platform-tenant-actions.js';
71
- export * from './use-batch-columns.js';
72
- export * from './plan-versions-catalog.js';
49
+ export * from './vue/use-tenant-billing-catalog.js';
50
+ export * from './vue/use-tenant-billing.js';
51
+ export * from './vue/use-subscription-draft.js';
52
+ export * from './vue/use-plan-versions.js';
53
+ export * from './vue/use-bulk-publish.js';
54
+ export * from './vue/use-plan-editor.js';
55
+ export * from './vue/use-public-boot.js';
56
+ export * from './vue/use-discovery.js';
57
+ export * from './vue/use-catalog-entries.js';
58
+ export * from './vue/use-bundles.js';
59
+ export * from './vue/use-bundle-versions-map.js';
60
+ export * from './vue/use-tenant-subscription-bundles.js';
61
+ export * from './vue/use-business-types.js';
62
+ export * from './vue/use-marketing-projections.js';
63
+ export * from './vue/use-promotions.js';
64
+ export * from './vue/use-plans.js';
65
+ export * from './vue/use-live-plan-versions.js';
66
+ export * from './vue/use-manifest.js';
67
+ export * from './vue/use-nav.js';
68
+ export * from './vue/use-actions.js';
69
+ export * from './vue/use-tenant-action-flow.js';
70
+ export * from './vue/use-platform-tenant-actions.js';
71
+ export * from './vue/use-batch-columns.js';
72
+ // Loader factory that builds BootLoader + ManifestLoader from the same
73
+ // endpoint configuration as createSuperAdminApp() — so that endpoints live
74
+ // in a single place per app.
75
+ export * from './vue/platform-loaders.js';
76
+ // ProjectPageHost: resolves manifest projectPages dynamically against the
77
+ // extensions: map — replaces static route duplication in the apps.
78
+ export * from './vue/project-page-host.js';
79
+ // Manifest Pinia store factory — standardizes ensureLoaded/reload/clearCache.
80
+ export * from './vue/manifest-store-factory.js';
81
+
82
+ // ---------------------------------------------------------------------------
83
+ // Framework-free type/i18n modules that deliberately stay co-located with
84
+ // their SFCs (whitelisted in the ESLint layer rules).
85
+ // ---------------------------------------------------------------------------
73
86
  // Platform dialog types for app wrappers that type submit handlers.
74
87
  export * from './components/dialogs/types.js';
75
88
  // Pure resolvers for translated feature/quota labels in the bundle editors.
@@ -78,18 +91,8 @@ export * from './components/bundle-editor/catalog-i18n.js';
78
91
  export * from './pages-standard/platform-email.types.js';
79
92
  // Types of the shared EmailHistoryPage (platform email history).
80
93
  export * from './pages-standard/email-history.types.js';
81
- // Universal bootstrap helper for SuperAdmin apps + associated composables.
82
- export * from './create-super-admin-app.js';
83
- export * from './use-super-admin-context.js';
84
- // Loader factory that builds BootLoader + ManifestLoader from the same
85
- // endpoint configuration as createSuperAdminApp() — so that endpoints live
86
- // in a single place per app.
87
- export * from './platform-loaders.js';
88
- // ProjectPageHost: resolves manifest projectPages dynamically against the
89
- // extensions: map — replaces static route duplication in the apps.
90
- export * from './project-page-host.js';
91
- // Manifest Pinia store factory — standardizes ensureLoaded/reload/clearCache.
92
- export * from './manifest-store-factory.js';
94
+ // Default German labels for the tenant-facing pages.
95
+ export * from './pages-tenant/default-i18n.js';
93
96
 
94
97
  // The shared SuperAdmin LoginPage lives at
95
98
  // `@saasicat/ui-vue/pages-standard/SuperAdminLoginPage.vue` —
@@ -94,8 +94,8 @@
94
94
  import { computed, ref } from 'vue';
95
95
  import { useRoute } from 'vue-router';
96
96
  import type { AdminManifest, StandardPageKey } from '@saasicat/types';
97
- import { buildRoutes, buildSidebar, DEFAULT_SECTION_ORDER } from '../nav-builder.js';
98
- import { ADMIN_UI_VERSION } from '../version.js';
97
+ import { buildRoutes, buildSidebar, DEFAULT_SECTION_ORDER } from '../client/nav-builder.js';
98
+ import { ADMIN_UI_VERSION } from '../client/version.js';
99
99
 
100
100
  // SuperAdmin layout — universal platform shell for all consumer apps.
101
101
  // CSS classes `sa-admin-*` with BEM convention; apps can override any class
@@ -108,8 +108,8 @@
108
108
  <script setup lang="ts">
109
109
  import { computed, onMounted, reactive, ref, watch } from 'vue';
110
110
  import type { AdminManifest, KpiCardDef } from '@saasicat/types';
111
- import type { HttpClient } from '../types.js';
112
- import { buildRoutes } from '../nav-builder.js';
111
+ import type { HttpClient } from '../client/types.js';
112
+ import { buildRoutes } from '../client/nav-builder.js';
113
113
 
114
114
  // Platform standard page: Dashboard.
115
115
  //
@@ -197,7 +197,7 @@
197
197
 
198
198
  <script setup lang="ts">
199
199
  import { reactive, ref } from 'vue';
200
- import { useQuasar } from 'quasar';
200
+ import { useSuperAdminNotify } from '../quasar/notify.js';
201
201
  import MfaPromptDialog from '../components/MfaPromptDialog.vue';
202
202
  import type {
203
203
  EmailHistoryRow,
@@ -231,7 +231,7 @@ const props = withDefaults(
231
231
  },
232
232
  );
233
233
 
234
- const q = useQuasar();
234
+ const notify = useSuperAdminNotify();
235
235
 
236
236
  const rows = ref<EmailHistoryRow[]>([]);
237
237
  const loading = ref(false);
@@ -312,7 +312,7 @@ async function reload(): Promise<void> {
312
312
  if (seq !== reloadSeq) return;
313
313
  rows.value = [];
314
314
  pagination.value.rowsNumber = 0;
315
- q.notify({ type: 'negative', message: errMsg(err), position: 'top' });
315
+ notify('negative', errMsg(err));
316
316
  } finally {
317
317
  if (seq === reloadSeq) loading.value = false;
318
318
  }
@@ -342,7 +342,7 @@ async function openDetail(row: EmailHistoryRow): Promise<void> {
342
342
  detail.value = await props.loadEmailDetail(row.id);
343
343
  } catch (err) {
344
344
  detailOpen.value = false;
345
- q.notify({ type: 'negative', message: errMsg(err), position: 'top' });
345
+ notify('negative', errMsg(err));
346
346
  } finally {
347
347
  detailLoading.value = false;
348
348
  }
@@ -354,13 +354,9 @@ async function onResend(id: string): Promise<void> {
354
354
  );
355
355
  if (!ok) return;
356
356
  if (result && result.success === false) {
357
- q.notify({
358
- type: 'negative',
359
- message: result.message ?? 'Versand fehlgeschlagen',
360
- position: 'top',
361
- });
357
+ notify('negative', result.message ?? 'Versand fehlgeschlagen');
362
358
  } else {
363
- q.notify({ type: 'positive', message: 'E-Mail erneut versendet', position: 'top' });
359
+ notify('positive', 'E-Mail erneut versendet');
364
360
  }
365
361
  await reload();
366
362
  }
@@ -378,7 +374,7 @@ async function confirmDelete(): Promise<void> {
378
374
  props.deleteEmail(id, code || undefined),
379
375
  );
380
376
  if (!ok) return;
381
- q.notify({ type: 'positive', message: 'Aus Verlauf entfernt', position: 'top' });
377
+ notify('positive', 'Aus Verlauf entfernt');
382
378
  if (detail.value?.id === id) detailOpen.value = false;
383
379
  await reload();
384
380
  }
@@ -394,7 +390,7 @@ async function runWrite<T>(
394
390
  const result = await invoke('');
395
391
  return { ok: true, result };
396
392
  } catch (err) {
397
- q.notify({ type: 'negative', message: errMsg(err), position: 'top' });
393
+ notify('negative', errMsg(err));
398
394
  return { ok: false };
399
395
  }
400
396
  }
@@ -412,7 +408,7 @@ async function runWrite<T>(
412
408
  continue;
413
409
  }
414
410
  showMfa.value = false;
415
- q.notify({ type: 'negative', message: errMsg(err), position: 'top' });
411
+ notify('negative', errMsg(err));
416
412
  return { ok: false };
417
413
  }
418
414
  }
@@ -122,11 +122,11 @@ import {
122
122
  type PromotionResult,
123
123
  type PromotionRow,
124
124
  } from '@saasicat/types';
125
- import { usePlans } from '../use-plans.js';
126
- import { useMarketingProjections } from '../use-marketing-projections.js';
127
- import { usePromotions } from '../use-promotions.js';
128
- import { useCatalogEntries } from '../use-catalog-entries.js';
129
- import { defaultHttpClient, type HttpClient } from '../types.js';
125
+ import { usePlans } from '../vue/use-plans.js';
126
+ import { useMarketingProjections } from '../vue/use-marketing-projections.js';
127
+ import { usePromotions } from '../vue/use-promotions.js';
128
+ import { useCatalogEntries } from '../vue/use-catalog-entries.js';
129
+ import { defaultHttpClient, type HttpClient } from '../client/types.js';
130
130
  import MarketingPromotionsTab from '../components/MarketingPromotionsTab.vue';
131
131
  import MarketingCatalogAdmin from './marketing-catalog/MarketingCatalogAdmin.vue';
132
132
  import MarketingCatalogHeader from './marketing-catalog/MarketingCatalogHeader.vue';