@indexeddb-orm/idb-orm 0.0.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 (216) hide show
  1. package/.vscode/extensions.json +5 -0
  2. package/README.md +1280 -0
  3. package/angular-demo-app/README.md +84 -0
  4. package/angular-demo-app/angular.json +109 -0
  5. package/angular-demo-app/package-lock.json +14215 -0
  6. package/angular-demo-app/package.json +41 -0
  7. package/angular-demo-app/src/app/app.component.ts +481 -0
  8. package/angular-demo-app/src/app/app.routes.ts +8 -0
  9. package/angular-demo-app/src/app/components/actions.component.ts +202 -0
  10. package/angular-demo-app/src/app/components/cloud-sync-demo.component.ts +296 -0
  11. package/angular-demo-app/src/app/components/live-query-demo.component.ts +307 -0
  12. package/angular-demo-app/src/app/components/main-info.component.ts +148 -0
  13. package/angular-demo-app/src/app/components/posts-live-query-demo.component.ts +336 -0
  14. package/angular-demo-app/src/app/components/typescript-demo.component.ts +268 -0
  15. package/angular-demo-app/src/entities/post-tag.entity.ts +25 -0
  16. package/angular-demo-app/src/entities/post.entity.ts +49 -0
  17. package/angular-demo-app/src/entities/profile.entity.ts +42 -0
  18. package/angular-demo-app/src/entities/tag.entity.ts +36 -0
  19. package/angular-demo-app/src/entities/user.entity.ts +59 -0
  20. package/angular-demo-app/src/favicon.ico +1 -0
  21. package/angular-demo-app/src/index.html +16 -0
  22. package/angular-demo-app/src/main.ts +13 -0
  23. package/angular-demo-app/src/services/app-logic.service.ts +449 -0
  24. package/angular-demo-app/src/services/cloud-sync.service.ts +95 -0
  25. package/angular-demo-app/src/services/database.service.ts +26 -0
  26. package/angular-demo-app/src/services/live-query.service.ts +63 -0
  27. package/angular-demo-app/src/services/posts-live-query.service.ts +86 -0
  28. package/angular-demo-app/src/services/typescript-demo.service.ts +59 -0
  29. package/angular-demo-app/src/styles.scss +50 -0
  30. package/angular-demo-app/tsconfig.app.json +13 -0
  31. package/angular-demo-app/tsconfig.json +34 -0
  32. package/angular-demo-app/tsconfig.spec.json +13 -0
  33. package/dist/Database.d.ts +206 -0
  34. package/dist/Database.js +288 -0
  35. package/dist/decorators/Column.d.ts +79 -0
  36. package/dist/decorators/Column.js +236 -0
  37. package/dist/decorators/Entity.d.ts +32 -0
  38. package/dist/decorators/Entity.js +44 -0
  39. package/dist/decorators/Relation.d.ts +70 -0
  40. package/dist/decorators/Relation.js +120 -0
  41. package/dist/decorators/index.d.ts +3 -0
  42. package/dist/decorators/index.js +3 -0
  43. package/dist/errors/ValidationError.d.ts +4 -0
  44. package/dist/errors/ValidationError.js +8 -0
  45. package/dist/index.d.ts +8 -0
  46. package/dist/index.js +7 -0
  47. package/dist/metadata/Column.d.ts +8 -0
  48. package/dist/metadata/Column.js +44 -0
  49. package/dist/metadata/Entity.d.ts +11 -0
  50. package/dist/metadata/Entity.js +21 -0
  51. package/dist/metadata/Relation.d.ts +20 -0
  52. package/dist/metadata/Relation.js +74 -0
  53. package/dist/metadata/index.d.ts +3 -0
  54. package/dist/metadata/index.js +3 -0
  55. package/dist/services/AggregationService.d.ts +38 -0
  56. package/dist/services/AggregationService.js +229 -0
  57. package/dist/services/BaseEntity.d.ts +32 -0
  58. package/dist/services/BaseEntity.js +62 -0
  59. package/dist/services/CloudSyncService.d.ts +100 -0
  60. package/dist/services/CloudSyncService.js +196 -0
  61. package/dist/services/DecoratorUtils.d.ts +12 -0
  62. package/dist/services/DecoratorUtils.js +10 -0
  63. package/dist/services/EntityFactory.d.ts +25 -0
  64. package/dist/services/EntityFactory.js +27 -0
  65. package/dist/services/EntityRegistry.d.ts +61 -0
  66. package/dist/services/EntityRegistry.js +56 -0
  67. package/dist/services/EntitySchema.d.ts +56 -0
  68. package/dist/services/EntitySchema.js +125 -0
  69. package/dist/services/MigrationManager.d.ts +70 -0
  70. package/dist/services/MigrationManager.js +181 -0
  71. package/dist/services/RelationLoader.d.ts +66 -0
  72. package/dist/services/RelationLoader.js +310 -0
  73. package/dist/services/SchemaBuilder.d.ts +68 -0
  74. package/dist/services/SchemaBuilder.js +191 -0
  75. package/dist/services/index.d.ts +7 -0
  76. package/dist/services/index.js +7 -0
  77. package/dist/types.d.ts +152 -0
  78. package/dist/types.js +1 -0
  79. package/dist/utils/logger.d.ts +12 -0
  80. package/dist/utils/logger.js +16 -0
  81. package/eslint.config.js +49 -0
  82. package/homepage/favicon.svg +36 -0
  83. package/homepage/index.html +1725 -0
  84. package/package.json +78 -0
  85. package/react-demo-app/README.md +61 -0
  86. package/react-demo-app/eslint.config.js +60 -0
  87. package/react-demo-app/index.html +13 -0
  88. package/react-demo-app/package-lock.json +4955 -0
  89. package/react-demo-app/package.json +39 -0
  90. package/react-demo-app/src/App.tsx +172 -0
  91. package/react-demo-app/src/assets/react.svg +1 -0
  92. package/react-demo-app/src/components/Actions.tsx +171 -0
  93. package/react-demo-app/src/components/CloudSyncDemo.tsx +191 -0
  94. package/react-demo-app/src/components/LiveQueryDemo.tsx +122 -0
  95. package/react-demo-app/src/components/MainInfo.tsx +75 -0
  96. package/react-demo-app/src/components/PostsLiveQueryDemo.tsx +185 -0
  97. package/react-demo-app/src/components/TypeScriptDemo.tsx +190 -0
  98. package/react-demo-app/src/database/Database.ts +30 -0
  99. package/react-demo-app/src/entities/Post.ts +48 -0
  100. package/react-demo-app/src/entities/PostTag.ts +26 -0
  101. package/react-demo-app/src/entities/Profile.ts +41 -0
  102. package/react-demo-app/src/entities/Tag.ts +35 -0
  103. package/react-demo-app/src/entities/User.ts +61 -0
  104. package/react-demo-app/src/hooks/useAppLogic.ts +565 -0
  105. package/react-demo-app/src/hooks/useCloudSyncDemo.ts +84 -0
  106. package/react-demo-app/src/hooks/useLiveQueryDemo.ts +68 -0
  107. package/react-demo-app/src/hooks/usePostsLiveQueryDemo.ts +64 -0
  108. package/react-demo-app/src/hooks/useTypeScriptDemo.ts +43 -0
  109. package/react-demo-app/src/index.css +26 -0
  110. package/react-demo-app/src/main.tsx +18 -0
  111. package/react-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
  112. package/react-demo-app/src/migrations/002-add-post-category.ts +37 -0
  113. package/react-demo-app/src/migrations/index.ts +8 -0
  114. package/react-demo-app/src/vite-env.d.ts +1 -0
  115. package/react-demo-app/tsconfig.app.json +22 -0
  116. package/react-demo-app/tsconfig.json +6 -0
  117. package/react-demo-app/vite.config.ts +10 -0
  118. package/src/Database.ts +405 -0
  119. package/src/errors/ValidationError.ts +9 -0
  120. package/src/index.ts +13 -0
  121. package/src/metadata/Column.ts +74 -0
  122. package/src/metadata/Entity.ts +42 -0
  123. package/src/metadata/Relation.ts +121 -0
  124. package/src/metadata/index.ts +5 -0
  125. package/src/services/AggregationService.ts +348 -0
  126. package/src/services/BaseEntity.ts +77 -0
  127. package/src/services/CloudSyncService.ts +248 -0
  128. package/src/services/EntityFactory.ts +35 -0
  129. package/src/services/EntityRegistry.ts +109 -0
  130. package/src/services/EntitySchema.ts +154 -0
  131. package/src/services/MigrationManager.ts +276 -0
  132. package/src/services/RelationLoader.ts +532 -0
  133. package/src/services/SchemaBuilder.ts +237 -0
  134. package/src/services/index.ts +7 -0
  135. package/src/types.d.ts +1 -0
  136. package/src/types.ts +169 -0
  137. package/src/utils/logger.ts +40 -0
  138. package/svelte-demo-app/README.md +61 -0
  139. package/svelte-demo-app/package-lock.json +3000 -0
  140. package/svelte-demo-app/package.json +30 -0
  141. package/svelte-demo-app/src/app.d.ts +12 -0
  142. package/svelte-demo-app/src/app.html +13 -0
  143. package/svelte-demo-app/src/components/Actions.svelte +121 -0
  144. package/svelte-demo-app/src/components/CloudSyncDemo.svelte +333 -0
  145. package/svelte-demo-app/src/components/LiveQueryDemo.svelte +191 -0
  146. package/svelte-demo-app/src/components/MainInfo.svelte +133 -0
  147. package/svelte-demo-app/src/components/PostsLiveQueryDemo.svelte +330 -0
  148. package/svelte-demo-app/src/components/TypeScriptDemo.svelte +251 -0
  149. package/svelte-demo-app/src/database/Database.ts +29 -0
  150. package/svelte-demo-app/src/entities/Post.ts +46 -0
  151. package/svelte-demo-app/src/entities/PostTag.ts +22 -0
  152. package/svelte-demo-app/src/entities/Profile.ts +39 -0
  153. package/svelte-demo-app/src/entities/Tag.ts +33 -0
  154. package/svelte-demo-app/src/entities/User.ts +62 -0
  155. package/svelte-demo-app/src/lib/database/Database.ts +30 -0
  156. package/svelte-demo-app/src/lib/entities/Post.ts +47 -0
  157. package/svelte-demo-app/src/lib/entities/PostTag.ts +23 -0
  158. package/svelte-demo-app/src/lib/entities/Profile.ts +40 -0
  159. package/svelte-demo-app/src/lib/entities/Tag.ts +34 -0
  160. package/svelte-demo-app/src/lib/entities/User.ts +59 -0
  161. package/svelte-demo-app/src/lib/index.ts +7 -0
  162. package/svelte-demo-app/src/lib/migrations/001-add-user-email-index.ts +17 -0
  163. package/svelte-demo-app/src/lib/migrations/002-add-post-category.ts +37 -0
  164. package/svelte-demo-app/src/lib/migrations/index.ts +8 -0
  165. package/svelte-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
  166. package/svelte-demo-app/src/migrations/002-add-post-category.ts +37 -0
  167. package/svelte-demo-app/src/migrations/index.ts +8 -0
  168. package/svelte-demo-app/src/routes/+layout.js +3 -0
  169. package/svelte-demo-app/src/routes/+layout.svelte +228 -0
  170. package/svelte-demo-app/src/routes/+page.js +3 -0
  171. package/svelte-demo-app/src/routes/+page.svelte +1305 -0
  172. package/svelte-demo-app/src/stores/appStore.js +603 -0
  173. package/svelte-demo-app/svelte.config.js +18 -0
  174. package/svelte-demo-app/tsconfig.json +14 -0
  175. package/svelte-demo-app/vite.config.ts +6 -0
  176. package/tests/aggregation.e2e.test.ts +87 -0
  177. package/tests/base-entity.e2e.test.ts +47 -0
  178. package/tests/database-api.e2e.test.ts +177 -0
  179. package/tests/decorators.e2e.test.ts +40 -0
  180. package/tests/entity-schema.e2e.test.ts +58 -0
  181. package/tests/relation-loader-table-names.test.ts +192 -0
  182. package/tests/relations.e2e.test.ts +178 -0
  183. package/tests/zod-runtime.e2e.test.ts +69 -0
  184. package/tsconfig.json +21 -0
  185. package/vitest.config.ts +21 -0
  186. package/vitest.setup.ts +27 -0
  187. package/vue-demo-app/README.md +61 -0
  188. package/vue-demo-app/index.html +13 -0
  189. package/vue-demo-app/package-lock.json +1537 -0
  190. package/vue-demo-app/package.json +27 -0
  191. package/vue-demo-app/src/App.vue +100 -0
  192. package/vue-demo-app/src/components/Actions.vue +135 -0
  193. package/vue-demo-app/src/components/CloudSyncDemo.vue +139 -0
  194. package/vue-demo-app/src/components/LiveQueryDemo.vue +122 -0
  195. package/vue-demo-app/src/components/MainInfo.vue +80 -0
  196. package/vue-demo-app/src/components/PostsLiveQueryDemo.vue +136 -0
  197. package/vue-demo-app/src/components/TypeScriptDemo.vue +133 -0
  198. package/vue-demo-app/src/database/Database.ts +29 -0
  199. package/vue-demo-app/src/entities/Post.ts +48 -0
  200. package/vue-demo-app/src/entities/PostTag.ts +24 -0
  201. package/vue-demo-app/src/entities/Profile.ts +41 -0
  202. package/vue-demo-app/src/entities/Tag.ts +35 -0
  203. package/vue-demo-app/src/entities/User.ts +61 -0
  204. package/vue-demo-app/src/main.ts +29 -0
  205. package/vue-demo-app/src/migrations/001-add-user-email-index.ts +23 -0
  206. package/vue-demo-app/src/migrations/002-add-post-category.ts +46 -0
  207. package/vue-demo-app/src/migrations/index.ts +14 -0
  208. package/vue-demo-app/src/services/useAppLogic.ts +565 -0
  209. package/vue-demo-app/src/services/useCloudSyncDemo.ts +84 -0
  210. package/vue-demo-app/src/services/useLiveQueryDemo.ts +82 -0
  211. package/vue-demo-app/src/services/usePostsLiveQueryDemo.ts +77 -0
  212. package/vue-demo-app/src/services/useTypeScriptDemo.ts +56 -0
  213. package/vue-demo-app/src/vite-env.d.ts +1 -0
  214. package/vue-demo-app/tsconfig.json +25 -0
  215. package/vue-demo-app/tsconfig.node.json +10 -0
  216. package/vue-demo-app/vite.config.ts +16 -0
