@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.
- package/.vscode/extensions.json +5 -0
- package/README.md +1280 -0
- package/angular-demo-app/README.md +84 -0
- package/angular-demo-app/angular.json +109 -0
- package/angular-demo-app/package-lock.json +14215 -0
- package/angular-demo-app/package.json +41 -0
- package/angular-demo-app/src/app/app.component.ts +481 -0
- package/angular-demo-app/src/app/app.routes.ts +8 -0
- package/angular-demo-app/src/app/components/actions.component.ts +202 -0
- package/angular-demo-app/src/app/components/cloud-sync-demo.component.ts +296 -0
- package/angular-demo-app/src/app/components/live-query-demo.component.ts +307 -0
- package/angular-demo-app/src/app/components/main-info.component.ts +148 -0
- package/angular-demo-app/src/app/components/posts-live-query-demo.component.ts +336 -0
- package/angular-demo-app/src/app/components/typescript-demo.component.ts +268 -0
- package/angular-demo-app/src/entities/post-tag.entity.ts +25 -0
- package/angular-demo-app/src/entities/post.entity.ts +49 -0
- package/angular-demo-app/src/entities/profile.entity.ts +42 -0
- package/angular-demo-app/src/entities/tag.entity.ts +36 -0
- package/angular-demo-app/src/entities/user.entity.ts +59 -0
- package/angular-demo-app/src/favicon.ico +1 -0
- package/angular-demo-app/src/index.html +16 -0
- package/angular-demo-app/src/main.ts +13 -0
- package/angular-demo-app/src/services/app-logic.service.ts +449 -0
- package/angular-demo-app/src/services/cloud-sync.service.ts +95 -0
- package/angular-demo-app/src/services/database.service.ts +26 -0
- package/angular-demo-app/src/services/live-query.service.ts +63 -0
- package/angular-demo-app/src/services/posts-live-query.service.ts +86 -0
- package/angular-demo-app/src/services/typescript-demo.service.ts +59 -0
- package/angular-demo-app/src/styles.scss +50 -0
- package/angular-demo-app/tsconfig.app.json +13 -0
- package/angular-demo-app/tsconfig.json +34 -0
- package/angular-demo-app/tsconfig.spec.json +13 -0
- package/dist/Database.d.ts +206 -0
- package/dist/Database.js +288 -0
- package/dist/decorators/Column.d.ts +79 -0
- package/dist/decorators/Column.js +236 -0
- package/dist/decorators/Entity.d.ts +32 -0
- package/dist/decorators/Entity.js +44 -0
- package/dist/decorators/Relation.d.ts +70 -0
- package/dist/decorators/Relation.js +120 -0
- package/dist/decorators/index.d.ts +3 -0
- package/dist/decorators/index.js +3 -0
- package/dist/errors/ValidationError.d.ts +4 -0
- package/dist/errors/ValidationError.js +8 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +7 -0
- package/dist/metadata/Column.d.ts +8 -0
- package/dist/metadata/Column.js +44 -0
- package/dist/metadata/Entity.d.ts +11 -0
- package/dist/metadata/Entity.js +21 -0
- package/dist/metadata/Relation.d.ts +20 -0
- package/dist/metadata/Relation.js +74 -0
- package/dist/metadata/index.d.ts +3 -0
- package/dist/metadata/index.js +3 -0
- package/dist/services/AggregationService.d.ts +38 -0
- package/dist/services/AggregationService.js +229 -0
- package/dist/services/BaseEntity.d.ts +32 -0
- package/dist/services/BaseEntity.js +62 -0
- package/dist/services/CloudSyncService.d.ts +100 -0
- package/dist/services/CloudSyncService.js +196 -0
- package/dist/services/DecoratorUtils.d.ts +12 -0
- package/dist/services/DecoratorUtils.js +10 -0
- package/dist/services/EntityFactory.d.ts +25 -0
- package/dist/services/EntityFactory.js +27 -0
- package/dist/services/EntityRegistry.d.ts +61 -0
- package/dist/services/EntityRegistry.js +56 -0
- package/dist/services/EntitySchema.d.ts +56 -0
- package/dist/services/EntitySchema.js +125 -0
- package/dist/services/MigrationManager.d.ts +70 -0
- package/dist/services/MigrationManager.js +181 -0
- package/dist/services/RelationLoader.d.ts +66 -0
- package/dist/services/RelationLoader.js +310 -0
- package/dist/services/SchemaBuilder.d.ts +68 -0
- package/dist/services/SchemaBuilder.js +191 -0
- package/dist/services/index.d.ts +7 -0
- package/dist/services/index.js +7 -0
- package/dist/types.d.ts +152 -0
- package/dist/types.js +1 -0
- package/dist/utils/logger.d.ts +12 -0
- package/dist/utils/logger.js +16 -0
- package/eslint.config.js +49 -0
- package/homepage/favicon.svg +36 -0
- package/homepage/index.html +1725 -0
- package/package.json +78 -0
- package/react-demo-app/README.md +61 -0
- package/react-demo-app/eslint.config.js +60 -0
- package/react-demo-app/index.html +13 -0
- package/react-demo-app/package-lock.json +4955 -0
- package/react-demo-app/package.json +39 -0
- package/react-demo-app/src/App.tsx +172 -0
- package/react-demo-app/src/assets/react.svg +1 -0
- package/react-demo-app/src/components/Actions.tsx +171 -0
- package/react-demo-app/src/components/CloudSyncDemo.tsx +191 -0
- package/react-demo-app/src/components/LiveQueryDemo.tsx +122 -0
- package/react-demo-app/src/components/MainInfo.tsx +75 -0
- package/react-demo-app/src/components/PostsLiveQueryDemo.tsx +185 -0
- package/react-demo-app/src/components/TypeScriptDemo.tsx +190 -0
- package/react-demo-app/src/database/Database.ts +30 -0
- package/react-demo-app/src/entities/Post.ts +48 -0
- package/react-demo-app/src/entities/PostTag.ts +26 -0
- package/react-demo-app/src/entities/Profile.ts +41 -0
- package/react-demo-app/src/entities/Tag.ts +35 -0
- package/react-demo-app/src/entities/User.ts +61 -0
- package/react-demo-app/src/hooks/useAppLogic.ts +565 -0
- package/react-demo-app/src/hooks/useCloudSyncDemo.ts +84 -0
- package/react-demo-app/src/hooks/useLiveQueryDemo.ts +68 -0
- package/react-demo-app/src/hooks/usePostsLiveQueryDemo.ts +64 -0
- package/react-demo-app/src/hooks/useTypeScriptDemo.ts +43 -0
- package/react-demo-app/src/index.css +26 -0
- package/react-demo-app/src/main.tsx +18 -0
- package/react-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
- package/react-demo-app/src/migrations/002-add-post-category.ts +37 -0
- package/react-demo-app/src/migrations/index.ts +8 -0
- package/react-demo-app/src/vite-env.d.ts +1 -0
- package/react-demo-app/tsconfig.app.json +22 -0
- package/react-demo-app/tsconfig.json +6 -0
- package/react-demo-app/vite.config.ts +10 -0
- package/src/Database.ts +405 -0
- package/src/errors/ValidationError.ts +9 -0
- package/src/index.ts +13 -0
- package/src/metadata/Column.ts +74 -0
- package/src/metadata/Entity.ts +42 -0
- package/src/metadata/Relation.ts +121 -0
- package/src/metadata/index.ts +5 -0
- package/src/services/AggregationService.ts +348 -0
- package/src/services/BaseEntity.ts +77 -0
- package/src/services/CloudSyncService.ts +248 -0
- package/src/services/EntityFactory.ts +35 -0
- package/src/services/EntityRegistry.ts +109 -0
- package/src/services/EntitySchema.ts +154 -0
- package/src/services/MigrationManager.ts +276 -0
- package/src/services/RelationLoader.ts +532 -0
- package/src/services/SchemaBuilder.ts +237 -0
- package/src/services/index.ts +7 -0
- package/src/types.d.ts +1 -0
- package/src/types.ts +169 -0
- package/src/utils/logger.ts +40 -0
- package/svelte-demo-app/README.md +61 -0
- package/svelte-demo-app/package-lock.json +3000 -0
- package/svelte-demo-app/package.json +30 -0
- package/svelte-demo-app/src/app.d.ts +12 -0
- package/svelte-demo-app/src/app.html +13 -0
- package/svelte-demo-app/src/components/Actions.svelte +121 -0
- package/svelte-demo-app/src/components/CloudSyncDemo.svelte +333 -0
- package/svelte-demo-app/src/components/LiveQueryDemo.svelte +191 -0
- package/svelte-demo-app/src/components/MainInfo.svelte +133 -0
- package/svelte-demo-app/src/components/PostsLiveQueryDemo.svelte +330 -0
- package/svelte-demo-app/src/components/TypeScriptDemo.svelte +251 -0
- package/svelte-demo-app/src/database/Database.ts +29 -0
- package/svelte-demo-app/src/entities/Post.ts +46 -0
- package/svelte-demo-app/src/entities/PostTag.ts +22 -0
- package/svelte-demo-app/src/entities/Profile.ts +39 -0
- package/svelte-demo-app/src/entities/Tag.ts +33 -0
- package/svelte-demo-app/src/entities/User.ts +62 -0
- package/svelte-demo-app/src/lib/database/Database.ts +30 -0
- package/svelte-demo-app/src/lib/entities/Post.ts +47 -0
- package/svelte-demo-app/src/lib/entities/PostTag.ts +23 -0
- package/svelte-demo-app/src/lib/entities/Profile.ts +40 -0
- package/svelte-demo-app/src/lib/entities/Tag.ts +34 -0
- package/svelte-demo-app/src/lib/entities/User.ts +59 -0
- package/svelte-demo-app/src/lib/index.ts +7 -0
- package/svelte-demo-app/src/lib/migrations/001-add-user-email-index.ts +17 -0
- package/svelte-demo-app/src/lib/migrations/002-add-post-category.ts +37 -0
- package/svelte-demo-app/src/lib/migrations/index.ts +8 -0
- package/svelte-demo-app/src/migrations/001-add-user-email-index.ts +17 -0
- package/svelte-demo-app/src/migrations/002-add-post-category.ts +37 -0
- package/svelte-demo-app/src/migrations/index.ts +8 -0
- package/svelte-demo-app/src/routes/+layout.js +3 -0
- package/svelte-demo-app/src/routes/+layout.svelte +228 -0
- package/svelte-demo-app/src/routes/+page.js +3 -0
- package/svelte-demo-app/src/routes/+page.svelte +1305 -0
- package/svelte-demo-app/src/stores/appStore.js +603 -0
- package/svelte-demo-app/svelte.config.js +18 -0
- package/svelte-demo-app/tsconfig.json +14 -0
- package/svelte-demo-app/vite.config.ts +6 -0
- package/tests/aggregation.e2e.test.ts +87 -0
- package/tests/base-entity.e2e.test.ts +47 -0
- package/tests/database-api.e2e.test.ts +177 -0
- package/tests/decorators.e2e.test.ts +40 -0
- package/tests/entity-schema.e2e.test.ts +58 -0
- package/tests/relation-loader-table-names.test.ts +192 -0
- package/tests/relations.e2e.test.ts +178 -0
- package/tests/zod-runtime.e2e.test.ts +69 -0
- package/tsconfig.json +21 -0
- package/vitest.config.ts +21 -0
- package/vitest.setup.ts +27 -0
- package/vue-demo-app/README.md +61 -0
- package/vue-demo-app/index.html +13 -0
- package/vue-demo-app/package-lock.json +1537 -0
- package/vue-demo-app/package.json +27 -0
- package/vue-demo-app/src/App.vue +100 -0
- package/vue-demo-app/src/components/Actions.vue +135 -0
- package/vue-demo-app/src/components/CloudSyncDemo.vue +139 -0
- package/vue-demo-app/src/components/LiveQueryDemo.vue +122 -0
- package/vue-demo-app/src/components/MainInfo.vue +80 -0
- package/vue-demo-app/src/components/PostsLiveQueryDemo.vue +136 -0
- package/vue-demo-app/src/components/TypeScriptDemo.vue +133 -0
- package/vue-demo-app/src/database/Database.ts +29 -0
- package/vue-demo-app/src/entities/Post.ts +48 -0
- package/vue-demo-app/src/entities/PostTag.ts +24 -0
- package/vue-demo-app/src/entities/Profile.ts +41 -0
- package/vue-demo-app/src/entities/Tag.ts +35 -0
- package/vue-demo-app/src/entities/User.ts +61 -0
- package/vue-demo-app/src/main.ts +29 -0
- package/vue-demo-app/src/migrations/001-add-user-email-index.ts +23 -0
- package/vue-demo-app/src/migrations/002-add-post-category.ts +46 -0
- package/vue-demo-app/src/migrations/index.ts +14 -0
- package/vue-demo-app/src/services/useAppLogic.ts +565 -0
- package/vue-demo-app/src/services/useCloudSyncDemo.ts +84 -0
- package/vue-demo-app/src/services/useLiveQueryDemo.ts +82 -0
- package/vue-demo-app/src/services/usePostsLiveQueryDemo.ts +77 -0
- package/vue-demo-app/src/services/useTypeScriptDemo.ts +56 -0
- package/vue-demo-app/src/vite-env.d.ts +1 -0
- package/vue-demo-app/tsconfig.json +25 -0
- package/vue-demo-app/tsconfig.node.json +10 -0
- 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
|
+
}
|