@nextsparkjs/mobile 0.1.0-beta.1

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 (123) hide show
  1. package/README.md +339 -0
  2. package/dist/api/client.d.ts +102 -0
  3. package/dist/api/client.js +189 -0
  4. package/dist/api/client.js.map +1 -0
  5. package/dist/api/client.types.d.ts +39 -0
  6. package/dist/api/client.types.js +12 -0
  7. package/dist/api/client.types.js.map +1 -0
  8. package/dist/api/core/auth.d.ts +26 -0
  9. package/dist/api/core/auth.js +52 -0
  10. package/dist/api/core/auth.js.map +1 -0
  11. package/dist/api/core/index.d.ts +4 -0
  12. package/dist/api/core/index.js +5 -0
  13. package/dist/api/core/index.js.map +1 -0
  14. package/dist/api/core/teams.d.ts +20 -0
  15. package/dist/api/core/teams.js +19 -0
  16. package/dist/api/core/teams.js.map +1 -0
  17. package/dist/api/core/types.d.ts +58 -0
  18. package/dist/api/core/types.js +1 -0
  19. package/dist/api/core/types.js.map +1 -0
  20. package/dist/api/core/users.d.ts +43 -0
  21. package/dist/api/core/users.js +41 -0
  22. package/dist/api/core/users.js.map +1 -0
  23. package/dist/api/entities/factory.d.ts +43 -0
  24. package/dist/api/entities/factory.js +31 -0
  25. package/dist/api/entities/factory.js.map +1 -0
  26. package/dist/api/entities/index.d.ts +3 -0
  27. package/dist/api/entities/index.js +3 -0
  28. package/dist/api/entities/index.js.map +1 -0
  29. package/dist/api/entities/types.d.ts +32 -0
  30. package/dist/api/entities/types.js +1 -0
  31. package/dist/api/entities/types.js.map +1 -0
  32. package/dist/api/index.d.ts +7 -0
  33. package/dist/api/index.js +15 -0
  34. package/dist/api/index.js.map +1 -0
  35. package/dist/hooks/index.d.ts +4 -0
  36. package/dist/hooks/index.js +5 -0
  37. package/dist/hooks/index.js.map +1 -0
  38. package/dist/index.d.ts +14 -0
  39. package/dist/index.js +28 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/lib/alert.d.ts +34 -0
  42. package/dist/lib/alert.js +73 -0
  43. package/dist/lib/alert.js.map +1 -0
  44. package/dist/lib/index.d.ts +2 -0
  45. package/dist/lib/index.js +10 -0
  46. package/dist/lib/index.js.map +1 -0
  47. package/dist/lib/storage.d.ts +1 -0
  48. package/dist/lib/storage.js +29 -0
  49. package/dist/lib/storage.js.map +1 -0
  50. package/dist/providers/AuthProvider.d.ts +21 -0
  51. package/dist/providers/AuthProvider.js +113 -0
  52. package/dist/providers/AuthProvider.js.map +1 -0
  53. package/dist/providers/QueryProvider.d.ts +11 -0
  54. package/dist/providers/QueryProvider.js +23 -0
  55. package/dist/providers/QueryProvider.js.map +1 -0
  56. package/dist/providers/index.d.ts +6 -0
  57. package/dist/providers/index.js +9 -0
  58. package/dist/providers/index.js.map +1 -0
  59. package/dist/storage-BaRppHUz.d.ts +22 -0
  60. package/package.json +99 -0
  61. package/templates/app/(app)/_layout.tsx +216 -0
  62. package/templates/app/(app)/customer/[id].tsx +68 -0
  63. package/templates/app/(app)/customer/create.tsx +24 -0
  64. package/templates/app/(app)/customers.tsx +164 -0
  65. package/templates/app/(app)/index.tsx +310 -0
  66. package/templates/app/(app)/notifications.tsx +242 -0
  67. package/templates/app/(app)/profile.tsx +254 -0
  68. package/templates/app/(app)/settings.tsx +241 -0
  69. package/templates/app/(app)/task/[id].tsx +70 -0
  70. package/templates/app/(app)/task/create.tsx +24 -0
  71. package/templates/app/(app)/tasks.tsx +164 -0
  72. package/templates/app/_layout.tsx +54 -0
  73. package/templates/app/index.tsx +35 -0
  74. package/templates/app/login.tsx +179 -0
  75. package/templates/app.config.ts +39 -0
  76. package/templates/babel.config.js +9 -0
  77. package/templates/eas.json +18 -0
  78. package/templates/jest.config.js +12 -0
  79. package/templates/metro.config.js +23 -0
  80. package/templates/package.json.template +52 -0
  81. package/templates/src/components/entities/customers/CustomerCard.tsx +59 -0
  82. package/templates/src/components/entities/customers/CustomerForm.tsx +194 -0
  83. package/templates/src/components/entities/customers/index.ts +6 -0
  84. package/templates/src/components/entities/index.ts +9 -0
  85. package/templates/src/components/entities/tasks/TaskCard.tsx +89 -0
  86. package/templates/src/components/entities/tasks/TaskForm.tsx +231 -0
  87. package/templates/src/components/entities/tasks/index.ts +6 -0
  88. package/templates/src/components/features/index.ts +6 -0
  89. package/templates/src/components/navigation/BottomTabBar.tsx +80 -0
  90. package/templates/src/components/navigation/CreateSheet.tsx +108 -0
  91. package/templates/src/components/navigation/MoreSheet.tsx +403 -0
  92. package/templates/src/components/navigation/TopBar.tsx +74 -0
  93. package/templates/src/components/navigation/index.ts +8 -0
  94. package/templates/src/components/ui/index.ts +89 -0
  95. package/templates/src/components/ui/text.tsx +64 -0
  96. package/templates/src/config/api.config.ts +26 -0
  97. package/templates/src/config/app.config.ts +15 -0
  98. package/templates/src/config/hooks.ts +58 -0
  99. package/templates/src/config/permissions.config.ts +119 -0
  100. package/templates/src/constants/colors.ts +55 -0
  101. package/templates/src/data/notifications.mock.json +100 -0
  102. package/templates/src/entities/customers/api.ts +10 -0
  103. package/templates/src/entities/customers/constants.internal.ts +6 -0
  104. package/templates/src/entities/customers/constants.ts +14 -0
  105. package/templates/src/entities/customers/index.ts +9 -0
  106. package/templates/src/entities/customers/mutations.ts +58 -0
  107. package/templates/src/entities/customers/queries.ts +40 -0
  108. package/templates/src/entities/customers/types.ts +43 -0
  109. package/templates/src/entities/index.ts +8 -0
  110. package/templates/src/entities/tasks/api.ts +10 -0
  111. package/templates/src/entities/tasks/constants.internal.ts +6 -0
  112. package/templates/src/entities/tasks/constants.ts +39 -0
  113. package/templates/src/entities/tasks/index.ts +9 -0
  114. package/templates/src/entities/tasks/mutations.ts +108 -0
  115. package/templates/src/entities/tasks/queries.ts +42 -0
  116. package/templates/src/entities/tasks/types.ts +52 -0
  117. package/templates/src/hooks/useCustomers.ts +17 -0
  118. package/templates/src/hooks/useTasks.ts +18 -0
  119. package/templates/src/lib/utils.ts +10 -0
  120. package/templates/src/styles/globals.css +103 -0
  121. package/templates/src/types/index.ts +45 -0
  122. package/templates/tailwind.config.js +108 -0
  123. package/templates/tsconfig.json +15 -0