@@ -0,0 +1,84 @@
1
+ import {
2
+ useEffect, useState,
3
+ } from 'react';
4
+
5
+ import { db } from '../database/Database';
6
+
7
+ export function useCloudSyncDemo() {
8
+ const [syncStatus, setSyncStatus] = useState<{
9
+ enabled: boolean;
10
+ lastSync?: Date;
11
+ isOnline?: boolean;
12
+ }>({ enabled: false });
13
+ const [isLoading, setIsLoading] = useState(false);
14
+
15
+ useEffect(() => {
16
+ // Get initial sync status
17
+ const status = db.getSyncStatus();
18
+ setSyncStatus(status);
19
+ }, []);
20
+
21
+ const handleManualSync = async () => {
22
+ setIsLoading(true);
23
+ try {
24
+ await db.sync();
25
+ // Update status after sync
26
+ const newStatus = db.getSyncStatus();
27
+ setSyncStatus(newStatus);
28
+ alert('Sync completed successfully!');
29
+ } catch (error) {
30
+ console.error('Sync failed:', error);
31
+ alert(`Sync failed: ${(error as Error).message}`);
32
+ } finally {
33
+ setIsLoading(false);
34
+ }
35
+ };
36
+
37
+ const handleEnableCloudSync = async () => {
38
+ setIsLoading(true);
39
+ try {
40
+ await db.enableCloudSync({
41
+ databaseUrl: 'https://your-database-url.dexie.cloud',
42
+ enableOfflineSupport: true,
43
+ syncInterval: 30000,
44
+ });
45
+
46
+ const newStatus = db.getSyncStatus();
47
+ setSyncStatus(newStatus);
48
+ alert('Cloud sync enabled successfully!');
49
+ } catch (error) {
50
+ console.error('Failed to enable cloud sync:', error);
51
+ alert(`Failed to enable cloud sync: ${(error as Error).message}`);
52
+ } finally {
53
+ setIsLoading(false);
54
+ }
55
+ };
56
+
57
+ const handleDisableCloudSync = () => {
58
+ db.disableCloudSync();
59
+ setSyncStatus({ enabled: false });
60
+ alert('Cloud sync disabled');
61
+ };
62
+
63
+ const handleSyncTables = async () => {
64
+ setIsLoading(true);
65
+ try {
66
+ await db.syncTables(['users', 'posts']);
67
+ alert('Tables synced successfully!');
68
+ } catch (error) {
69
+ console.error('Table sync failed:', error);
70
+ alert(`Table sync failed: ${(error as Error).message}`);
71
+ } finally {
72
+ setIsLoading(false);
73
+ }
74
+ };
75
+
76
+ return {
77
+ syncStatus,
78
+ isLoading,
79
+ handleManualSync,
80
+ handleEnableCloudSync,
81
+ handleDisableCloudSync,
82
+ handleSyncTables,
83
+ };
84
+ }
@@ -0,0 +1,68 @@
1
+ import { useLiveQuery } from 'dexie-react-hooks';
2
+
3
+ import { db } from '../database/Database';
4
+ import { PostEntity } from '../entities/Post';
5
+ import { ProfileEntity } from '../entities/Profile';
6
+ import { UserEntity } from '../entities/User';
7
+
8
+ export function useLiveQueryDemo() {
9
+ // 1. Using getRepository - preferred typed API (full UserEntity[] typing)
10
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
11
+ const allUsers = useLiveQuery(() => db.table('users').toArray());
12
+
13
+ // 4. Filtering with full typing - TypeScript knows it's UserEntity[]
14
+ const adultUsers = useLiveQuery(() =>
15
+ db.getRepository(UserEntity).where('age').above(18).toArray(),
16
+ );
17
+
18
+ // 5. Counting records - TypeScript knows it's number
19
+ const userCount = useLiveQuery(() => db.getRepository(UserEntity).count());
20
+
21
+ // 6. Single record - TypeScript knows it's UserEntity | undefined
22
+ const firstUser = useLiveQuery(() => db.getRepository(UserEntity).orderBy('id').first());
23
+
24
+ // 7. Complex query with relations - full typing preserved
25
+ const usersWithProfiles = useLiveQuery(async () => {
26
+ const users = await db.getRepository(UserEntity).toArray(); // UserEntity[]
27
+ const usersWithProfiles: Array<UserEntity
28
+ & { profile?: ProfileEntity }> = [];
29
+
30
+ console.log('new users', users);
31
+
32
+ for (const user of users) {
33
+ if (user.id == null) {
34
+ usersWithProfiles
35
+ .push(user as UserEntity & { profile?: ProfileEntity });
36
+ continue;
37
+ }
38
+ const profile = await db
39
+ .getRepository(ProfileEntity)
40
+ .where('userId')
41
+ .equals(user.id)
42
+ .first(); // ProfileEntity | undefined
43
+ usersWithProfiles.push(Object.assign(user, { profile }));
44
+ }
45
+
46
+ return usersWithProfiles;
47
+ });
48
+
49
+ // 8. Test with PostEntity - ensure typing works across entities
50
+ const allPosts = useLiveQuery(() =>
51
+ db.getRepository(PostEntity).toArray()); // PostEntity[]
52
+
53
+ // 9. Test with ProfileEntity
54
+ const allProfiles = useLiveQuery(() =>
55
+ db.getRepository(ProfileEntity)
56
+ .toArray(),
57
+ ); // ProfileEntity[]
58
+
59
+ return {
60
+ allUsers,
61
+ adultUsers,
62
+ userCount,
63
+ firstUser,
64
+ usersWithProfiles,
65
+ allPosts,
66
+ allProfiles,
67
+ };
68
+ }
@@ -0,0 +1,64 @@
1
+ import { newEntity } from 'idb-orm';
2
+ import { useLiveQuery } from 'dexie-react-hooks';
3
+
4
+ import { db } from '../database/Database';
5
+ import { PostEntity } from '../entities/Post';
6
+
7
+ export function usePostsLiveQueryDemo() {
8
+ // 1. All posts with sorting
9
+ const allPosts = useLiveQuery(() =>
10
+ db.getRepository(PostEntity).orderBy('createdAt').reverse().toArray(),
11
+ );
12
+
13
+ // 2. Published posts
14
+ const publishedPosts = useLiveQuery(() =>
15
+ db.getRepository(PostEntity).where('published').equals(1).toArray(),
16
+ );
17
+
18
+ // 3. Most liked posts
19
+ const topPosts = useLiveQuery(() =>
20
+ db.getRepository(PostEntity).orderBy('likes').reverse().limit(3).toArray(),
21
+ );
22
+
23
+ // 4. Post statistics
24
+ const postStats = useLiveQuery(async () => {
25
+ const total = await db.getRepository(PostEntity).count();
26
+ const published = await db
27
+ .getRepository(PostEntity)
28
+ .where('published')
29
+ .equals(1)
30
+ .count();
31
+ const totalLikes = await db
32
+ .getRepository(PostEntity)
33
+ .toArray()
34
+ .then((posts) => posts.reduce((sum, post) => sum + (post.likes || 0), 0));
35
+
36
+ return { total, published, totalLikes };
37
+ });
38
+
39
+ const addSamplePost = async () => {
40
+ try {
41
+ const post = newEntity(PostEntity, {
42
+ title: `Post ${Date.now()}`,
43
+ content: 'This is a sample post added by the useLiveQuery demo!',
44
+ published: Math.random() > 0.5,
45
+ likes: Math.floor(Math.random() * 100),
46
+ postTags: ['demo', 'useLiveQuery'],
47
+ createdAt: Date.now(),
48
+ updatedAt: Date.now(),
49
+ });
50
+
51
+ await db.getRepository(PostEntity).add(post);
52
+ } catch (error) {
53
+ console.error('Error adding post:', error);
54
+ }
55
+ };
56
+
57
+ return {
58
+ allPosts,
59
+ publishedPosts,
60
+ topPosts,
61
+ postStats,
62
+ addSamplePost,
63
+ };
64
+ }
@@ -0,0 +1,43 @@
1
+ import { useLiveQuery } from 'dexie-react-hooks';
2
+
3
+ import { db } from '../database/Database';
4
+ import { PostEntity } from '../entities/Post';
5
+ import { ProfileEntity } from '../entities/Profile';
6
+ import { UserEntity } from '../entities/User';
7
+
8
+ export function useTypeScriptDemo() {
9
+ // These variables are fully typed - check in your IDE!
10
+ const users = useLiveQuery(() => db.getRepository(UserEntity).toArray());
11
+ const posts = useLiveQuery(() => db.getRepository(PostEntity).toArray());
12
+ const profiles = useLiveQuery(() =>
13
+ db.getRepository(ProfileEntity).toArray(),
14
+ );
15
+
16
+ // Test functions - TypeScript should suggest properties
17
+ const handleUserClick = (user: UserEntity) => {
18
+ // IDE should suggest
19
+ // : user.id, user.name, user.email, user.age, user.tags, user.metadata
20
+ console.log('User clicked:', user.name, user.email, user.age);
21
+ };
22
+
23
+ const handlePostClick = (post: PostEntity) => {
24
+ // IDE should suggest:
25
+ // post.id, post.title, post.content, post.published, post.likes, etc.
26
+ console.log('Post clicked:', post.title, post.published, post.likes);
27
+ };
28
+
29
+ const handleProfileClick = (profile: ProfileEntity) => {
30
+ // IDE should suggest:
31
+ // profile.id, profile.userId, profile.bio, profile.avatar, etc.
32
+ console.log('Profile clicked:', profile.bio, profile.website);
33
+ };
34
+
35
+ return {
36
+ users,
37
+ posts,
38
+ profiles,
39
+ handleUserClick,
40
+ handlePostClick,
41
+ handleProfileClick,
42
+ };
43
+ }
@@ -0,0 +1,26 @@
1
+
2
+ /* Reset and base styles */
3
+ * {
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ html, body {
8
+ margin: 0;
9
+ padding: 0;
10
+ width: 100%;
11
+ height: 100%;
12
+ overflow-x: hidden;
13
+ }
14
+
15
+ #root {
16
+ width: 100%;
17
+ min-height: 100vh;
18
+ }
19
+
20
+ /* Custom styles */
21
+ .line-clamp-3 {
22
+ display: -webkit-box;
23
+ -webkit-line-clamp: 3;
24
+ -webkit-box-orient: vertical;
25
+ overflow: hidden;
26
+ }
@@ -0,0 +1,18 @@
1
+ import './index.css';
2
+
3
+ import {
4
+ createTheme,CssBaseline, ThemeProvider,
5
+ } from '@mui/material';
6
+ import { StrictMode } from 'react';
7
+ import { createRoot } from 'react-dom/client';
8
+
9
+ import App from './App.tsx';
10
+
11
+ createRoot(document.getElementById('root')!).render(
12
+ <StrictMode>
13
+ <ThemeProvider theme={createTheme()}>
14
+ <CssBaseline />
15
+ <App />
16
+ </ThemeProvider>
17
+ </StrictMode>,
18
+ );
@@ -0,0 +1,17 @@
1
+ import type { Migration } from '../../../src/types';
2
+
3
+ export const addUserEmailIndex: Migration = {
4
+ version: 1,
5
+ name: 'add-user-email-index',
6
+ up: async () => {
7
+ console.log('Adding email index to users table...');
8
+ // This migration would add an index to the email field
9
+ // In a real scenario, you might need to recreate the table with the new index
10
+ console.log('Email index added successfully');
11
+ },
12
+ down: async () => {
13
+ console.log('Removing email index from users table...');
14
+ // This would remove the index
15
+ console.log('Email index removed successfully');
16
+ },
17
+ };
@@ -0,0 +1,37 @@
1
+ import type { Migration } from '../../../src/types';
2
+
3
+ export const addPostCategory: Migration = {
4
+ version: 2,
5
+ name: 'add-post-category',
6
+ up: async (db) => {
7
+ console.log('Adding category field to posts table...');
8
+
9
+ const posts = await db.table('posts').toArray();
10
+ const updatedPosts = posts.map((post: Record<string, unknown>) => ({
11
+ ...post,
12
+ category: 'general',
13
+ }));
14
+
15
+ const postsRepo = db.table('posts');
16
+ await postsRepo.clear();
17
+ await postsRepo.bulkAdd(updatedPosts);
18
+
19
+ console.log('Category field added to all existing posts');
20
+ },
21
+ down: async (db) => {
22
+ console.log('Removing category field from posts table...');
23
+
24
+ const posts = await db.table('posts').toArray();
25
+ const updatedPosts = posts
26
+ .map(({ _category, ...post }: Record<string, unknown>) => {
27
+
28
+ return post;
29
+ });
30
+
31
+ const postsRepo = db.table('posts');
32
+ await postsRepo.clear();
33
+ await postsRepo.bulkAdd(updatedPosts);
34
+
35
+ console.log('Category field removed from all posts');
36
+ },
37
+ };
@@ -0,0 +1,8 @@
1
+ import type { Migration } from '../../../src/types';
2
+ import { addUserEmailIndex } from './001-add-user-email-index';
3
+ import { addPostCategory } from './002-add-post-category';
4
+
5
+ export const migrations: Migration[] = [
6
+ addUserEmailIndex,
7
+ addPostCategory,
8
+ ];
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,22 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "useDefineForClassFields": false,
5
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ "moduleResolution": "bundler",
10
+ "allowImportingTsExtensions": true,
11
+ "verbatimModuleSyntax": true,
12
+ "moduleDetection": "force",
13
+ "noEmit": true,
14
+ "jsx": "react-jsx",
15
+
16
+ "strict": true,
17
+ "noUnusedLocals": true,
18
+ "noUnusedParameters": true,
19
+ "noFallthroughCasesInSwitch": true
20
+ },
21
+ "include": ["src"]
22
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.app.json" }
5
+ ]
6
+ }
@@ -0,0 +1,10 @@
1
+ import react from '@vitejs/plugin-react';
2
+ import { defineConfig } from 'vite';
3
+
4
+ // https://vite.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ resolve: {
8
+ dedupe: ['dexie'],
9
+ },
10
+ });