Skip to content

Commit

Permalink
feat(folder): improve folder structure management
Browse files Browse the repository at this point in the history
  • Loading branch information
tericcabrel committed Oct 23, 2022
1 parent 0a61e9e commit ba33946
Show file tree
Hide file tree
Showing 43 changed files with 214 additions and 46 deletions.
2 changes: 1 addition & 1 deletion apps/core/src/resources/folders/queries/list-directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const listDirectory: QueryResolvers['listDirectory'] = async (_parent, ar

const folders = await context.db.folder.findSubFolders(userId, args.folderId);
const snippets = await context.db.snippet.findByFolder(args.folderId);
const paths = await context.db.folder.generateDirectoryPath(args.folderId);
const paths = await context.db.folder.generateBreadcrumb(args.folderId);

return {
folders,
Expand Down
2 changes: 1 addition & 1 deletion apps/core/src/resources/snippets/queries/find-snippet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export const findSnippet: QueryResolvers['findSnippet'] = async (_parent, args,

try {
const snippet = await context.db.snippet.findById(args.snippetId);
const paths = await context.db.folder.generateDirectoryPath(snippet.folderId);
const paths = await context.db.folder.generateBreadcrumb(snippet.folderId);

return {
paths,
Expand Down
File renamed without changes.
1 change: 1 addition & 0 deletions packages/database/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"build": "tsc --project tsconfig.prod.json",
"clean": "rm -rf .turbo dist",
"lint": "eslint src index.ts",
"test": "jest",
"db:dev": "pscale connect sharingan dev --port 3311",
"db:shadow": "docker run -d --rm -e MYSQL_ROOT_PASSWORD=secret -e MYSQL_DATABASE=sharingan --name sharingan-shadow-db -p 3312:3306 mysql:8.0",
"db:shadow:stop": "docker kill sharingan-shadow-db && docker container prune -f",
Expand Down
1 change: 1 addition & 0 deletions packages/database/prisma/schema.test.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ model Folder {
userId String @map("user_id") @db.VarChar(50)
parentId String? @map("parent_id")
name String @db.VarChar(255)
path String? @db.Text
isFavorite Boolean @default(false) @map("is_favorite")
createdAt DateTime @default(now()) @map("created_at")
updatedAt DateTime @updatedAt @map("updated_at")
Expand Down
4 changes: 2 additions & 2 deletions packages/database/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
"outDir": "./dist",
"declaration": true,
"composite": true,
"sourceMap": true
"sourceMap": false
},
"files": ["env.d.ts"],
"include": ["./src/**/*", "./tests/**/*", "index.ts"],
"include": ["src", "__tests__", "index.ts"],
"exclude": [
"node_modules"
]
Expand Down
4 changes: 3 additions & 1 deletion packages/database/tsconfig.prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"compilerOptions": {
"sourceMap": false
},
"exclude": ["tests"]
"exclude": [
"__tests__"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ describe('Test Create Folder DTO', () => {
isFavorite: false,
name: 'blogs',
parentId: 'cl23rzwe5000002czaedc8sll',
path: null,
updatedAt: expect.any(Date),
userId: 'dm34saxf6111113dabfed9tmm',
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ describe('Test Create User Root Folder DTO', () => {
isFavorite: false,
name: '__dm34saxf6111113dabfed9tmm__',
parentId: null,
path: null,
updatedAt: expect.any(Date),
userId: 'dm34saxf6111113dabfed9tmm',
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { Folder } from '@sharingan/database';

import { UpdateFolderDto } from '../../../../index';
import { createTestFolderDto, generateTestId } from '../../../setup/test-utils';

describe('Test Update Folder DTO', () => {
it('should return the folder to update', () => {
const parentId = generateTestId();
const userId = generateTestId();

const dto = new UpdateFolderDto({
creatorId: userId,
folderId: parentId,
name: 'folder updated',
});

const currentFolder = createTestFolderDto({ parentId, userId }).toFolder();

const folderToUpdate = dto.toFolder(currentFolder);

const expectedFolder: Folder = {
createdAt: currentFolder.createdAt,
id: currentFolder.id,
isFavorite: currentFolder.isFavorite,
name: 'folder updated',
parentId: currentFolder.parentId,
path: currentFolder.path,
updatedAt: currentFolder.updatedAt,
userId: currentFolder.userId,
};

expect(folderToUpdate).toMatchObject(expectedFolder);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { CreateUserRootFolderDto } from '../../../index';
import CreateFolderDto from '../../../src/folders/dtos/create-folder-dto';
import {
createManyTestFolders,
createTestFolderDto,
createTestUser,
createUserWithRootFolder,
deleteTestFoldersById,
Expand Down Expand Up @@ -248,4 +249,47 @@ describe('Test Folder service', () => {
await deleteTestUsersById([user1.id]);
await deleteTestUsersById([user2.id]);
});

it('should generate the breadcrumb path of a folder', async () => {
// GIVEN
const [user, rootFolder] = await createUserWithRootFolder();

const gistFolderDto = createTestFolderDto({
name: 'My gist',
parentId: rootFolder.id,
userId: user.id,
});
const gistFolder = await folderService.create(gistFolderDto);

const nodeFolderDto = createTestFolderDto({
name: 'Node.js',
parentId: gistFolder.id,
userId: user.id,
});
const nodeFolder = await folderService.create(nodeFolderDto);

// WHEN
const subFolders = await folderService.generateBreadcrumb(nodeFolder.id);

// THEN
expect(subFolders).toHaveLength(2);
expect(subFolders.map((folder) => folder.name)).toEqual(['My gist', 'Node.js']);

await deleteTestFoldersById([nodeFolder.id, gistFolder.id, rootFolder.id]);
await deleteTestUsersById([user.id]);
});

it('should generate the breadcrumb path of the root folder', async () => {
// GIVEN
const [user, rootFolder] = await createUserWithRootFolder();

// WHEN
const subFolders = await folderService.generateBreadcrumb(rootFolder.id);

// THEN
expect(subFolders).toHaveLength(0);

await deleteTestFoldersById([rootFolder.id]);
await deleteTestUsersById([user.id]);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import DeleteSnippetDto from '../../../../src/snippets/dtos/delete-snippet-dto';
import { generateTestId } from '../../../setup/test-utils';

describe('Test Delete Snippet DTO', () => {
it('should have the right property defined', () => {
const snippetId = generateTestId();
const userId = generateTestId();

// GIVEN
const dto = new DeleteSnippetDto({
creatorId: userId,
snippetId,
});

// WHEN
// THEN
expect(dto.snippetId).toEqual(snippetId);
expect(dto.creatorId).toEqual(userId);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Snippet } from '@sharingan/database';

import { UpdateSnippetDto } from '../../../../index';
import { createTestSnippetDto, generateTestId } from '../../../setup/test-utils';

describe('Test Update Snippet DTO', () => {
it('should have the right property defined to update the snippet', () => {
const snippetId = generateTestId();
const userId = generateTestId();

const dto = new UpdateSnippetDto({
content:
'import React from "react";\n\nexport const App = () => {\n\n\treturn(\n\t\t<div>Hello Updated</div>\n\t);\n};',
creatorId: userId,
description: 'Basic react component updated',
language: 'tsx',
lineHighlight: '[[1, "diff-add"]]',
name: 'app-updated.tsx',
snippetId,
theme: 'one-dark-pro',
visibility: 'private',
});

const folderId = generateTestId();
const currentSnippet = createTestSnippetDto({
folderId,
name: 'app.tsx',
userId,
visibility: 'public',
}).toSnippet();

const snippetToUpdate = dto.toSnippet(currentSnippet);

const expectedSnippet: Snippet = {
content:
'import React from "react";\n\nexport const App = () => {\n\n\treturn(\n\t\t<div>Hello Updated</div>\n\t);\n};',
createdAt: currentSnippet.createdAt,
description: 'Basic react component updated',
folderId: snippetToUpdate.folderId,
id: currentSnippet.id,
language: 'tsx',
lineHighlight: '[[1, "diff-add"]]',
name: 'app-updated.tsx',
size: expect.any(Number),
theme: 'one-dark-pro',
updatedAt: currentSnippet.updatedAt,
userId,
visibility: 'private',
};

expect(snippetToUpdate).toMatchObject(expectedSnippet);
});
});
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,9 @@ export const createManyTestFolders = async ({

export const generateTestId = (): string => dbId.generate();

export const createTestFolderDto = (args?: { parentId?: string; userId?: string }): CreateFolderDto => {
export const createTestFolderDto = (args?: { name?: string; parentId?: string; userId?: string }): CreateFolderDto => {
return new CreateFolderDto({
name: randWord(),
name: args?.name ?? randWord(),
parentId: args?.parentId ?? generateTestId(),
userId: args?.userId ?? generateTestId(),
});
Expand Down
11 changes: 4 additions & 7 deletions packages/domain/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,13 @@ const config: Config.InitialOptions = {
clearMocks: true,
maxWorkers: 1,
snapshotFormat: {
"printBasicPrototype": false
printBasicPrototype: false,
},
globalSetup: './tests/setup/global-setup.ts',
setupFilesAfterEnv: ['./tests/setup/test-setup.ts'],
globalSetup: './__tests__/setup/global-setup.ts',
setupFilesAfterEnv: ['./__tests__/setup/test-setup.ts'],
coverageDirectory: 'coverage',
collectCoverage: false, // When set to true, coverage is performed even if coverage flag isn't provided
collectCoverageFrom: [
'src/**/*.ts',
'!src/index.ts',
],
collectCoverageFrom: ['src/**/*.ts', '!src/index.ts'],
coverageThreshold: {
global: {
branches: 40,
Expand Down
1 change: 1 addition & 0 deletions packages/domain/src/folders/dtos/create-folder-dto.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ export default class CreateFolderDto {
isFavorite: false,
name: this._input.name,
parentId: this._input.parentId,
path: null,
updatedAt: new Date(),
userId: this._input.userId,
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default class CreateUserRootFolderDto {
isFavorite: false,
name: `__${this._userId}__`,
parentId: null,
path: null,
updatedAt: new Date(),
userId: this._userId,
};
Expand Down
37 changes: 20 additions & 17 deletions packages/domain/src/folders/folder.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,30 @@ export default class FolderService {
});
}

async generateDirectoryPath(folderId: string): Promise<Folder[]> {
const folders: Folder[] = [];
async generateBreadcrumb(folderId: string): Promise<Folder[]> {
const folder = await this.findById(folderId);

await this.listParentFolderRecursively(folderId, folders);
const parentFolderIds = folder.path?.split('/') ?? [];

if (parentFolderIds.length === 0) {
return [];
}

const parentFoldersOrdered = await dbClient.folder.findMany({
orderBy: {
createdAt: 'asc',
},
where: {
id: {
in: parentFolderIds,
},
},
});

// Remove the user root folder
folders.pop();
parentFoldersOrdered.shift();

return folders.reverse();
return parentFoldersOrdered.concat(folder);
}

async update(updateFolderDto: UpdateFolderDto): Promise<Folder> {
Expand Down Expand Up @@ -163,18 +178,6 @@ export default class FolderService {
return [parentFolder.path, parentFolder.id].join('/');
}

private async listParentFolderRecursively(folderId: string, result: Folder[] = []): Promise<Folder[]> {
const folder = await dbClient.folder.findFirstOrThrow({ where: { id: folderId } });

result.push(folder);

if (!folder.parentId) {
return result;
}

return this.listParentFolderRecursively(folder.parentId, result);
}

private findFolderSubFolders(folderId: string, userId: string): Promise<Folder[]> {
return dbClient.folder.findMany({
where: {
Expand Down
2 changes: 1 addition & 1 deletion packages/domain/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"sourceMap": true
},
"files": ["env.d.ts"],
"include": ["src", "tests", "index.ts"],
"include": ["src", "__tests__", "index.ts"],
"exclude": [
"node_modules"
],
Expand Down
4 changes: 3 additions & 1 deletion packages/domain/tsconfig.prod.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,7 @@
"compilerOptions": {
"sourceMap": false
},
"exclude": ["tests"]
"exclude": [
"__tests__"
]
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateOembedMetadata } from '../index';
import { generateOembedMetadata } from '../../src/oembed';

describe('Test Generate Oembed metadata', () => {
it('should generate Oembed metadata for a code snippet', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { generateNoSnippetHtmlContent } from '../html-generator';
import { generateNoSnippetHtmlContent } from '../../../src/renderer/content/html-generator';

describe('Test HTML generator functions', () => {
it.only('should generates html content for a non existing code snippet', () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { Args, generateHTMLPreview } from '../preview-template';
import { Args, generateHTMLPreview } from '../../../src/renderer/content/preview-template';

jest.mock('../utils', () => {
jest.mock('../../../src/renderer/content/utils', () => {
return {
generateRandomString: () => 'random-id',
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { addWhitespaceForEmptyLine, generateLineHighlightOptions, parseHTMLSnippetCode } from '../utils';
import {
addWhitespaceForEmptyLine,
generateLineHighlightOptions,
parseHTMLSnippetCode,
} from '../../../src/renderer/content/utils';

describe('Test utils functions', () => {
describe('Test addWhitespaceForEmptyLine()', () => {
Expand Down
Loading

0 comments on commit ba33946

Please sign in to comment.