@nextsparkjs/core 0.1.0-beta.67 → 0.1.0-beta.69

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 (201) hide show
  1. package/dist/components/dashboard/block-editor/block-picker.d.ts +7 -2
  2. package/dist/components/dashboard/block-editor/block-picker.d.ts.map +1 -1
  3. package/dist/components/dashboard/block-editor/block-picker.js +27 -20
  4. package/dist/components/dashboard/block-editor/block-preview-canvas.d.ts.map +1 -1
  5. package/dist/components/dashboard/block-editor/block-preview-canvas.js +37 -37
  6. package/dist/components/dashboard/block-editor/block-settings-panel.js +3 -3
  7. package/dist/components/dashboard/block-editor/builder-editor-view.d.ts.map +1 -1
  8. package/dist/components/dashboard/block-editor/builder-editor-view.js +124 -82
  9. package/dist/components/dashboard/block-editor/config-panel.d.ts +18 -0
  10. package/dist/components/dashboard/block-editor/config-panel.d.ts.map +1 -0
  11. package/dist/components/dashboard/block-editor/config-panel.js +413 -0
  12. package/dist/components/dashboard/block-editor/floating-block-toolbar.js +1 -1
  13. package/dist/components/dashboard/block-editor/pattern-card.js +1 -1
  14. package/dist/components/dashboard/block-editor/pattern-reference-preview.js +1 -1
  15. package/dist/components/dashboard/block-editor/sortable-block.js +1 -1
  16. package/dist/components/dashboard/block-editor/tree-view-node.d.ts +11 -0
  17. package/dist/components/dashboard/block-editor/tree-view-node.d.ts.map +1 -0
  18. package/dist/components/dashboard/block-editor/tree-view-node.js +91 -0
  19. package/dist/components/dashboard/block-editor/tree-view.d.ts +17 -0
  20. package/dist/components/dashboard/block-editor/tree-view.d.ts.map +1 -0
  21. package/dist/components/dashboard/block-editor/tree-view.js +125 -0
  22. package/dist/components/dashboard/block-editor/viewport-toggle.d.ts +10 -0
  23. package/dist/components/dashboard/block-editor/viewport-toggle.d.ts.map +1 -0
  24. package/dist/components/dashboard/block-editor/viewport-toggle.js +55 -0
  25. package/dist/components/public/pageBuilder/PageRenderer.d.ts.map +1 -1
  26. package/dist/components/public/pageBuilder/PageRenderer.js +10 -1
  27. package/dist/components/settings/layouts/SettingsSidebar.d.ts.map +1 -1
  28. package/dist/components/settings/layouts/SettingsSidebar.js +14 -0
  29. package/dist/components/ui/dynamic-icon.d.ts +12 -0
  30. package/dist/components/ui/dynamic-icon.d.ts.map +1 -0
  31. package/dist/components/ui/dynamic-icon.js +11 -0
  32. package/dist/components/ui/index.d.ts +7 -0
  33. package/dist/components/ui/index.d.ts.map +1 -1
  34. package/dist/components/ui/index.js +7 -0
  35. package/dist/components/ui/skeleton-dashboard.d.ts +32 -0
  36. package/dist/components/ui/skeleton-dashboard.d.ts.map +1 -0
  37. package/dist/components/ui/skeleton-dashboard.js +69 -0
  38. package/dist/components/ui/skeleton-detail.d.ts.map +1 -1
  39. package/dist/components/ui/skeleton-detail.js +0 -1
  40. package/dist/components/ui/skeleton-features.d.ts +27 -0
  41. package/dist/components/ui/skeleton-features.d.ts.map +1 -0
  42. package/dist/components/ui/skeleton-features.js +90 -0
  43. package/dist/components/ui/skeleton-form.d.ts.map +1 -1
  44. package/dist/components/ui/skeleton-form.js +0 -1
  45. package/dist/components/ui/skeleton-list.d.ts.map +1 -1
  46. package/dist/components/ui/skeleton-list.js +0 -1
  47. package/dist/components/ui/skeleton-public.d.ts +26 -0
  48. package/dist/components/ui/skeleton-public.d.ts.map +1 -0
  49. package/dist/components/ui/skeleton-public.js +61 -0
  50. package/dist/components/ui/skeleton-settings.d.ts +54 -0
  51. package/dist/components/ui/skeleton-settings.d.ts.map +1 -0
  52. package/dist/components/ui/skeleton-settings.js +332 -0
  53. package/dist/components/ui/skeleton.d.ts +23 -1
  54. package/dist/components/ui/skeleton.d.ts.map +1 -1
  55. package/dist/components/ui/skeleton.js +46 -2
  56. package/dist/contexts/TeamContext.d.ts +2 -0
  57. package/dist/contexts/TeamContext.d.ts.map +1 -1
  58. package/dist/contexts/TeamContext.js +78 -68
  59. package/dist/hooks/usePrefetch.d.ts +43 -0
  60. package/dist/hooks/usePrefetch.d.ts.map +1 -0
  61. package/dist/hooks/usePrefetch.js +56 -0
  62. package/dist/lib/actions/index.d.ts +27 -14
  63. package/dist/lib/actions/index.d.ts.map +1 -1
  64. package/dist/lib/actions/index.js +19 -1
  65. package/dist/lib/actions/team.actions.d.ts +107 -0
  66. package/dist/lib/actions/team.actions.d.ts.map +1 -0
  67. package/dist/lib/actions/team.actions.js +220 -0
  68. package/dist/lib/actions/user.actions.d.ts +99 -0
  69. package/dist/lib/actions/user.actions.d.ts.map +1 -0
  70. package/dist/lib/actions/user.actions.js +149 -0
  71. package/dist/lib/selectors/core-selectors.d.ts +98 -44
  72. package/dist/lib/selectors/core-selectors.d.ts.map +1 -1
  73. package/dist/lib/selectors/domains/block-editor.selectors.d.ts +136 -71
  74. package/dist/lib/selectors/domains/block-editor.selectors.d.ts.map +1 -1
  75. package/dist/lib/selectors/domains/block-editor.selectors.js +130 -60
  76. package/dist/lib/selectors/selectors.d.ts +196 -88
  77. package/dist/lib/selectors/selectors.d.ts.map +1 -1
  78. package/dist/messages/de/devtools.json +4 -0
  79. package/dist/messages/de/index.d.ts +4 -0
  80. package/dist/messages/de/index.d.ts.map +1 -1
  81. package/dist/messages/en/admin.json +15 -1
  82. package/dist/messages/en/devtools.json +16 -0
  83. package/dist/messages/en/index.d.ts +30 -0
  84. package/dist/messages/en/index.d.ts.map +1 -1
  85. package/dist/messages/es/admin.json +16 -1
  86. package/dist/messages/es/devtools.json +4 -0
  87. package/dist/messages/es/index.d.ts +19 -0
  88. package/dist/messages/es/index.d.ts.map +1 -1
  89. package/dist/messages/fr/devtools.json +4 -0
  90. package/dist/messages/fr/index.d.ts +4 -0
  91. package/dist/messages/fr/index.d.ts.map +1 -1
  92. package/dist/messages/it/devtools.json +4 -0
  93. package/dist/messages/it/index.d.ts +4 -0
  94. package/dist/messages/it/index.d.ts.map +1 -1
  95. package/dist/messages/pt/devtools.json +4 -0
  96. package/dist/messages/pt/index.d.ts +4 -0
  97. package/dist/messages/pt/index.d.ts.map +1 -1
  98. package/dist/nextspark-entities.d.ts +59 -0
  99. package/dist/presets/blocks/cta-section/component.tsx +4 -4
  100. package/dist/presets/blocks/features-grid/component.tsx +5 -5
  101. package/dist/presets/blocks/hero/component.tsx +2 -2
  102. package/dist/presets/blocks/testimonials/component.tsx +4 -4
  103. package/dist/presets/blocks/text-content/component.tsx +2 -2
  104. package/dist/presets/theme/blocks/hero/component.tsx +2 -2
  105. package/dist/presets/theme/tests/cypress/src/core/BlockEditorBasePOM.ts +123 -24
  106. package/dist/styles/classes.json +22 -2
  107. package/dist/styles/ui.css +1 -1
  108. package/dist/templates/app/(public)/[...slug]/page.tsx +2 -1
  109. package/dist/templates/app/(public)/docs/[section]/[page]/page.tsx +1 -1
  110. package/dist/templates/app/api/devtools/config/entities/route.ts +2 -1
  111. package/dist/templates/app/api/user/plan-flags/route.ts +1 -1
  112. package/dist/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +4 -2
  113. package/dist/templates/app/dashboard/(main)/layout.tsx +2 -1
  114. package/dist/templates/app/dashboard/(main)/loading.tsx +5 -0
  115. package/dist/templates/app/dashboard/features/loading.tsx +5 -0
  116. package/dist/templates/app/dashboard/settings/api-keys/loading.tsx +5 -0
  117. package/dist/templates/app/dashboard/settings/billing/loading.tsx +5 -0
  118. package/dist/templates/app/dashboard/settings/invoices/loading.tsx +5 -0
  119. package/dist/templates/app/dashboard/settings/loading.tsx +5 -0
  120. package/dist/templates/app/dashboard/settings/notifications/loading.tsx +5 -0
  121. package/dist/templates/app/dashboard/settings/password/loading.tsx +5 -0
  122. package/dist/templates/app/dashboard/settings/plans/loading.tsx +5 -0
  123. package/dist/templates/app/dashboard/settings/profile/loading.tsx +5 -0
  124. package/dist/templates/app/dashboard/settings/security/loading.tsx +5 -0
  125. package/dist/templates/app/dashboard/settings/teams/loading.tsx +5 -0
  126. package/dist/templates/app/devtools/config/page.tsx +1 -1
  127. package/dist/templates/app/devtools/page.tsx +1 -1
  128. package/dist/templates/app/devtools/tests/[[...path]]/page.tsx +1 -1
  129. package/dist/templates/contents/themes/starter/messages/de/common.json +4 -1
  130. package/dist/templates/contents/themes/starter/messages/de/index.ts +15 -0
  131. package/dist/templates/contents/themes/starter/messages/en/common.json +4 -1
  132. package/dist/templates/contents/themes/starter/messages/en/index.ts +15 -0
  133. package/dist/templates/contents/themes/starter/messages/es/common.json +4 -1
  134. package/dist/templates/contents/themes/starter/messages/es/index.ts +15 -0
  135. package/dist/templates/contents/themes/starter/messages/fr/common.json +4 -1
  136. package/dist/templates/contents/themes/starter/messages/fr/index.ts +15 -0
  137. package/dist/templates/contents/themes/starter/messages/it/common.json +4 -1
  138. package/dist/templates/contents/themes/starter/messages/it/index.ts +13 -0
  139. package/dist/templates/contents/themes/starter/messages/pt/common.json +4 -1
  140. package/dist/templates/contents/themes/starter/messages/pt/index.ts +13 -0
  141. package/dist/templates/contents/themes/starter/styles/globals.css +3 -1
  142. package/dist/templates/contents/themes/starter/templates/(dashboard)/analytics/loading.tsx +5 -0
  143. package/dist/templates/contents/themes/starter/templates/(public)/loading.tsx +5 -0
  144. package/dist/templates/features/blog/blocks/post-content/component.tsx +2 -2
  145. package/dist/templates/features/pages/blocks/hero/component.tsx +2 -2
  146. package/dist/templates/next.config.mjs +10 -3
  147. package/dist/templates/{middleware.ts → proxy.ts} +5 -6
  148. package/globals.css +54 -0
  149. package/nextspark-entities.d.ts +59 -0
  150. package/package.json +18 -16
  151. package/scripts/build/registry/discovery/api-presets.mjs +20 -12
  152. package/scripts/build/registry/generators/api-presets-registry.mjs +18 -5
  153. package/scripts/build/registry/generators/block-registry.mjs +14 -3
  154. package/scripts/build/registry/generators/docs-registry.mjs +21 -3
  155. package/scripts/build/registry/generators/translation-registry.mjs +16 -7
  156. package/scripts/build/theme.mjs +2 -1
  157. package/templates/app/(public)/[...slug]/page.tsx +2 -1
  158. package/templates/app/(public)/docs/[section]/[page]/page.tsx +1 -1
  159. package/templates/app/api/auth/[...all]/route.ts +13 -5
  160. package/templates/app/api/devtools/config/entities/route.ts +2 -1
  161. package/templates/app/api/user/plan-flags/route.ts +1 -1
  162. package/templates/app/api/v1/[entity]/[id]/child/[childType]/[childId]/route.ts +4 -2
  163. package/templates/app/dashboard/(main)/layout.tsx +2 -1
  164. package/templates/app/dashboard/(main)/loading.tsx +5 -0
  165. package/templates/app/dashboard/features/loading.tsx +5 -0
  166. package/templates/app/dashboard/settings/api-keys/loading.tsx +5 -0
  167. package/templates/app/dashboard/settings/billing/loading.tsx +5 -0
  168. package/templates/app/dashboard/settings/invoices/loading.tsx +5 -0
  169. package/templates/app/dashboard/settings/loading.tsx +5 -0
  170. package/templates/app/dashboard/settings/notifications/loading.tsx +5 -0
  171. package/templates/app/dashboard/settings/password/loading.tsx +5 -0
  172. package/templates/app/dashboard/settings/plans/loading.tsx +5 -0
  173. package/templates/app/dashboard/settings/profile/loading.tsx +5 -0
  174. package/templates/app/dashboard/settings/security/loading.tsx +5 -0
  175. package/templates/app/dashboard/settings/teams/loading.tsx +5 -0
  176. package/templates/app/devtools/config/page.tsx +1 -1
  177. package/templates/app/devtools/page.tsx +1 -1
  178. package/templates/app/devtools/tests/[[...path]]/page.tsx +1 -1
  179. package/templates/contents/themes/starter/config/app.config.ts +8 -7
  180. package/templates/contents/themes/starter/messages/de/common.json +4 -1
  181. package/templates/contents/themes/starter/messages/de/index.ts +15 -0
  182. package/templates/contents/themes/starter/messages/en/common.json +4 -1
  183. package/templates/contents/themes/starter/messages/en/index.ts +15 -0
  184. package/templates/contents/themes/starter/messages/es/common.json +4 -1
  185. package/templates/contents/themes/starter/messages/es/index.ts +15 -0
  186. package/templates/contents/themes/starter/messages/fr/common.json +4 -1
  187. package/templates/contents/themes/starter/messages/fr/index.ts +15 -0
  188. package/templates/contents/themes/starter/messages/it/common.json +4 -1
  189. package/templates/contents/themes/starter/messages/it/index.ts +13 -0
  190. package/templates/contents/themes/starter/messages/pt/common.json +4 -1
  191. package/templates/contents/themes/starter/messages/pt/index.ts +13 -0
  192. package/templates/contents/themes/starter/styles/globals.css +3 -1
  193. package/templates/contents/themes/starter/templates/(dashboard)/analytics/loading.tsx +5 -0
  194. package/templates/contents/themes/starter/templates/(public)/loading.tsx +5 -0
  195. package/templates/features/blog/blocks/post-content/component.tsx +2 -2
  196. package/templates/features/pages/blocks/hero/component.tsx +2 -2
  197. package/templates/next.config.mjs +10 -3
  198. package/templates/pnpm-workspace.yaml +5 -0
  199. package/templates/{middleware.ts → proxy.ts} +5 -6
  200. package/tests/jest/setup.ts +5 -0
  201. package/dist/presets/plugin/.env.example.template +0 -19