@@ -0,0 +1,26 @@
1
+ import { LoginResponse, SessionResponse } from './types.js';
2
+
3
+ /**
4
+ * Auth API Service
5
+ *
6
+ * Authentication operations: login, logout, session management.
7
+ */
8
+
9
+ declare const authApi: {
10
+ /**
11
+ * Login with email and password
12
+ * Better Auth returns user and session info
13
+ */
14
+ login(email: string, password: string): Promise<LoginResponse>;
15
+ /**
16
+ * Logout - clear local auth and call server signout
17
+ */
18
+ logout(): Promise<void>;
19
+ /**
20
+ * Get current session from server
21
+ * Used to validate stored credentials and get fresh user data
22
+ */
23
+ getSession(): Promise<SessionResponse | null>;
24
+ };
25
+
26
+ export { authApi };
@@ -0,0 +1,52 @@
1
+ import { apiClient } from '../client.js';
2
+ import { ApiError } from '../client.types.js';
3
+ const authApi = {
4
+ /**
5
+ * Login with email and password
6
+ * Better Auth returns user and session info
7
+ */
8
+ async login(email, password) {
9
+ const response = await apiClient.post("/api/auth/sign-in/email", {
10
+ email,
11
+ password
12
+ });
13
+ await apiClient.setUser(response.user);
14
+ if (response.session?.token) {
15
+ await apiClient.setToken(response.session.token);
16
+ }
17
+ return response;
18
+ },
19
+ /**
20
+ * Logout - clear local auth and call server signout
21
+ */
22
+ async logout() {
23
+ try {
24
+ await apiClient.post("/api/auth/sign-out");
25
+ } catch (error) {
26
+ console.warn("[AuthApi] Failed to sign out from server:", error);
27
+ }
28
+ await apiClient.clearAuth();
29
+ },
30
+ /**
31
+ * Get current session from server
32
+ * Used to validate stored credentials and get fresh user data
33
+ */
34
+ async getSession() {
35
+ try {
36
+ const response = await apiClient.get("/api/auth/get-session");
37
+ if (response.user) {
38
+ await apiClient.setUser(response.user);
39
+ }
40
+ return response;
41
+ } catch (error) {
42
+ if (error instanceof ApiError && error.status === 401) {
43
+ return null;
44
+ }
45
+ throw error;
46
+ }
47
+ }
48
+ };
49
+ export {
50
+ authApi
51
+ };
52
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/core/auth.ts"],"sourcesContent":["/**\n * Auth API Service\n *\n * Authentication operations: login, logout, session management.\n */\n\nimport { apiClient } from '../client'\nimport { ApiError } from '../client.types'\nimport type { LoginResponse, SessionResponse } from './types'\n\nexport const authApi = {\n /**\n * Login with email and password\n * Better Auth returns user and session info\n */\n async login(email: string, password: string): Promise<LoginResponse> {\n const response = await apiClient.post<LoginResponse>('/api/auth/sign-in/email', {\n email,\n password,\n })\n\n // Store user info for session restoration\n await apiClient.setUser(response.user)\n\n // Store token if provided (Better Auth may return it for mobile clients)\n if (response.session?.token) {\n await apiClient.setToken(response.session.token)\n }\n\n return response\n },\n\n /**\n * Logout - clear local auth and call server signout\n */\n async logout(): Promise<void> {\n try {\n // Call server signout endpoint to invalidate session\n await apiClient.post('/api/auth/sign-out')\n } catch (error) {\n // Log error for debugging but continue with local cleanup\n // Server session may remain active if this fails (network issues)\n console.warn('[AuthApi] Failed to sign out from server:', error)\n }\n await apiClient.clearAuth()\n },\n\n /**\n * Get current session from server\n * Used to validate stored credentials and get fresh user data\n */\n async getSession(): Promise<SessionResponse | null> {\n try {\n const response = await apiClient.get<SessionResponse>('/api/auth/get-session')\n\n // Update stored user with fresh data\n if (response.user) {\n await apiClient.setUser(response.user)\n }\n\n return response\n } catch (error) {\n // Session invalid or expired\n if (error instanceof ApiError && error.status === 401) {\n return null\n }\n throw error\n }\n },\n}\n"],"mappings":"AAMA,SAAS,iBAAiB;AAC1B,SAAS,gBAAgB;AAGlB,MAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA,EAKrB,MAAM,MAAM,OAAe,UAA0C;AACnE,UAAM,WAAW,MAAM,UAAU,KAAoB,2BAA2B;AAAA,MAC9E;AAAA,MACA;AAAA,IACF,CAAC;AAGD,UAAM,UAAU,QAAQ,SAAS,IAAI;AAGrC,QAAI,SAAS,SAAS,OAAO;AAC3B,YAAM,UAAU,SAAS,SAAS,QAAQ,KAAK;AAAA,IACjD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAwB;AAC5B,QAAI;AAEF,YAAM,UAAU,KAAK,oBAAoB;AAAA,IAC3C,SAAS,OAAO;AAGd,cAAQ,KAAK,6CAA6C,KAAK;AAAA,IACjE;AACA,UAAM,UAAU,UAAU;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,aAA8C;AAClD,QAAI;AACF,YAAM,WAAW,MAAM,UAAU,IAAqB,uBAAuB;AAG7E,UAAI,SAAS,MAAM;AACjB,cAAM,UAAU,QAAQ,SAAS,IAAI;AAAA,MACvC;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,UAAI,iBAAiB,YAAY,MAAM,WAAW,KAAK;AACrD,eAAO;AAAA,MACT;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;","names":[]}
@@ -0,0 +1,4 @@
1
+ export { authApi } from './auth.js';
2
+ export { teamsApi } from './teams.js';
3
+ export { UpdateProfileInput, UserPreferences, usersApi } from './users.js';
4
+ export { AuthSession, LoginResponse, SessionResponse, Team, TeamsResponse, User } from './types.js';
@@ -0,0 +1,5 @@
1
+ export * from './auth.js';
2
+ export * from './teams.js';
3
+ export * from './users.js';
4
+ export * from './types.js';
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/core/index.ts"],"sourcesContent":["/**\n * Core API Services\n *\n * Authentication, teams, and user management.\n */\n\nexport * from './auth'\nexport * from './teams'\nexport * from './users'\nexport * from './types'\n"],"mappings":"AAMA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,20 @@
1
+ import { TeamsResponse } from './types.js';
2
+
3
+ /**
4
+ * Teams API Service
5
+ *
6
+ * Team management operations.
7
+ */
8
+
9
+ declare const teamsApi: {
10
+ /**
11
+ * Get user's teams
12
+ */
13
+ getTeams(): Promise<TeamsResponse>;
14
+ /**
15
+ * Switch to a different team
16
+ */
17
+ switchTeam(teamId: string): Promise<void>;
18
+ };
19
+
20
+ export { teamsApi };
@@ -0,0 +1,19 @@
1
+ import { apiClient } from '../client.js';
2
+ const teamsApi = {
3
+ /**
4
+ * Get user's teams
5
+ */
6
+ async getTeams() {
7
+ return apiClient.get("/api/v1/teams");
8
+ },
9
+ /**
10
+ * Switch to a different team
11
+ */
12
+ async switchTeam(teamId) {
13
+ await apiClient.setTeamId(teamId);
14
+ }
15
+ };
16
+ export {
17
+ teamsApi
18
+ };
19
+ //# sourceMappingURL=teams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/core/teams.ts"],"sourcesContent":["/**\n * Teams API Service\n *\n * Team management operations.\n */\n\nimport { apiClient } from '../client'\nimport type { TeamsResponse } from './types'\n\nexport const teamsApi = {\n /**\n * Get user's teams\n */\n async getTeams(): Promise<TeamsResponse> {\n return apiClient.get<TeamsResponse>('/api/v1/teams')\n },\n\n /**\n * Switch to a different team\n */\n async switchTeam(teamId: string): Promise<void> {\n await apiClient.setTeamId(teamId)\n },\n}\n"],"mappings":"AAMA,SAAS,iBAAiB;AAGnB,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA,EAItB,MAAM,WAAmC;AACvC,WAAO,UAAU,IAAmB,eAAe;AAAA,EACrD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,WAAW,QAA+B;AAC9C,UAAM,UAAU,UAAU,MAAM;AAAA,EAClC;AACF;","names":[]}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Core API Types
3
+ *
4
+ * Types for authentication, users, and teams.
5
+ */
6
+ /**
7
+ * User entity
8
+ */
9
+ interface User {
10
+ id: string;
11
+ email: string;
12
+ name?: string | null;
13
+ image?: string | null;
14
+ }
15
+ /**
16
+ * Team entity (from /api/v1/teams)
17
+ */
18
+ interface Team {
19
+ id: string;
20
+ name: string;
21
+ slug?: string;
22
+ logo?: string | null;
23
+ role: string;
24
+ }
25
+ /**
26
+ * Auth session info
27
+ */
28
+ interface AuthSession {
29
+ token: string;
30
+ user: User;
31
+ }
32
+ /**
33
+ * Login response from Better Auth
34
+ */
35
+ interface LoginResponse {
36
+ user: User;
37
+ session: {
38
+ token: string;
39
+ };
40
+ }
41
+ /**
42
+ * Session response from Better Auth
43
+ */
44
+ interface SessionResponse {
45
+ user: User | null;
46
+ session: {
47
+ id: string;
48
+ expiresAt: string;
49
+ } | null;
50
+ }
51
+ /**
52
+ * Teams list response
53
+ */
54
+ interface TeamsResponse {
55
+ data: Team[];
56
+ }
57
+
58
+ export type { AuthSession, LoginResponse, SessionResponse, Team, TeamsResponse, User };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,43 @@
1
+ import { User } from './types.js';
2
+
3
+ /**
4
+ * Users API Service
5
+ *
6
+ * User profile and preferences operations.
7
+ */
8
+
9
+ /**
10
+ * Profile update input
11
+ */
12
+ interface UpdateProfileInput {
13
+ name?: string;
14
+ image?: string | null;
15
+ }
16
+ /**
17
+ * User preferences
18
+ */
19
+ interface UserPreferences {
20
+ theme?: 'light' | 'dark' | 'system';
21
+ notifications?: boolean;
22
+ language?: string;
23
+ }
24
+ declare const usersApi: {
25
+ /**
26
+ * Get current authenticated user
27
+ */
28
+ getCurrentUser(): Promise<User>;
29
+ /**
30
+ * Update user profile
31
+ */
32
+ updateProfile(data: UpdateProfileInput): Promise<User>;
33
+ /**
34
+ * Update user preferences
35
+ */
36
+ updatePreferences(preferences: UserPreferences): Promise<UserPreferences>;
37
+ /**
38
+ * Get user preferences
39
+ */
40
+ getPreferences(): Promise<UserPreferences>;
41
+ };
42
+
43
+ export { type UpdateProfileInput, type UserPreferences, usersApi };
@@ -0,0 +1,41 @@
1
+ import { apiClient } from '../client.js';
2
+ const usersApi = {
3
+ /**
4
+ * Get current authenticated user
5
+ */
6
+ async getCurrentUser() {
7
+ const response = await apiClient.get("/api/v1/users/me");
8
+ return response.data;
9
+ },
10
+ /**
11
+ * Update user profile
12
+ */
13
+ async updateProfile(data) {
14
+ const response = await apiClient.patch("/api/v1/users/me", data);
15
+ await apiClient.setUser(response.data);
16
+ return response.data;
17
+ },
18
+ /**
19
+ * Update user preferences
20
+ */
21
+ async updatePreferences(preferences) {
22
+ const response = await apiClient.patch(
23
+ "/api/v1/users/me/preferences",
24
+ preferences
25
+ );
26
+ return response.data;
27
+ },
28
+ /**
29
+ * Get user preferences
30
+ */
31
+ async getPreferences() {
32
+ const response = await apiClient.get(
33
+ "/api/v1/users/me/preferences"
34
+ );
35
+ return response.data;
36
+ }
37
+ };
38
+ export {
39
+ usersApi
40
+ };
41
+ //# sourceMappingURL=users.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/core/users.ts"],"sourcesContent":["/**\n * Users API Service\n *\n * User profile and preferences operations.\n */\n\nimport { apiClient } from '../client'\nimport type { SingleResponse } from '../client.types'\nimport type { User } from './types'\n\n/**\n * Profile update input\n */\nexport interface UpdateProfileInput {\n name?: string\n image?: string | null\n}\n\n/**\n * User preferences\n */\nexport interface UserPreferences {\n theme?: 'light' | 'dark' | 'system'\n notifications?: boolean\n language?: string\n}\n\nexport const usersApi = {\n /**\n * Get current authenticated user\n */\n async getCurrentUser(): Promise<User> {\n const response = await apiClient.get<SingleResponse<User>>('/api/v1/users/me')\n return response.data\n },\n\n /**\n * Update user profile\n */\n async updateProfile(data: UpdateProfileInput): Promise<User> {\n const response = await apiClient.patch<SingleResponse<User>>('/api/v1/users/me', data)\n\n // Update stored user with new data\n await apiClient.setUser(response.data)\n\n return response.data\n },\n\n /**\n * Update user preferences\n */\n async updatePreferences(preferences: UserPreferences): Promise<UserPreferences> {\n const response = await apiClient.patch<SingleResponse<UserPreferences>>(\n '/api/v1/users/me/preferences',\n preferences\n )\n return response.data\n },\n\n /**\n * Get user preferences\n */\n async getPreferences(): Promise<UserPreferences> {\n const response = await apiClient.get<SingleResponse<UserPreferences>>(\n '/api/v1/users/me/preferences'\n )\n return response.data\n },\n}\n"],"mappings":"AAMA,SAAS,iBAAiB;AAqBnB,MAAM,WAAW;AAAA;AAAA;AAAA;AAAA,EAItB,MAAM,iBAAgC;AACpC,UAAM,WAAW,MAAM,UAAU,IAA0B,kBAAkB;AAC7E,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,cAAc,MAAyC;AAC3D,UAAM,WAAW,MAAM,UAAU,MAA4B,oBAAoB,IAAI;AAGrF,UAAM,UAAU,QAAQ,SAAS,IAAI;AAErC,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,kBAAkB,aAAwD;AAC9E,UAAM,WAAW,MAAM,UAAU;AAAA,MAC/B;AAAA,MACA;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,iBAA2C;AAC/C,UAAM,WAAW,MAAM,UAAU;AAAA,MAC/B;AAAA,IACF;AACA,WAAO,SAAS;AAAA,EAClB;AACF;","names":[]}
@@ -0,0 +1,43 @@
1
+ import { EntityApi } from './types.js';
2
+ import '../client.types.js';
3
+
4
+ /**
5
+ * Entity API Factory
6
+ *
7
+ * Factory function to create typed API clients for any entity.
8
+ * Follows the same pattern as BaseEntityService in NextSpark web.
9
+ */
10
+
11
+ /**
12
+ * Create an API client for an entity
13
+ *
14
+ * @param entityPath - The entity path (e.g., 'tasks', 'customers')
15
+ * @returns Typed API client with CRUD operations
16
+ *
17
+ * Note: This factory assumes entities have an `id: string` field for get/update/delete operations.
18
+ * We intentionally don't enforce this via generic constraints to maintain flexibility for
19
+ * entities with different ID field names or types.
20
+ *
21
+ * @example
22
+ * ```typescript
23
+ * const tasksApi = createEntityApi<Task, CreateTaskInput, UpdateTaskInput>('tasks')
24
+ *
25
+ * // List tasks
26
+ * const { data, meta } = await tasksApi.list({ page: 1, limit: 10 })
27
+ *
28
+ * // Get single task
29
+ * const { data: task } = await tasksApi.get('task-id')
30
+ *
31
+ * // Create task
32
+ * const { data: newTask } = await tasksApi.create({ title: 'New Task' })
33
+ *
34
+ * // Update task
35
+ * const { data: updated } = await tasksApi.update('task-id', { status: 'done' })
36
+ *
37
+ * // Delete task
38
+ * await tasksApi.delete('task-id')
39
+ * ```
40
+ */
41
+ declare function createEntityApi<T, CreateInput = Partial<T>, UpdateInput = Partial<T>>(entityPath: string): EntityApi<T, CreateInput, UpdateInput>;
42
+
43
+ export { createEntityApi };
@@ -0,0 +1,31 @@
1
+ import { apiClient } from '../client.js';
2
+ function createEntityApi(entityPath) {
3
+ const basePath = `/api/v1/${entityPath}`;
4
+ return {
5
+ /**
6
+ * List entities with pagination and filters
7
+ */
8
+ list: (params) => apiClient.get(basePath, params),
9
+ /**
10
+ * Get a single entity by ID
11
+ */
12
+ get: (id) => apiClient.get(`${basePath}/${id}`),
13
+ /**
14
+ * Create a new entity
15
+ */
16
+ create: (data) => apiClient.post(basePath, data),
17
+ /**
18
+ * Update an existing entity
19
+ */
20
+ update: (id, data) => apiClient.patch(`${basePath}/${id}`, data),
21
+ /**
22
+ * Delete an entity
23
+ * Returns void (no content expected from DELETE operations)
24
+ */
25
+ delete: (id) => apiClient.delete(`${basePath}/${id}`)
26
+ };
27
+ }
28
+ export {
29
+ createEntityApi
30
+ };
31
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/entities/factory.ts"],"sourcesContent":["/**\n * Entity API Factory\n *\n * Factory function to create typed API clients for any entity.\n * Follows the same pattern as BaseEntityService in NextSpark web.\n */\n\nimport { apiClient } from '../client'\nimport type { PaginatedResponse, SingleResponse } from '../client.types'\nimport type { EntityApi, EntityListParams } from './types'\n\n/**\n * Create an API client for an entity\n *\n * @param entityPath - The entity path (e.g., 'tasks', 'customers')\n * @returns Typed API client with CRUD operations\n *\n * Note: This factory assumes entities have an `id: string` field for get/update/delete operations.\n * We intentionally don't enforce this via generic constraints to maintain flexibility for\n * entities with different ID field names or types.\n *\n * @example\n * ```typescript\n * const tasksApi = createEntityApi<Task, CreateTaskInput, UpdateTaskInput>('tasks')\n *\n * // List tasks\n * const { data, meta } = await tasksApi.list({ page: 1, limit: 10 })\n *\n * // Get single task\n * const { data: task } = await tasksApi.get('task-id')\n *\n * // Create task\n * const { data: newTask } = await tasksApi.create({ title: 'New Task' })\n *\n * // Update task\n * const { data: updated } = await tasksApi.update('task-id', { status: 'done' })\n *\n * // Delete task\n * await tasksApi.delete('task-id')\n * ```\n */\nexport function createEntityApi<T, CreateInput = Partial<T>, UpdateInput = Partial<T>>(\n entityPath: string\n): EntityApi<T, CreateInput, UpdateInput> {\n const basePath = `/api/v1/${entityPath}`\n\n return {\n /**\n * List entities with pagination and filters\n */\n list: (params?: EntityListParams) =>\n apiClient.get<PaginatedResponse<T>>(basePath, params),\n\n /**\n * Get a single entity by ID\n */\n get: (id: string) =>\n apiClient.get<SingleResponse<T>>(`${basePath}/${id}`),\n\n /**\n * Create a new entity\n */\n create: (data: CreateInput) =>\n apiClient.post<SingleResponse<T>>(basePath, data),\n\n /**\n * Update an existing entity\n */\n update: (id: string, data: UpdateInput) =>\n apiClient.patch<SingleResponse<T>>(`${basePath}/${id}`, data),\n\n /**\n * Delete an entity\n * Returns void (no content expected from DELETE operations)\n */\n delete: (id: string): Promise<void> =>\n apiClient.delete<void>(`${basePath}/${id}`),\n }\n}\n"],"mappings":"AAOA,SAAS,iBAAiB;AAkCnB,SAAS,gBACd,YACwC;AACxC,QAAM,WAAW,WAAW,UAAU;AAEtC,SAAO;AAAA;AAAA;AAAA;AAAA,IAIL,MAAM,CAAC,WACL,UAAU,IAA0B,UAAU,MAAM;AAAA;AAAA;AAAA;AAAA,IAKtD,KAAK,CAAC,OACJ,UAAU,IAAuB,GAAG,QAAQ,IAAI,EAAE,EAAE;AAAA;AAAA;AAAA;AAAA,IAKtD,QAAQ,CAAC,SACP,UAAU,KAAwB,UAAU,IAAI;AAAA;AAAA;AAAA;AAAA,IAKlD,QAAQ,CAAC,IAAY,SACnB,UAAU,MAAyB,GAAG,QAAQ,IAAI,EAAE,IAAI,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA,IAM9D,QAAQ,CAAC,OACP,UAAU,OAAa,GAAG,QAAQ,IAAI,EAAE,EAAE;AAAA,EAC9C;AACF;","names":[]}
@@ -0,0 +1,3 @@
1
+ export { createEntityApi } from './factory.js';
2
+ export { EntityApi, EntityListParams } from './types.js';
3
+ import '../client.types.js';
@@ -0,0 +1,3 @@
1
+ export * from './factory.js';
2
+ export * from './types.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/api/entities/index.ts"],"sourcesContent":["/**\n * Entity API Module\n *\n * Factory and types for creating entity API clients.\n */\n\nexport * from './factory'\nexport * from './types'\n"],"mappings":"AAMA,cAAc;AACd,cAAc;","names":[]}
@@ -0,0 +1,32 @@
1
+ import { PaginatedResponse, SingleResponse } from '../client.types.js';
2
+
3
+ /**
4
+ * Entity API Types
5
+ *
6
+ * Generic types for entity CRUD operations.
7
+ */
8
+
9
+ /**
10
+ * Parameters for listing entities
11
+ */
12
+ interface EntityListParams {
13
+ page?: number;
14
+ limit?: number;
15
+ search?: string;
16
+ sort?: string;
17
+ order?: 'asc' | 'desc';
18
+ [key: string]: string | number | boolean | undefined;
19
+ }
20
+ /**
21
+ * Generic entity API interface
22
+ * Matches NextSpark web BaseEntityService pattern
23
+ */
24
+ interface EntityApi<T, CreateInput, UpdateInput> {
25
+ list: (params?: EntityListParams) => Promise<PaginatedResponse<T>>;
26
+ get: (id: string) => Promise<SingleResponse<T>>;
27
+ create: (data: CreateInput) => Promise<SingleResponse<T>>;
28
+ update: (id: string, data: UpdateInput) => Promise<SingleResponse<T>>;
29
+ delete: (id: string) => Promise<void>;
30
+ }
31
+
32
+ export type { EntityApi, EntityListParams };
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -0,0 +1,7 @@
1
+ export { ApiClient, apiClient, getApiUrl } from './client.js';
2
+ export { ApiError, PaginatedResponse, RequestConfig, SingleResponse } from './client.types.js';
3
+ export { authApi } from './core/auth.js';
4
+ export { teamsApi } from './core/teams.js';
5
+ export { AuthSession, LoginResponse, SessionResponse, Team, TeamsResponse, User } from './core/types.js';
6
+ export { createEntityApi } from './entities/factory.js';
7
+ export { EntityApi, EntityListParams } from './entities/types.js';
@@ -0,0 +1,15 @@
1
+ import { apiClient, ApiClient, getApiUrl } from './client.js';
2
+ import { ApiError } from './client.types.js';
3
+ import { authApi } from './core/auth.js';
4
+ import { teamsApi } from './core/teams.js';
5
+ import { createEntityApi } from './entities/factory.js';
6
+ export {
7
+ ApiClient,
8
+ ApiError,
9
+ apiClient,
10
+ authApi,
11
+ createEntityApi,
12
+ getApiUrl,
13
+ teamsApi
14
+ };
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/index.ts"],"sourcesContent":["/**\n * API Module\n *\n * Client, core services, and entity factory.\n */\n\n// Client\nexport { apiClient, ApiClient, getApiUrl } from './client'\nexport { ApiError, type RequestConfig, type PaginatedResponse, type SingleResponse } from './client.types'\n\n// Core services\nexport { authApi } from './core/auth'\nexport { teamsApi } from './core/teams'\nexport type { User, Team, AuthSession, LoginResponse, SessionResponse, TeamsResponse } from './core/types'\n\n// Entity factory\nexport { createEntityApi } from './entities/factory'\nexport type { EntityApi, EntityListParams } from './entities/types'\n"],"mappings":"AAOA,SAAS,WAAW,WAAW,iBAAiB;AAChD,SAAS,gBAAiF;AAG1F,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAIzB,SAAS,uBAAuB;","names":[]}
@@ -0,0 +1,4 @@
1
+ export { useAuth } from '../providers/AuthProvider.js';
2
+ import 'react/jsx-runtime';
3
+ import 'react';
4
+ import '../api/core/types.js';
@@ -0,0 +1,5 @@
1
+ import { useAuth } from '../providers/AuthProvider.js';
2
+ export {
3
+ useAuth
4
+ };
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["/**\n * Hooks\n *\n * Re-export hooks from providers for convenience.\n */\n\n// Auth hooks from AuthProvider\nexport { useAuth } from '../providers/AuthProvider'\n\n// Additional hooks can be added here\n"],"mappings":"AAOA,SAAS,eAAe;","names":[]}
@@ -0,0 +1,14 @@
1
+ export { ApiClient, apiClient, getApiUrl } from './api/client.js';
2
+ export { ApiError, PaginatedResponse, RequestConfig, SingleResponse } from './api/client.types.js';
3
+ export { createEntityApi } from './api/entities/factory.js';
4
+ export { EntityApi, EntityListParams } from './api/entities/types.js';
5
+ export { authApi } from './api/core/auth.js';
6
+ export { teamsApi } from './api/core/teams.js';
7
+ export { AuthSession, LoginResponse, SessionResponse, Team, TeamsResponse, User } from './api/core/types.js';
8
+ export { AuthProvider, useAuth } from './providers/AuthProvider.js';
9
+ export { QueryProvider, queryClient } from './providers/QueryProvider.js';
10
+ export { s as Storage } from './storage-BaRppHUz.js';
11
+ export { Alert, alert, confirm, confirmDestructive } from './lib/alert.js';
12
+ import 'react/jsx-runtime';
13
+ import 'react';
14
+ import '@tanstack/react-query';
package/dist/index.js ADDED
@@ -0,0 +1,28 @@
1
+ import { apiClient, ApiClient, getApiUrl } from './api/client.js';
2
+ import { ApiError } from './api/client.types.js';
3
+ import { createEntityApi } from './api/entities/factory.js';
4
+ import { authApi } from './api/core/auth.js';
5
+ import { teamsApi } from './api/core/teams.js';
6
+ import { AuthProvider, useAuth } from './providers/AuthProvider.js';
7
+ import { QueryProvider, queryClient } from './providers/QueryProvider.js';
8
+ import * as Storage from './lib/storage.js';
9
+ import { alert, confirm, confirmDestructive, Alert } from './lib/alert.js';
10
+ export {
11
+ Alert,
12
+ ApiClient,
13
+ ApiError,
14
+ AuthProvider,
15
+ QueryProvider,
16
+ Storage,
17
+ alert,
18
+ apiClient,
19
+ authApi,
20
+ confirm,
21
+ confirmDestructive,
22
+ createEntityApi,
23
+ getApiUrl,
24
+ queryClient,
25
+ teamsApi,
26
+ useAuth
27
+ };
28
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["/**\n * @nextsparkjs/mobile\n *\n * Mobile app infrastructure for NextSpark.\n * Provides API client, authentication, and utilities for Expo apps.\n */\n\n// API Client\nexport { apiClient, ApiClient, getApiUrl } from './api/client'\nexport { ApiError } from './api/client.types'\nexport type { RequestConfig, PaginatedResponse, SingleResponse } from './api/client.types'\n\n// Entity Factory\nexport { createEntityApi } from './api/entities/factory'\nexport type { EntityApi, EntityListParams } from './api/entities/types'\n\n// Core API Services\nexport { authApi } from './api/core/auth'\nexport { teamsApi } from './api/core/teams'\nexport type { User, Team, AuthSession, LoginResponse, SessionResponse, TeamsResponse } from './api/core/types'\n\n// Providers\nexport { AuthProvider, useAuth } from './providers/AuthProvider'\nexport { QueryProvider, queryClient } from './providers/QueryProvider'\n\n// Utilities\n/**\n * Secure storage utilities using Expo SecureStore (native) or localStorage (web)\n * @example\n * ```ts\n * import { Storage } from '@nextsparkjs/mobile'\n * await Storage.setItemAsync('key', 'value')\n * const value = await Storage.getItemAsync('key')\n * ```\n */\nexport * as Storage from './lib/storage'\n\n/**\n * Cross-platform alert dialogs (native Alert API on iOS/Android, window.confirm on web)\n * @example\n * ```ts\n * import { alert, confirm } from '@nextsparkjs/mobile'\n * alert({ title: 'Info', message: 'Hello!' })\n * const confirmed = await confirm('Are you sure?', 'This action cannot be undone')\n * ```\n */\nexport { alert, confirm, confirmDestructive, Alert } from './lib/alert'\n"],"mappings":"AAQA,SAAS,WAAW,WAAW,iBAAiB;AAChD,SAAS,gBAAgB;AAIzB,SAAS,uBAAuB;AAIhC,SAAS,eAAe;AACxB,SAAS,gBAAgB;AAIzB,SAAS,cAAc,eAAe;AACtC,SAAS,eAAe,mBAAmB;AAY3C,YAAY,aAAa;AAWzB,SAAS,OAAO,SAAS,oBAAoB,aAAa;","names":[]}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Cross-platform Alert utility
3
+ * Works on iOS, Android, and Web
4
+ */
5
+ interface AlertButton {
6
+ text: string;
7
+ style?: "default" | "cancel" | "destructive";
8
+ onPress?: () => void;
9
+ }
10
+ interface AlertOptions {
11
+ title: string;
12
+ message?: string;
13
+ buttons?: AlertButton[];
14
+ }
15
+ /**
16
+ * Show an alert dialog that works on all platforms
17
+ */
18
+ declare function alert(options: AlertOptions): void;
19
+ /**
20
+ * Show a confirmation dialog
21
+ * Returns a promise that resolves to true if confirmed, false if cancelled
22
+ */
23
+ declare function confirm(title: string, message?: string): Promise<boolean>;
24
+ /**
25
+ * Show a destructive confirmation dialog (for delete actions)
26
+ */
27
+ declare function confirmDestructive(title: string, message?: string, destructiveButtonText?: string): Promise<boolean>;
28
+ declare const Alert: {
29
+ alert: typeof alert;
30
+ confirm: typeof confirm;
31
+ confirmDestructive: typeof confirmDestructive;
32
+ };
33
+
34
+ export { Alert, alert, confirm, confirmDestructive };
@@ -0,0 +1,73 @@
1
+ import { Alert as RNAlert, Platform } from "react-native";
2
+ function alert(options) {
3
+ const { title, message, buttons = [{ text: "OK" }] } = options;
4
+ if (Platform.OS === "web") {
5
+ const hasDestructive = buttons.some((b) => b.style === "destructive");
6
+ const hasCancel = buttons.some((b) => b.style === "cancel");
7
+ if (hasDestructive && hasCancel) {
8
+ const confirmed = window.confirm(`${title}
9
+
10
+ ${message || ""}`);
11
+ if (confirmed) {
12
+ const destructiveBtn = buttons.find((b) => b.style === "destructive");
13
+ destructiveBtn?.onPress?.();
14
+ } else {
15
+ const cancelBtn = buttons.find((b) => b.style === "cancel");
16
+ cancelBtn?.onPress?.();
17
+ }
18
+ } else if (buttons.length === 1) {
19
+ window.alert(`${title}
20
+
21
+ ${message || ""}`);
22
+ buttons[0]?.onPress?.();
23
+ } else {
24
+ const confirmed = window.confirm(`${title}
25
+
26
+ ${message || ""}`);
27
+ const btn = confirmed ? buttons[buttons.length - 1] : buttons[0];
28
+ btn?.onPress?.();
29
+ }
30
+ } else {
31
+ RNAlert.alert(title, message, buttons);
32
+ }
33
+ }
34
+ function confirm(title, message) {
35
+ return new Promise((resolve) => {
36
+ alert({
37
+ title,
38
+ message,
39
+ buttons: [
40
+ { text: "Cancelar", style: "cancel", onPress: () => resolve(false) },
41
+ { text: "Confirmar", style: "default", onPress: () => resolve(true) }
42
+ ]
43
+ });
44
+ });
45
+ }
46
+ function confirmDestructive(title, message, destructiveButtonText = "Eliminar") {
47
+ return new Promise((resolve) => {
48
+ alert({
49
+ title,
50
+ message,
51
+ buttons: [
52
+ { text: "Cancelar", style: "cancel", onPress: () => resolve(false) },
53
+ {
54
+ text: destructiveButtonText,
55
+ style: "destructive",
56
+ onPress: () => resolve(true)
57
+ }
58
+ ]
59
+ });
60
+ });
61
+ }
62
+ const Alert = {
63
+ alert,
64
+ confirm,
65
+ confirmDestructive
66
+ };
67
+ export {
68
+ Alert,
69
+ alert,
70
+ confirm,
71
+ confirmDestructive
72
+ };
73
+ //# sourceMappingURL=alert.js.map