mirror of
https://github.com/colanode/colanode.git
synced 2025-12-14 18:57:46 +01:00
Initiate monorepo
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -143,4 +143,6 @@ out/
|
||||
.yarn/unplugged
|
||||
dist/
|
||||
|
||||
.DS_Store
|
||||
.DS_Store
|
||||
.turbo
|
||||
.tsbuildinfo
|
||||
@@ -1,3 +1,4 @@
|
||||
dist
|
||||
out
|
||||
/tsconfig.base.json
|
||||
/tsconfig.base.json
|
||||
pnpm-lock.yaml
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"semi": true,
|
||||
"trailingComma": "all",
|
||||
"trailingComma": "es5",
|
||||
"singleQuote": true,
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2
|
||||
|
||||
@@ -1,34 +1,33 @@
|
||||
{
|
||||
"name": "neuron-server",
|
||||
"name": "@colanode/server",
|
||||
"version": "1.0.0",
|
||||
"main": "src/index.ts",
|
||||
"type": "module",
|
||||
"main": "./dist/index.js",
|
||||
"module": "./dist/index.js",
|
||||
"files": [
|
||||
"dist",
|
||||
".env"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc --project tsconfig.json && tsc-alias -p tsconfig.json",
|
||||
"start": "node dist/index.js",
|
||||
"dev": "node -r ts-node/register -r tsconfig-paths/register --env-file .env src/index.ts",
|
||||
"format": "prettier --write \"{src,test}/**/*.{js,ts}\""
|
||||
"compile": "tsc --noEmit",
|
||||
"build": "tsup-node",
|
||||
"clean": "del-cli dist isolate tsconfig.tsbuildinfo",
|
||||
"lint": "eslint . --max-warnings 0",
|
||||
"dev": "nodemon --env-file .env dist/index.js"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"author": "Hakan Shehu",
|
||||
"description": "",
|
||||
"devDependencies": {
|
||||
"@types/bcrypt": "^5.0.2",
|
||||
"@types/cors": "^2.8.17",
|
||||
"@types/express": "^4.17.21",
|
||||
"@types/jsonwebtoken": "^9.0.7",
|
||||
"@types/lodash": "^4.17.12",
|
||||
"@types/multer": "^1.4.12",
|
||||
"@types/node": "^22.7.7",
|
||||
"@types/pg": "^8.11.10",
|
||||
"@types/ws": "^8.5.12",
|
||||
"concurrently": "^9.0.1",
|
||||
"nodemon": "^3.1.7",
|
||||
"prettier": "^3.3.3",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsc-alias": "^1.8.10",
|
||||
"tsconfig-paths": "^4.2.0",
|
||||
"typescript": "^5.6.3"
|
||||
"tsup": "^8.3.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "^3.675.0",
|
||||
@@ -37,12 +36,12 @@
|
||||
"bcrypt": "^5.1.1",
|
||||
"bullmq": "^5.21.1",
|
||||
"cors": "^2.8.5",
|
||||
"dotenv": "^16.4.5",
|
||||
"express": "^4.21.1",
|
||||
"js-base64": "^3.7.7",
|
||||
"js-sha256": "^0.11.0",
|
||||
"kafkajs": "^2.2.4",
|
||||
"kysely": "^0.27.4",
|
||||
"lodash": "^4.17.21",
|
||||
"multer": "^1.4.5-lts.1",
|
||||
"pg": "^8.13.0",
|
||||
"postgres": "^3.4.4",
|
||||
@@ -7,12 +7,12 @@ import {
|
||||
PostgresDialect,
|
||||
UpdateResult,
|
||||
} from 'kysely';
|
||||
import { Pool } from 'pg';
|
||||
import pg from 'pg';
|
||||
import { DatabaseSchema } from '@/data/schema';
|
||||
import { databaseMigrations } from '@/data/migrations';
|
||||
|
||||
const dialect = new PostgresDialect({
|
||||
pool: new Pool({
|
||||
pool: new pg.Pool({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
}),
|
||||
});
|
||||
@@ -40,7 +40,7 @@ export const hasInsertChanges = (result: InsertResult[]): boolean => {
|
||||
}
|
||||
|
||||
return result.some(
|
||||
(r) => r.numInsertedOrUpdatedRows && r.numInsertedOrUpdatedRows > 0n,
|
||||
(r) => r.numInsertedOrUpdatedRows && r.numInsertedOrUpdatedRows > 0n
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,6 +3,9 @@ import { initRedis } from '@/data/redis';
|
||||
import { migrate } from '@/data/database';
|
||||
import { initEventWorker } from '@/queues/events';
|
||||
import { initTaskWorker } from '@/queues/tasks';
|
||||
import dotenv from 'dotenv';
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const init = async () => {
|
||||
await migrate();
|
||||
@@ -21,6 +21,9 @@ export const compareString = (a?: string | null, b?: string | null): number => {
|
||||
export const getNameFromEmail = (email: string): string => {
|
||||
// Extract the part before the @ symbol
|
||||
const namePart = email.split('@')[0];
|
||||
if (!namePart) {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Split by dots, underscores, and dashes, then capitalize each part
|
||||
const displayName = namePart
|
||||
@@ -16,7 +16,7 @@ import {
|
||||
import { ServerNodeAttributes } from '@/types/nodes';
|
||||
import { DeleteObjectCommand } from '@aws-sdk/client-s3';
|
||||
import { Job, Queue, Worker } from 'bullmq';
|
||||
import { difference } from 'lodash';
|
||||
import { difference } from 'lodash-es';
|
||||
|
||||
const eventQueue = new Queue('events', {
|
||||
connection: {
|
||||
@@ -59,7 +59,7 @@ const handleEventJob = async (job: Job) => {
|
||||
};
|
||||
|
||||
const handleNodeCreatedEvent = async (
|
||||
event: NodeCreatedEvent,
|
||||
event: NodeCreatedEvent
|
||||
): Promise<void> => {
|
||||
await createUserNodes(event);
|
||||
await synapse.sendSynapseMessage({
|
||||
@@ -70,7 +70,7 @@ const handleNodeCreatedEvent = async (
|
||||
};
|
||||
|
||||
const handleNodeUpdatedEvent = async (
|
||||
event: NodeUpdatedEvent,
|
||||
event: NodeUpdatedEvent
|
||||
): Promise<void> => {
|
||||
await checkForCollaboratorsChange(event);
|
||||
await synapse.sendSynapseMessage({
|
||||
@@ -81,7 +81,7 @@ const handleNodeUpdatedEvent = async (
|
||||
};
|
||||
|
||||
const handleNodeDeletedEvent = async (
|
||||
event: NodeDeletedEvent,
|
||||
event: NodeDeletedEvent
|
||||
): Promise<void> => {
|
||||
if (event.attributes.type === NodeTypes.File) {
|
||||
const command = new DeleteObjectCommand({
|
||||
@@ -167,19 +167,19 @@ const createUserNodes = async (event: NodeCreatedEvent): Promise<void> => {
|
||||
};
|
||||
|
||||
const checkForCollaboratorsChange = async (
|
||||
event: NodeUpdatedEvent,
|
||||
event: NodeUpdatedEvent
|
||||
): Promise<void> => {
|
||||
const beforeCollaborators = extractCollaboratorIds(event.beforeAttributes);
|
||||
const afterCollaborators = extractCollaboratorIds(event.afterAttributes);
|
||||
|
||||
const addedCollaborators = difference(
|
||||
afterCollaborators,
|
||||
beforeCollaborators,
|
||||
beforeCollaborators
|
||||
);
|
||||
|
||||
const removedCollaborators = difference(
|
||||
beforeCollaborators,
|
||||
afterCollaborators,
|
||||
afterCollaborators
|
||||
);
|
||||
|
||||
if (addedCollaborators.length === 0 && removedCollaborators.length === 0) {
|
||||
@@ -198,7 +198,7 @@ const checkForCollaboratorsChange = async (
|
||||
|
||||
const actualAddedCollaborators = difference(
|
||||
addedCollaborators,
|
||||
existingCollaboratorIds,
|
||||
existingCollaboratorIds
|
||||
);
|
||||
|
||||
if (actualAddedCollaborators.length > 0) {
|
||||
@@ -241,7 +241,7 @@ const checkForCollaboratorsChange = async (
|
||||
const nodeCollaboratorIds = nodeCollaborators.map((c) => c.collaboratorId);
|
||||
const actualRemovedCollaborators = difference(
|
||||
removedCollaborators,
|
||||
nodeCollaboratorIds,
|
||||
nodeCollaboratorIds
|
||||
);
|
||||
|
||||
if (actualRemovedCollaborators.length > 0) {
|
||||
@@ -170,7 +170,7 @@ workspacesRouter.post('/', async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
workspacesRouter.put(
|
||||
'/:id',
|
||||
async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
const id = req.params.id;
|
||||
const id = req.params.id as string;
|
||||
const input: WorkspaceInput = req.body;
|
||||
|
||||
if (!req.account) {
|
||||
@@ -276,13 +276,13 @@ workspacesRouter.put(
|
||||
};
|
||||
|
||||
return res.status(200).json(output);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
workspacesRouter.delete(
|
||||
'/:id',
|
||||
async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
const id = req.params.id;
|
||||
const id = req.params.id as string;
|
||||
|
||||
if (!req.account) {
|
||||
return res.status(401).json({
|
||||
@@ -330,13 +330,13 @@ workspacesRouter.delete(
|
||||
return res.status(200).json({
|
||||
id: workspace.id,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
workspacesRouter.get(
|
||||
'/:id',
|
||||
async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
const id = req.params.id;
|
||||
const id = req.params.id as string;
|
||||
|
||||
if (!req.account) {
|
||||
return res.status(401).json({
|
||||
@@ -400,7 +400,7 @@ workspacesRouter.get(
|
||||
};
|
||||
|
||||
return res.status(200).json(output);
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
workspacesRouter.get('/', async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
@@ -430,7 +430,7 @@ workspacesRouter.get('/', async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
.where(
|
||||
'id',
|
||||
'in',
|
||||
workspaceUsers.map((wa) => wa.id),
|
||||
workspaceUsers.map((wa) => wa.id)
|
||||
)
|
||||
.execute();
|
||||
|
||||
@@ -438,7 +438,7 @@ workspacesRouter.get('/', async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
|
||||
for (const workspace of workspaces) {
|
||||
const workspaceUser = workspaceUsers.find(
|
||||
(wa) => wa.workspace_id === workspace.id,
|
||||
(wa) => wa.workspace_id === workspace.id
|
||||
);
|
||||
|
||||
if (!workspaceUser) {
|
||||
@@ -474,7 +474,7 @@ workspacesRouter.get('/', async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
workspacesRouter.post(
|
||||
'/:id/users',
|
||||
async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
const id = req.params.id;
|
||||
const id = req.params.id as string;
|
||||
const input: WorkspaceAccountsInviteInput = req.body;
|
||||
|
||||
if (!input.emails || input.emails.length === 0) {
|
||||
@@ -545,14 +545,14 @@ workspacesRouter.post(
|
||||
eb.and([
|
||||
eb('account_id', 'in', existingAccountIds),
|
||||
eb('workspace_id', '=', workspace.id),
|
||||
]),
|
||||
])
|
||||
)
|
||||
.execute();
|
||||
}
|
||||
|
||||
if (existingWorkspaceUsers.length > 0) {
|
||||
const existingUserIds = existingWorkspaceUsers.map(
|
||||
(workspaceAccount) => workspaceAccount.id,
|
||||
(workspaceAccount) => workspaceAccount.id
|
||||
);
|
||||
existingUsers = await database
|
||||
.selectFrom('nodes')
|
||||
@@ -592,12 +592,12 @@ workspacesRouter.post(
|
||||
}
|
||||
|
||||
const existingWorkspaceUser = existingWorkspaceUsers.find(
|
||||
(workspaceUser) => workspaceUser.account_id === account!.id,
|
||||
(workspaceUser) => workspaceUser.account_id === account!.id
|
||||
);
|
||||
|
||||
if (existingWorkspaceUser) {
|
||||
const existingUser = existingUsers.find(
|
||||
(user) => user.id === existingWorkspaceUser.id,
|
||||
(user) => user.id === existingWorkspaceUser.id
|
||||
);
|
||||
if (!existingUser) {
|
||||
return res.status(500).json({
|
||||
@@ -708,14 +708,14 @@ workspacesRouter.post(
|
||||
return res.status(200).json({
|
||||
users: users,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
workspacesRouter.put(
|
||||
'/:id/users/:userId',
|
||||
async (req: NeuronRequest, res: NeuronResponse) => {
|
||||
const id = req.params.id;
|
||||
const userId = req.params.userId;
|
||||
const id = req.params.id as string;
|
||||
const userId = req.params.userId as string;
|
||||
const input: WorkspaceAccountRoleUpdateInput = req.body;
|
||||
|
||||
if (!req.account) {
|
||||
@@ -852,5 +852,5 @@ workspacesRouter.put(
|
||||
return res.status(200).json({
|
||||
user: userNode,
|
||||
});
|
||||
},
|
||||
}
|
||||
);
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class BoardViewValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -29,7 +29,7 @@ export class BoardViewValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -45,7 +45,7 @@ export class BoardViewValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class CalendarViewValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ export class CalendarViewValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -46,7 +46,7 @@ export class CalendarViewValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class ChannelValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ export class ChannelValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -46,7 +46,7 @@ export class ChannelValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class FolderValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ export class FolderValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -46,7 +46,7 @@ export class FolderValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasCollaboratorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class MessageValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -26,7 +26,7 @@ export class MessageValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (
|
||||
!isEqual(attributes.content, node.attributes.content) &&
|
||||
@@ -45,7 +45,7 @@ export class MessageValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
if (node.createdBy === workspaceUser.id) {
|
||||
return true;
|
||||
@@ -1,6 +1,6 @@
|
||||
import { SelectWorkspaceUser } from '@/data/schema';
|
||||
import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
@@ -8,7 +8,7 @@ import { Validator } from '@/types/validators';
|
||||
export class PageValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ export class PageValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -46,7 +46,7 @@ export class PageValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class SelectOptionValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -30,7 +30,7 @@ export class SelectOptionValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -46,7 +46,7 @@ export class SelectOptionValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -3,12 +3,12 @@ import { hasAdminAccess, hasEditorAccess } from '@/lib/constants';
|
||||
import { fetchNodeRole } from '@/lib/nodes';
|
||||
import { ServerNode, ServerNodeAttributes } from '@/types/nodes';
|
||||
import { Validator } from '@/types/validators';
|
||||
import { isEqual } from 'lodash';
|
||||
import { isEqual } from 'lodash-es';
|
||||
|
||||
export class TableViewValidator implements Validator {
|
||||
async canCreate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
if (!attributes.parentId) {
|
||||
return false;
|
||||
@@ -29,7 +29,7 @@ export class TableViewValidator implements Validator {
|
||||
async canUpdate(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
attributes: ServerNodeAttributes,
|
||||
attributes: ServerNodeAttributes
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
@@ -45,7 +45,7 @@ export class TableViewValidator implements Validator {
|
||||
|
||||
async canDelete(
|
||||
workspaceUser: SelectWorkspaceUser,
|
||||
node: ServerNode,
|
||||
node: ServerNode
|
||||
): Promise<boolean> {
|
||||
const role = await fetchNodeRole(node.id, workspaceUser.id);
|
||||
if (!role) {
|
||||
15
apps/server/tsconfig.json
Normal file
15
apps/server/tsconfig.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Server",
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"references": [
|
||||
{
|
||||
"path": "../../packages/core"
|
||||
}
|
||||
]
|
||||
}
|
||||
18
apps/server/tsup.config.ts
Normal file
18
apps/server/tsup.config.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { defineConfig } from 'tsup';
|
||||
|
||||
export default defineConfig({
|
||||
entry: ['src/index.ts'],
|
||||
format: ['esm'],
|
||||
target: 'es2022',
|
||||
sourcemap: true,
|
||||
/**
|
||||
* The common package is using the internal packages approach, so it needs to
|
||||
* be transpiled / bundled together with the deployed code.
|
||||
*/
|
||||
noExternal: ['@colanode/core'],
|
||||
/**
|
||||
* Do not use tsup for generating d.ts files because it can not generate type
|
||||
* the definition maps required for go-to-definition to work in our IDE. We
|
||||
* use tsc for that.
|
||||
*/
|
||||
});
|
||||
19
apps/server/turbo.json
Normal file
19
apps/server/turbo.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"extends": ["//"],
|
||||
"globalDependencies": [".env"],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"env": ["DEMO_ENV_VAR"],
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["coverage/**"],
|
||||
"inputs": ["src/**/*.tsx", "src/**/*.ts"]
|
||||
},
|
||||
"lint": {
|
||||
"dependsOn": ["^lint"]
|
||||
}
|
||||
}
|
||||
}
|
||||
32
package.json
Normal file
32
package.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "@colanode",
|
||||
"description": "Colanode monorepo",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@9.0.4+sha256.caa915eaae9d9aefccf50ee8aeda25a2f8684d8f9d5c6e367eaf176d97c1f89e",
|
||||
"author": "Hakan Shehu",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/colanode/colanode"
|
||||
},
|
||||
"scripts": {
|
||||
"compile": "turbo run compile",
|
||||
"build": "turbo run build",
|
||||
"clean": "turbo run clean",
|
||||
"dev": "turbo run dev",
|
||||
"watch": "turbo watch build --filter=@colanode/core --filter=@colanode/server",
|
||||
"lint": "turbo run lint --parallel",
|
||||
"test": "turbo run test -- --watch false",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/lodash-es": "^4.17.12",
|
||||
"prettier": "^3.3.3",
|
||||
"turbo": "^2.1.3",
|
||||
"typescript": "^5.6.3",
|
||||
"vitest": "^1.6.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"lodash-es": "^4.17.21"
|
||||
}
|
||||
}
|
||||
26
packages/core/package.json
Normal file
26
packages/core/package.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"name": "@colanode/core",
|
||||
"version": "1.0.0",
|
||||
"type": "module",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"files": [
|
||||
"src"
|
||||
],
|
||||
"scripts": {
|
||||
"compile": "tsc --noEmit",
|
||||
"test": "vitest",
|
||||
"lint": "eslint . --max-warnings 0",
|
||||
"build?": "No build step required. This package links directly to its source files",
|
||||
"coverage": "vitest run --coverage "
|
||||
},
|
||||
"author": "Hakan Shehu",
|
||||
"devDependencies": {
|
||||
"eslint": "^8.57.1",
|
||||
"prettier": "^3.3.3",
|
||||
"typescript": "^5.6.3",
|
||||
"vitest": "^1.6.0"
|
||||
}
|
||||
}
|
||||
3
packages/core/src/index.ts
Normal file
3
packages/core/src/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export const core = () => {
|
||||
return 'core library';
|
||||
};
|
||||
10
packages/core/tsconfig.json
Normal file
10
packages/core/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Core Library",
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"composite": true
|
||||
}
|
||||
}
|
||||
13
packages/core/vitest.config.ts
Normal file
13
packages/core/vitest.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import path from 'node:path';
|
||||
import { configDefaults, defineConfig } from 'vitest/config';
|
||||
|
||||
export default defineConfig({
|
||||
test: {
|
||||
exclude: [...configDefaults.exclude],
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
'~': path.resolve(__dirname, './src'),
|
||||
},
|
||||
},
|
||||
});
|
||||
6016
pnpm-lock.yaml
generated
Normal file
6016
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
3
pnpm-workspace.yaml
Normal file
3
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
packages:
|
||||
- "apps/*"
|
||||
- "packages/*"
|
||||
5822
server/package-lock.json
generated
5822
server/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "commonjs",
|
||||
"outDir": "./dist",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"noEmit": false,
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
34
tsconfig.base.json
Normal file
34
tsconfig.base.json
Normal file
@@ -0,0 +1,34 @@
|
||||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"display": "Base Configuration",
|
||||
"compilerOptions": {
|
||||
/* Base Options: */
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"target": "esnext",
|
||||
"lib": ["esnext"],
|
||||
"allowJs": true,
|
||||
"resolveJsonModule": true,
|
||||
"moduleDetection": "force",
|
||||
"isolatedModules": true,
|
||||
"verbatimModuleSyntax": false,
|
||||
|
||||
/* Strictness */
|
||||
"strict": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"noImplicitOverride": true,
|
||||
|
||||
/* Opinion */
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "${configDir}/tsconfig.tsbuildinfo",
|
||||
"module": "preserve",
|
||||
"outDir": "${configDir}/dist",
|
||||
"baseUrl": "${configDir}",
|
||||
"rootDir": "${configDir}/src",
|
||||
"paths": {
|
||||
"~/*": ["./src/*"]
|
||||
}
|
||||
},
|
||||
"include": ["${configDir}/src", "${configDir}/src/**/*.json"],
|
||||
"exclude": ["${configDir}/node_modules", "${configDir}/dist"]
|
||||
}
|
||||
24
turbo.json
Normal file
24
turbo.json
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"$schema": "https://turbo.build/schema.json",
|
||||
"globalDependencies": [".env", "**/.env.*local"],
|
||||
"tasks": {
|
||||
"build": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["dist/**"]
|
||||
},
|
||||
"lint": {
|
||||
"dependsOn": ["^lint"]
|
||||
},
|
||||
"test": {
|
||||
"dependsOn": ["^build"],
|
||||
"outputs": ["coverage/**"],
|
||||
"inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"]
|
||||
},
|
||||
"compile": {
|
||||
"dependsOn": ["^compile"]
|
||||
},
|
||||
"clean": {
|
||||
"dependsOn": ["^clean"]
|
||||
}
|
||||
}
|
||||
}
|
||||
3
vitest.workspace.ts
Normal file
3
vitest.workspace.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { defineWorkspace } from "vitest/config";
|
||||
|
||||
export default defineWorkspace(["packages/*", "apps/*"]);
|
||||
Reference in New Issue
Block a user