@@ -1,74 +1,94 @@
1
1
  "use client";
2
2
  import { jsx, jsxs } from "react/jsx-runtime";
3
- import { createContext, useContext, useState, useEffect, useCallback } from "react";
3
+ import { createContext, useContext, useState, useEffect, useCallback, useMemo } from "react";
4
4
  import { useRouter } from "next/navigation";
5
- import { useQueryClient } from "@tanstack/react-query";
5
+ import { useQuery, useQueryClient } from "@tanstack/react-query";
6
6
  import { useAuth } from "../hooks/useAuth.js";
7
7
  import { TeamSwitchModal } from "../components/teams/TeamSwitchModal.js";
8
8
  import { APP_CONFIG_MERGED } from "../lib/config/config-sync.js";
9
9
  import { canUserCreateTeam } from "../lib/teams/helpers.js";
10
10
  const TeamContext = createContext(void 0);
11
+ const TEAMS_QUERY_KEY = ["user-teams"];
12
+ async function fetchUserTeams() {
13
+ const response = await fetch("/api/v1/teams");
14
+ const data = await response.json();
15
+ if (!response.ok || !data.data) {
16
+ throw new Error("Failed to fetch teams");
17
+ }
18
+ return data.data.map((t) => ({
19
+ team: {
20
+ id: t.id,
21
+ name: t.name,
22
+ slug: t.slug,
23
+ description: t.description,
24
+ ownerId: t.owner_id || t.ownerId,
25
+ avatarUrl: t.avatar_url || t.avatarUrl,
26
+ settings: t.settings || {},
27
+ createdAt: t.created_at || t.createdAt,
28
+ updatedAt: t.updated_at || t.updatedAt
29
+ },
30
+ role: t.userRole || t.user_role || t.role,
31
+ joinedAt: t.joinedAt || t.joined_at
32
+ }));
33
+ }
11
34
  function TeamProvider({ children }) {
12
- const { user } = useAuth();
35
+ const { user, isLoading: authLoading } = useAuth();
13
36
  const router = useRouter();
14
37
  const queryClient = useQueryClient();
15
38
  const [currentTeam, setCurrentTeam] = useState(null);
16
- const [userTeams, setUserTeams] = useState([]);
17
- const [isLoading, setIsLoading] = useState(true);
18
39
  const [isSwitching, setIsSwitching] = useState(false);
19
- const [canCurrentUserCreateTeam, setCanCurrentUserCreateTeam] = useState(true);
40
+ const [initialSyncDone, setInitialSyncDone] = useState(false);
20
41
  const [switchModalOpen, setSwitchModalOpen] = useState(false);
21
42
  const [previousTeam, setPreviousTeam] = useState(null);
22
43
  const [targetTeam, setTargetTeam] = useState(null);
23
- const loadUserTeams = useCallback(async () => {
44
+ const {
45
+ data: userTeams = [],
46
+ isLoading: teamsLoading,
47
+ refetch: refetchTeams
48
+ } = useQuery({
49
+ queryKey: TEAMS_QUERY_KEY,
50
+ queryFn: fetchUserTeams,
51
+ enabled: !!user && !authLoading,
52
+ staleTime: 1e3 * 60 * 5,
53
+ // Cache for 5 minutes - prevents refetch on navigation
54
+ gcTime: 1e3 * 60 * 60,
55
+ // Keep in cache for 1 hour
56
+ refetchOnWindowFocus: false,
57
+ // Don't refetch when window regains focus
58
+ refetchOnMount: false
59
+ // Don't refetch if data exists and is not stale
60
+ });
61
+ const isLoading = authLoading || teamsLoading;
62
+ const canCurrentUserCreateTeam = useMemo(() => {
63
+ if (!user || !userTeams.length) return false;
64
+ const { mode, options } = APP_CONFIG_MERGED.teams;
65
+ const ownedTeamsCount = userTeams.filter((m) => m.role === "owner").length;
66
+ return canUserCreateTeam(mode, options || {}, ownedTeamsCount);
67
+ }, [userTeams, user]);
68
+ useEffect(() => {
69
+ if (!userTeams.length || initialSyncDone) return;
70
+ const storedTeamId = typeof window !== "undefined" ? localStorage.getItem("activeTeamId") : null;
71
+ const storedTeam = userTeams.find((t) => t.team.id === storedTeamId);
72
+ const activeTeam = storedTeam || userTeams[0];
73
+ if (activeTeam) {
74
+ setCurrentTeam(activeTeam.team);
75
+ if (typeof window !== "undefined" && storedTeamId !== activeTeam.team.id) {
76
+ localStorage.setItem("activeTeamId", activeTeam.team.id);
77
+ }
78
+ if (typeof window !== "undefined") {
79
+ fetch("/api/v1/teams/switch", {
80
+ method: "POST",
81
+ headers: { "Content-Type": "application/json" },
82
+ body: JSON.stringify({ teamId: activeTeam.team.id })
83
+ }).catch((err) => console.error("Failed to sync team cookie:", err));
84
+ }
85
+ setInitialSyncDone(true);
86
+ }
87
+ }, [userTeams, initialSyncDone]);
88
+ useEffect(() => {
24
89
  if (!user) {
25
- setUserTeams([]);
26
90
  setCurrentTeam(null);
27
- setIsLoading(false);
28
- return;
29
- }
30
- try {
31
- setIsLoading(true);
32
- const response = await fetch("/api/v1/teams");
33
- const data = await response.json();
34
- if (response.ok && data.data) {
35
- const teams = data.data.map((t) => ({
36
- team: {
37
- id: t.id,
38
- name: t.name,
39
- slug: t.slug,
40
- description: t.description,
41
- ownerId: t.owner_id || t.ownerId,
42
- avatarUrl: t.avatar_url || t.avatarUrl,
43
- settings: t.settings || {},
44
- createdAt: t.created_at || t.createdAt,
45
- updatedAt: t.updated_at || t.updatedAt
46
- },
47
- role: t.userRole || t.user_role || t.role,
48
- joinedAt: t.joinedAt || t.joined_at
49
- }));
50
- setUserTeams(teams);
51
- const storedTeamId = typeof window !== "undefined" ? localStorage.getItem("activeTeamId") : null;
52
- const storedTeam = teams.find((t) => t.team.id === storedTeamId);
53
- const activeTeam = storedTeam || teams[0];
54
- if (activeTeam) {
55
- setCurrentTeam(activeTeam.team);
56
- if (typeof window !== "undefined" && storedTeamId !== activeTeam.team.id) {
57
- localStorage.setItem("activeTeamId", activeTeam.team.id);
58
- }
59
- if (typeof window !== "undefined") {
60
- fetch("/api/v1/teams/switch", {
61
- method: "POST",
62
- headers: { "Content-Type": "application/json" },
63
- body: JSON.stringify({ teamId: activeTeam.team.id })
64
- }).catch((err) => console.error("Failed to sync team cookie:", err));
65
- }
66
- }
67
- }
68
- } catch (error) {
69
- console.error("Failed to load teams:", error);
70
- } finally {
71
- setIsLoading(false);
91
+ setInitialSyncDone(false);
72
92
  }
73
93
  }, [user]);
74
94
  const handleSwitchComplete = useCallback(() => {
@@ -109,21 +129,9 @@ function TeamProvider({ children }) {
109
129
  }
110
130
  }, [userTeams, currentTeam]);
111
131
  const refreshTeams = useCallback(async () => {
112
- await loadUserTeams();
113
- }, [loadUserTeams]);
114
- useEffect(() => {
115
- loadUserTeams();
116
- }, [loadUserTeams]);
117
- useEffect(() => {
118
- if (!user || !userTeams) {
119
- setCanCurrentUserCreateTeam(false);
120
- return;
121
- }
122
- const { mode, options } = APP_CONFIG_MERGED.teams;
123
- const ownedTeamsCount = userTeams.filter((m) => m.role === "owner").length;
124
- const canCreate = canUserCreateTeam(mode, options || {}, ownedTeamsCount);
125
- setCanCurrentUserCreateTeam(canCreate);
126
- }, [userTeams, user]);
132
+ await queryClient.invalidateQueries({ queryKey: TEAMS_QUERY_KEY });
133
+ await refetchTeams();
134
+ }, [queryClient, refetchTeams]);
127
135
  return /* @__PURE__ */ jsxs(
128
136
  TeamContext.Provider,
129
137
  {
@@ -159,6 +167,8 @@ function useTeamContext() {
159
167
  return context;
160
168
  }
161
169
  export {
170
+ TEAMS_QUERY_KEY,
162
171
  TeamProvider,
172
+ fetchUserTeams,
163
173
  useTeamContext
164
174
  };
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Hook to prefetch settings page data on hover
3
+ *
4
+ * @example
5
+ * ```tsx
6
+ * function SettingsSidebar() {
7
+ * const { prefetchProfile, prefetchTeams } = usePrefetchSettings()
8
+ *
9
+ * return (
10
+ * <nav>
11
+ * <Link href="/dashboard/settings/profile" onMouseEnter={prefetchProfile}>
12
+ * Profile
13
+ * </Link>
14
+ * <Link href="/dashboard/settings/teams" onMouseEnter={prefetchTeams}>
15
+ * Teams
16
+ * </Link>
17
+ * </nav>
18
+ * )
19
+ * }
20
+ * ```
21
+ */
22
+ export declare function usePrefetchSettings(): {
23
+ prefetchProfile: () => void;
24
+ prefetchTeams: () => void;
25
+ };
26
+ /**
27
+ * Generic prefetch hook for any entity list
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * function EntityNav() {
32
+ * const prefetchProducts = usePrefetchEntity('products')
33
+ *
34
+ * return (
35
+ * <Link href="/dashboard/products" onMouseEnter={prefetchProducts}>
36
+ * Products
37
+ * </Link>
38
+ * )
39
+ * }
40
+ * ```
41
+ */
42
+ export declare function usePrefetchEntity(entitySlug: string): () => void;
43
+ //# sourceMappingURL=usePrefetch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePrefetch.d.ts","sourceRoot":"","sources":["../../src/hooks/usePrefetch.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB;;;EAuBlC;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,UAAU,EAAE,MAAM,cAgBnD"}
@@ -0,0 +1,56 @@
1
+ "use client";
2
+ import { useQueryClient } from "@tanstack/react-query";
3
+ import { useCallback } from "react";
4
+ import { TEAMS_QUERY_KEY, fetchUserTeams } from "../contexts/TeamContext.js";
5
+ const USER_PROFILE_QUERY_KEY = ["user-profile"];
6
+ async function fetchUserProfile() {
7
+ const response = await fetch("/api/user/profile");
8
+ if (!response.ok) {
9
+ throw new Error("Failed to fetch profile");
10
+ }
11
+ return response.json();
12
+ }
13
+ function usePrefetchSettings() {
14
+ const queryClient = useQueryClient();
15
+ const prefetchProfile = useCallback(() => {
16
+ queryClient.prefetchQuery({
17
+ queryKey: USER_PROFILE_QUERY_KEY,
18
+ queryFn: fetchUserProfile,
19
+ staleTime: 1e3 * 60 * 5
20
+ // 5 minutes
21
+ });
22
+ }, [queryClient]);
23
+ const prefetchTeams = useCallback(() => {
24
+ queryClient.prefetchQuery({
25
+ queryKey: TEAMS_QUERY_KEY,
26
+ queryFn: fetchUserTeams,
27
+ staleTime: 1e3 * 60 * 5
28
+ // 5 minutes
29
+ });
30
+ }, [queryClient]);
31
+ return {
32
+ prefetchProfile,
33
+ prefetchTeams
34
+ };
35
+ }
36
+ function usePrefetchEntity(entitySlug) {
37
+ const queryClient = useQueryClient();
38
+ return useCallback(() => {
39
+ queryClient.prefetchQuery({
40
+ queryKey: ["entity", entitySlug, "list"],
41
+ queryFn: async () => {
42
+ const response = await fetch(`/api/v1/${entitySlug}?limit=20`);
43
+ if (!response.ok) {
44
+ throw new Error(`Failed to fetch ${entitySlug}`);
45
+ }
46
+ return response.json();
47
+ },
48
+ staleTime: 1e3 * 60 * 2
49
+ // 2 minutes for entity lists
50
+ });
51
+ }, [queryClient, entitySlug]);
52
+ }
53
+ export {
54
+ usePrefetchEntity,
55
+ usePrefetchSettings
56
+ };
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Entity Server Actions
2
+ * NextSpark Server Actions
3
3
  *
4
- * Generic Server Actions for CRUD operations on any registered entity.
4
+ * Server Actions for CRUD operations, user management, and team management.
5
5
  * Auth (userId/teamId) is obtained automatically from session and cookies.
6
6
  *
7
7
  * Import from '@nextsparkjs/core/actions' or '@nextsparkjs/core/lib/actions'.
@@ -9,31 +9,44 @@
9
9
  * @example
10
10
  * ```typescript
11
11
  * import {
12
+ * // Entity actions
12
13
  * createEntity,
13
14
  * updateEntity,
14
15
  * deleteEntity,
15
16
  * getEntity,
16
17
  * listEntities,
18
+ * // User actions
19
+ * updateProfile,
20
+ * updateAvatar,
21
+ * deleteAccount,
22
+ * // Team actions
23
+ * updateTeam,
24
+ * inviteMember,
25
+ * removeMember,
26
+ * updateMemberRole,
17
27
  * } from '@nextsparkjs/core/actions'
18
28
  *
19
- * // Create - auth obtained from server session
29
+ * // Entity operations - auth obtained from server session
20
30
  * const result = await createEntity('schools', { name: 'MIT' })
21
- *
22
- * // Update with revalidation
23
- * await updateEntity('campaigns', id, { status: 'paused' }, {
24
- * revalidatePaths: ['/dashboard']
25
- * })
26
- *
27
- * // Delete with redirect
31
+ * await updateEntity('campaigns', id, { status: 'paused' })
28
32
  * await deleteEntity('leads', id, { redirectTo: '/leads' })
29
33
  *
30
- * // Get by ID
31
- * const entity = await getEntity('schools', id)
34
+ * // User profile operations
35
+ * await updateProfile({ firstName: 'John', lastName: 'Doe' })
36
+ * await updateAvatar(formData)
37
+ * await deleteAccount()
32
38
  *
33
- * // List with filters
34
- * const list = await listEntities('campaigns', { limit: 20, where: { status: 'active' } })
39
+ * // Team operations
40
+ * await updateTeam('team-id', { name: 'New Name' })
41
+ * await inviteMember('team-id', 'user@example.com', 'member')
42
+ * await removeMember('team-id', 'member-id')
43
+ * await updateMemberRole('team-id', 'member-id', 'admin')
35
44
  * ```
36
45
  */
37
46
  export { createEntity, updateEntity, deleteEntity, getEntity, listEntities, deleteEntities, entityExists, countEntities, } from './entity.actions';
47
+ export { updateProfile, updateAvatar, deleteAccount, } from './user.actions';
48
+ export type { UpdateProfileData, ProfileUpdateResult, } from './user.actions';
49
+ export { updateTeam, inviteMember, removeMember, updateMemberRole, } from './team.actions';
50
+ export type { UpdateTeamData, InviteMemberResult, } from './team.actions';
38
51
  export type { EntityActionResult, EntityActionVoidResult, CreateEntityInput, UpdateEntityInput, ListEntityOptions, ListEntityResult, ActionConfig, ActionAuthContext, BatchDeleteResult, } from './types';
39
52
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAGH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,kBAAkB,CAAA;AAGzB,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAMH,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,cAAc,EACd,YAAY,EACZ,aAAa,GACd,MAAM,kBAAkB,CAAA;AAMzB,OAAO,EACL,aAAa,EACb,YAAY,EACZ,aAAa,GACd,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,iBAAiB,EACjB,mBAAmB,GACpB,MAAM,gBAAgB,CAAA;AAMvB,OAAO,EACL,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,gBAAgB,GACjB,MAAM,gBAAgB,CAAA;AAEvB,YAAY,EACV,cAAc,EACd,kBAAkB,GACnB,MAAM,gBAAgB,CAAA;AAMvB,YAAY,EACV,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,YAAY,EACZ,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,SAAS,CAAA"}
@@ -8,13 +8,31 @@ import {
8
8
  entityExists,
9
9
  countEntities
10
10
  } from "./entity.actions.js";
11
+ import {
12
+ updateProfile,
13
+ updateAvatar,
14
+ deleteAccount
15
+ } from "./user.actions.js";
16
+ import {
17
+ updateTeam,
18
+ inviteMember,
19
+ removeMember,
20
+ updateMemberRole
21
+ } from "./team.actions.js";
11
22
  export {
12
23
  countEntities,
13
24
  createEntity,
25
+ deleteAccount,
14
26
  deleteEntities,
15
27
  deleteEntity,
16
28
  entityExists,
17
29
  getEntity,
30
+ inviteMember,
18
31
  listEntities,
19
- updateEntity
32
+ removeMember,
33
+ updateAvatar,
34
+ updateEntity,
35
+ updateMemberRole,
36
+ updateProfile,
37
+ updateTeam
20
38
  };
@@ -0,0 +1,107 @@
1
+ import type { Team, TeamRole, TeamMember } from '../teams/types';
2
+ import type { EntityActionResult, EntityActionVoidResult } from './types';
3
+ /**
4
+ * Team update data that can be passed to updateTeam
5
+ */
6
+ export interface UpdateTeamData {
7
+ name?: string;
8
+ slug?: string;
9
+ description?: string;
10
+ avatarUrl?: string;
11
+ settings?: Record<string, unknown>;
12
+ }
13
+ /**
14
+ * Result of invite member action
15
+ */
16
+ export interface InviteMemberResult {
17
+ memberId: string;
18
+ userId: string;
19
+ teamId: string;
20
+ role: TeamRole;
21
+ }
22
+ /**
23
+ * Update a team's information
24
+ *
25
+ * Requires owner or admin role in the team.
26
+ *
27
+ * @param teamId - The team ID to update
28
+ * @param data - Team fields to update
29
+ * @returns Updated team data wrapped in EntityActionResult
30
+ *
31
+ * @example
32
+ * ```typescript
33
+ * const result = await updateTeam('team-123', {
34
+ * name: 'New Team Name',
35
+ * description: 'Updated description'
36
+ * })
37
+ *
38
+ * if (result.success) {
39
+ * console.log('Team updated:', result.data.name)
40
+ * }
41
+ * ```
42
+ */
43
+ export declare function updateTeam(teamId: string, data: UpdateTeamData): Promise<EntityActionResult<Team>>;
44
+ /**
45
+ * Invite a user to join the team
46
+ *
47
+ * Requires owner or admin role in the team.
48
+ * The user must already exist in the system.
49
+ *
50
+ * @param teamId - The team ID
51
+ * @param email - Email of the user to invite
52
+ * @param role - Role to assign (member, admin, viewer)
53
+ * @returns Created membership data wrapped in EntityActionResult
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * const result = await inviteMember('team-123', 'user@example.com', 'member')
58
+ *
59
+ * if (result.success) {
60
+ * console.log('Member invited:', result.data.memberId)
61
+ * }
62
+ * ```
63
+ */
64
+ export declare function inviteMember(teamId: string, email: string, role?: TeamRole): Promise<EntityActionResult<InviteMemberResult>>;
65
+ /**
66
+ * Remove a member from the team
67
+ *
68
+ * Requires owner or admin role in the team.
69
+ * Cannot remove the team owner (must transfer ownership first).
70
+ *
71
+ * @param teamId - The team ID
72
+ * @param memberId - The member ID to remove (from team_members table)
73
+ * @returns Success status
74
+ *
75
+ * @example
76
+ * ```typescript
77
+ * const result = await removeMember('team-123', 'member-id-456')
78
+ *
79
+ * if (result.success) {
80
+ * console.log('Member removed')
81
+ * }
82
+ * ```
83
+ */
84
+ export declare function removeMember(teamId: string, memberId: string): Promise<EntityActionVoidResult>;
85
+ /**
86
+ * Update a team member's role
87
+ *
88
+ * Requires owner role to change to/from admin.
89
+ * Admins can change member/viewer roles.
90
+ * Cannot change owner role (must transfer ownership).
91
+ *
92
+ * @param teamId - The team ID
93
+ * @param memberId - The member's user ID
94
+ * @param role - New role to assign
95
+ * @returns Updated membership data wrapped in EntityActionResult
96
+ *
97
+ * @example
98
+ * ```typescript
99
+ * const result = await updateMemberRole('team-123', 'user-456', 'admin')
100
+ *
101
+ * if (result.success) {
102
+ * console.log('Role updated:', result.data.role)
103
+ * }
104
+ * ```
105
+ */
106
+ export declare function updateMemberRole(teamId: string, memberId: string, role: TeamRole): Promise<EntityActionResult<TeamMember>>;
107
+ //# sourceMappingURL=team.actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"team.actions.d.ts","sourceRoot":"","sources":["../../../src/lib/actions/team.actions.ts"],"names":[],"mappings":"AA4CA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChE,OAAO,KAAK,EAAE,kBAAkB,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAA;AAMzE;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACnC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,QAAQ,CAAA;CACf;AAgDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,UAAU,CAC9B,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,cAAc,GACnB,OAAO,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CA4DnC;AAMD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,KAAK,EAAE,MAAM,EACb,IAAI,GAAE,QAAmB,GACxB,OAAO,CAAC,kBAAkB,CAAC,kBAAkB,CAAC,CAAC,CAqEjD;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC,CAgEjC;AAMD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,kBAAkB,CAAC,UAAU,CAAC,CAAC,CAsEzC"}