mirror of
https://github.com/ahmadk953/tasko.git
synced 2025-01-31 09:03:36 +00:00
Started Adding Liveblocks
This commit is contained in:
parent
cde7e7ab6e
commit
03dd8df0f1
4 changed files with 248 additions and 3 deletions
26
app/api/liveblocks-auth/route.ts
Normal file
26
app/api/liveblocks-auth/route.ts
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
import { Liveblocks } from '@liveblocks/node';
|
||||||
|
import { useUser, auth } from '@clerk/nextjs';
|
||||||
|
|
||||||
|
const liveblocks = new Liveblocks({
|
||||||
|
secret: process.env.LIVEBLOCKS_SECRET_DEV_API_KEY!,
|
||||||
|
});
|
||||||
|
|
||||||
|
export async function POST(req: Request) {
|
||||||
|
const { user } = useUser();
|
||||||
|
const { orgId } = auth();
|
||||||
|
|
||||||
|
if (!orgId || !user) return new Response('Unauthorized', { status: 401 });
|
||||||
|
|
||||||
|
// Start an auth session inside your endpoint
|
||||||
|
const session = liveblocks.prepareSession(user.id);
|
||||||
|
|
||||||
|
// Implement your own security, and give the user access to the room
|
||||||
|
const { room } = await req.json();
|
||||||
|
if (room) {
|
||||||
|
session.allow(room, session.FULL_ACCESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authorize the user and return the result
|
||||||
|
const { status, body } = await session.authorize();
|
||||||
|
return new Response(body, { status });
|
||||||
|
}
|
127
liveblocks.config.ts
Normal file
127
liveblocks.config.ts
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
import { createClient } from '@liveblocks/client';
|
||||||
|
import { createRoomContext } from '@liveblocks/react';
|
||||||
|
|
||||||
|
const client = createClient({
|
||||||
|
// publicApiKey: process.env.LIVEBLOCKS_PUBLIC_DEV_API_KEY!,
|
||||||
|
authEndpoint: '/api/liveblocks-auth',
|
||||||
|
// throttle: 100,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Presence represents the properties that exist on every user in the Room
|
||||||
|
// and that will automatically be kept in sync. Accessible through the
|
||||||
|
// `user.presence` property. Must be JSON-serializable.
|
||||||
|
type Presence = {
|
||||||
|
// cursor: { x: number, y: number } | null,
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optionally, Storage represents the shared document that persists in the
|
||||||
|
// Room, even after all users leave. Fields under Storage typically are
|
||||||
|
// LiveList, LiveMap, LiveObject instances, for which updates are
|
||||||
|
// automatically persisted and synced to all connected clients.
|
||||||
|
type Storage = {
|
||||||
|
// author: LiveObject<{ firstName: string, lastName: string }>,
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optionally, UserMeta represents static/readonly metadata on each user, as
|
||||||
|
// provided by your own custom auth back end (if used). Useful for data that
|
||||||
|
// will not change during a session, like a user's name or avatar.
|
||||||
|
type UserMeta = {
|
||||||
|
id?: string; // Accessible through `user.id`
|
||||||
|
// info?: Json, // Accessible through `user.info`
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optionally, the type of custom events broadcast and listened to in this
|
||||||
|
// room. Use a union for multiple events. Must be JSON-serializable.
|
||||||
|
type RoomEvent = {
|
||||||
|
// type: "NOTIFICATION",
|
||||||
|
// ...
|
||||||
|
};
|
||||||
|
|
||||||
|
// Optionally, when using Comments, ThreadMetadata represents metadata on
|
||||||
|
// each thread. Can only contain booleans, strings, and numbers.
|
||||||
|
export type ThreadMetadata = {
|
||||||
|
// resolved: boolean;
|
||||||
|
// quote: string;
|
||||||
|
// time: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const {
|
||||||
|
suspense: {
|
||||||
|
RoomProvider,
|
||||||
|
useRoom,
|
||||||
|
useMyPresence,
|
||||||
|
useUpdateMyPresence,
|
||||||
|
useSelf,
|
||||||
|
useOthers,
|
||||||
|
useOthersMapped,
|
||||||
|
useOthersConnectionIds,
|
||||||
|
useOther,
|
||||||
|
useBroadcastEvent,
|
||||||
|
useEventListener,
|
||||||
|
useErrorListener,
|
||||||
|
useStorage,
|
||||||
|
useObject,
|
||||||
|
useMap,
|
||||||
|
useList,
|
||||||
|
useBatch,
|
||||||
|
useHistory,
|
||||||
|
useUndo,
|
||||||
|
useRedo,
|
||||||
|
useCanUndo,
|
||||||
|
useCanRedo,
|
||||||
|
useMutation,
|
||||||
|
useStatus,
|
||||||
|
useLostConnectionListener,
|
||||||
|
useThreads,
|
||||||
|
useUser,
|
||||||
|
useCreateThread,
|
||||||
|
useEditThreadMetadata,
|
||||||
|
useCreateComment,
|
||||||
|
useEditComment,
|
||||||
|
useDeleteComment,
|
||||||
|
useAddReaction,
|
||||||
|
useRemoveReaction,
|
||||||
|
},
|
||||||
|
} = createRoomContext<Presence, Storage, UserMeta, RoomEvent, ThreadMetadata>(
|
||||||
|
client,
|
||||||
|
{
|
||||||
|
async resolveUsers({ userIds }) {
|
||||||
|
// Used only for Comments. Return a list of user information retrieved
|
||||||
|
// from `userIds`. This info is used in comments, mentions etc.
|
||||||
|
|
||||||
|
// const usersData = await __fetchUsersFromDB__(userIds);
|
||||||
|
//
|
||||||
|
// return usersData.map((userData) => ({
|
||||||
|
// name: userData.name,
|
||||||
|
// avatar: userData.avatar.src,
|
||||||
|
// }));
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
async resolveMentionSuggestions({ text, roomId }) {
|
||||||
|
// Used only for Comments. Return a list of userIds that match `text`.
|
||||||
|
// These userIds are used to create a mention list when typing in the
|
||||||
|
// composer.
|
||||||
|
//
|
||||||
|
// For example when you type "@jo", `text` will be `"jo"`, and
|
||||||
|
// you should to return an array with John and Joanna's userIds:
|
||||||
|
// ["john@example.com", "joanna@example.com"]
|
||||||
|
|
||||||
|
// const userIds = await __fetchAllUserIdsFromDB__(roomId);
|
||||||
|
//
|
||||||
|
// Return all userIds if no `text`
|
||||||
|
// if (!text) {
|
||||||
|
// return userIds;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// Otherwise, filter userIds for the search `text` and return
|
||||||
|
// return userIds.filter((userId) =>
|
||||||
|
// userId.toLowerCase().includes(text.toLowerCase())
|
||||||
|
// );
|
||||||
|
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
89
package-lock.json
generated
89
package-lock.json
generated
|
@ -11,6 +11,9 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clerk/nextjs": "^4.29.3",
|
"@clerk/nextjs": "^4.29.3",
|
||||||
"@hello-pangea/dnd": "^16.5.0",
|
"@hello-pangea/dnd": "^16.5.0",
|
||||||
|
"@liveblocks/client": "^1.9.8",
|
||||||
|
"@liveblocks/node": "^1.9.8",
|
||||||
|
"@liveblocks/react": "^1.9.8",
|
||||||
"@prisma/client": "^5.9.1",
|
"@prisma/client": "^5.9.1",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
|
@ -480,6 +483,44 @@
|
||||||
"@jridgewell/sourcemap-codec": "^1.4.14"
|
"@jridgewell/sourcemap-codec": "^1.4.14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@liveblocks/client": {
|
||||||
|
"version": "1.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@liveblocks/client/-/client-1.9.8.tgz",
|
||||||
|
"integrity": "sha512-qNFHMKOLLPNlo0HaVL7jfh877PngWYIxuZrpfnFdttR/NtDlt1gH9cL/xoyV5roULf6a5tONcMt2NqJXAFkVEw==",
|
||||||
|
"dependencies": {
|
||||||
|
"@liveblocks/core": "1.9.8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@liveblocks/core": {
|
||||||
|
"version": "1.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@liveblocks/core/-/core-1.9.8.tgz",
|
||||||
|
"integrity": "sha512-sIt/pqQzdMSePYxT/9YAhsR8KKDSGDo9uO8S4LJKp7wR2AgzjfXJfEFMXUe2W3D+ugzo5RZODccJS6OdgGzEnQ=="
|
||||||
|
},
|
||||||
|
"node_modules/@liveblocks/node": {
|
||||||
|
"version": "1.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@liveblocks/node/-/node-1.9.8.tgz",
|
||||||
|
"integrity": "sha512-bK88vp0k3P9UngomiZjqhsiyUWKbyUvHmqeCgeSSksu1pjoivVDFu22WJrJRQws4g7+DdfCXN7kzQMD5QKVSzg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@liveblocks/core": "1.9.8",
|
||||||
|
"@stablelib/base64": "^1.0.1",
|
||||||
|
"fast-sha256": "^1.3.0",
|
||||||
|
"node-fetch": "^2.6.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@liveblocks/react": {
|
||||||
|
"version": "1.9.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/@liveblocks/react/-/react-1.9.8.tgz",
|
||||||
|
"integrity": "sha512-8ZXHeG8StX5g/YZ5LYejgHBPC5WAQX8vqxshsT0kVyvP+vZCId0FCA/74uAp5DTzP0UVyQ28mINWsHqVC7t/9w==",
|
||||||
|
"dependencies": {
|
||||||
|
"@liveblocks/client": "1.9.8",
|
||||||
|
"@liveblocks/core": "1.9.8",
|
||||||
|
"nanoid": "^3",
|
||||||
|
"use-sync-external-store": "^1.2.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"react": "^16.14.0 || ^17 || ^18"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@next/env": {
|
"node_modules/@next/env": {
|
||||||
"version": "14.0.4",
|
"version": "14.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/@next/env/-/env-14.0.4.tgz",
|
||||||
|
@ -1471,6 +1512,11 @@
|
||||||
"integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==",
|
"integrity": "sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/@stablelib/base64": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@stablelib/base64/-/base64-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-1bnPQqSxSuc3Ii6MhBysoWCg58j97aUjuCSZrGSmDxNqtytIi0k8utUenAwTZN4V5mXXYGsVUI9zeBqy+jBOSQ=="
|
||||||
|
},
|
||||||
"node_modules/@swc/helpers": {
|
"node_modules/@swc/helpers": {
|
||||||
"version": "0.5.2",
|
"version": "0.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
|
"resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.2.tgz",
|
||||||
|
@ -3555,6 +3601,11 @@
|
||||||
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/fast-sha256": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-sha256/-/fast-sha256-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ=="
|
||||||
|
},
|
||||||
"node_modules/fastq": {
|
"node_modules/fastq": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
|
||||||
|
@ -4823,6 +4874,25 @@
|
||||||
"tslib": "^2.0.3"
|
"tslib": "^2.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "2.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
|
||||||
|
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
|
||||||
|
"dependencies": {
|
||||||
|
"whatwg-url": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "4.x || >=6.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"encoding": "^0.1.0"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"encoding": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-fetch-native": {
|
"node_modules/node-fetch-native": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.0.1.tgz",
|
||||||
|
@ -6403,6 +6473,11 @@
|
||||||
"to-no-case": "^1.0.0"
|
"to-no-case": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/tr46": {
|
||||||
|
"version": "0.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
|
||||||
|
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
|
||||||
|
},
|
||||||
"node_modules/ts-api-utils": {
|
"node_modules/ts-api-utils": {
|
||||||
"version": "1.2.1",
|
"version": "1.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz",
|
||||||
|
@ -6711,6 +6786,20 @@
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
|
||||||
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
"integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
|
||||||
},
|
},
|
||||||
|
"node_modules/webidl-conversions": {
|
||||||
|
"version": "3.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
|
||||||
|
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
|
||||||
|
},
|
||||||
|
"node_modules/whatwg-url": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
|
||||||
|
"dependencies": {
|
||||||
|
"tr46": "~0.0.3",
|
||||||
|
"webidl-conversions": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/which": {
|
"node_modules/which": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@clerk/nextjs": "^4.29.3",
|
"@clerk/nextjs": "^4.29.3",
|
||||||
"@hello-pangea/dnd": "^16.5.0",
|
"@hello-pangea/dnd": "^16.5.0",
|
||||||
|
"@liveblocks/client": "^1.9.8",
|
||||||
|
"@liveblocks/node": "^1.9.8",
|
||||||
|
"@liveblocks/react": "^1.9.8",
|
||||||
"@prisma/client": "^5.9.1",
|
"@prisma/client": "^5.9.1",
|
||||||
"@radix-ui/react-accordion": "^1.1.2",
|
"@radix-ui/react-accordion": "^1.1.2",
|
||||||
"@radix-ui/react-avatar": "^1.0.4",
|
"@radix-ui/react-avatar": "^1.0.4",
|
||||||
|
@ -42,20 +45,20 @@
|
||||||
"zustand": "^4.4.7"
|
"zustand": "^4.4.7"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@next/eslint-plugin-next": "^14.1.0",
|
||||||
"@types/lodash": "^4.14.202",
|
"@types/lodash": "^4.14.202",
|
||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^18",
|
"@types/react": "^18",
|
||||||
"@types/react-dom": "^18",
|
"@types/react-dom": "^18",
|
||||||
"autoprefixer": "^10.0.1",
|
|
||||||
"@next/eslint-plugin-next": "^14.1.0",
|
|
||||||
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
"@typescript-eslint/eslint-plugin": "^7.0.0",
|
||||||
"@typescript-eslint/parser": "^7.0.0",
|
"@typescript-eslint/parser": "^7.0.0",
|
||||||
|
"autoprefixer": "^10.0.1",
|
||||||
"eslint": "^8.56.0",
|
"eslint": "^8.56.0",
|
||||||
"eslint-config-next": "^14.1.0",
|
"eslint-config-next": "^14.1.0",
|
||||||
"eslint-config-prettier": "^9.1.0",
|
"eslint-config-prettier": "^9.1.0",
|
||||||
|
"postcss": "^8",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.11",
|
"prettier-plugin-tailwindcss": "^0.5.11",
|
||||||
"postcss": "^8",
|
|
||||||
"prisma": "^5.9.1",
|
"prisma": "^5.9.1",
|
||||||
"tailwindcss": "^3.3.0",
|
"tailwindcss": "^3.3.0",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
|
|
Loading…
Reference in a new issue