Skip to content

Commit

Permalink
feat: refactored author feat (#144)
Browse files Browse the repository at this point in the history
  • Loading branch information
gustaveWPM authored May 19, 2024
1 parent bc93367 commit 44bcd00
Show file tree
Hide file tree
Showing 17 changed files with 217 additions and 175 deletions.
1 change: 1 addition & 0 deletions .ts-prune/artifacts/tsprune-false-positives.conf
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ interop/config/i18n.ts:29 - LanguageFlag (used in module)
interop/lib/builders/index.ts:30 - buildBlogAuthors (used in module)
interop/lib/builders/unifiedImport.ts:46 - authorNames (used in module)
interop/lib/builders/index.ts:22 - buildBlogPostHeadings (used in module)
interop/lib/builders/index.ts:23 - buildBlogAuthorsIndexes (used in module)
interop/lib/builders/index.ts:24 - buildBlogTagsIndexes (used in module)
interop/lib/builders/index.ts:27 - buildPageRoot (used in module)
interop/lib/builders/index.ts:26 - buildPageUrl (used in module)
Expand Down
29 changes: 19 additions & 10 deletions interop/config/contentlayer/blog/authors.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,35 @@
/* v8 ignore start */
// Stryker disable all

import type { NestedTypeNoiseKeys } from '##/lib/misc/contentlayerCornerCases';
import type { Author as NestedTypeAuthor } from 'contentlayer/generated';

const authors = {
Gustave: {
profilePicUrl: '/assets/medias/img/dev/placeholders/placeholder-54.jpeg',
bio: 'Je suis très chouette'
profilePicUrl: '/assets/medias/img/dev/placeholders/placeholder-54.jpeg'
},
Arnaud: {
profilePicUrl: '/assets/medias/img/dev/placeholders/placeholder-55.jpeg'
}
} as const satisfies Authors;
} as const satisfies Record<string, Author>;

export const authorNames = Object.keys(authors) as readonly (keyof typeof authors)[];
export const authorNames = Object.keys(authors) as readonly AuthorName[];

export default authors;

export type Author = Omit<NestedTypeAuthor, NestedTypeNoiseKeys>;
export type AuthorName = string;
export type Authors = Record<AuthorName, Author>;
export type Author = {
medias?: {
instagram?: undefined | string;
goodreads?: undefined | string;
linkedin?: undefined | string;
twitter?: undefined | string;
keybase?: undefined | string;
reddit?: undefined | string;
medium?: undefined | string;
github?: undefined | string;
};
profilePicUrl: string;
};

export type AuthorName = keyof Authors;
export type Authors = typeof authors;

// Stryker restore all
/* v8 ignore stop */
12 changes: 12 additions & 0 deletions interop/config/contentlayer/blog/authorsMetadatas.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/* v8 ignore start */
// Stryker disable all

import { generateBlogAuthorOptionsVocabSchema, generateIndexedAuthorNames } from '../../../lib/builders/blogAuthorsGenerators';
import { authorNames } from './authors';

export const indexedBlogAuthorNames = generateIndexedAuthorNames(authorNames);

export const blogAuthorOptionsVocabSchema = generateBlogAuthorOptionsVocabSchema(authorNames);

// Stryker restore all
/* v8 ignore stop */
6 changes: 6 additions & 0 deletions interop/config/contentlayer/blog/blogTagsMetadatas.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
/* v8 ignore start */
// Stryker disable all

import { generateBlogTagOptionsVocabSchema, generateIndexedBlogTagOptions } from '../../../lib/builders/blogTagsGenerators';
import { blogTagOptions } from './blogTags';

export const indexedBlogTagOptions = generateIndexedBlogTagOptions(blogTagOptions);

export const blogTagOptionsVocabSchema = generateBlogTagOptionsVocabSchema(blogTagOptions);

// Stryker restore all
/* v8 ignore stop */
29 changes: 17 additions & 12 deletions interop/config/contentlayer/contentlayerConfigTweakers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,24 +12,24 @@ import {
buildBlogPostLanguageFlag,
buildBlogPostSubcategory,
buildLandingPageCategory,
buildBlogAuthorsIndexes,
buildBlogPostHeadings,
buildBlogPostCategory,
buildPageLanguageFlag,
buildLandingPageSlug,
buildBlogTagsIndexes,
buildLandingPageUrl,
buildBlogPostSlug,
buildBlogAuthors,
buildBlogPostUrl,
buildPageRoot,
buildPagePath,
buildPageUrl
} from '../../lib/builders';
import { indexedBlogTagOptions } from './blog/blogTagsMetadatas';
import { indexedBlogAuthorNames } from './blog/authorsMetadatas';
import DocumentHeading from './nested-types/DocumentHeading';
import authors, { authorNames } from './blog/authors';
import { blogTagOptions } from './blog/blogTags';
import Author from './nested-types/Author';
import { authorNames } from './blog/authors';
import SEO from './nested-types/SEO';

export const PAGES_FOLDER = 'pages';
Expand Down Expand Up @@ -57,6 +57,15 @@ const _ALL_BLOG_FIELDS = {
type: 'enum'
},
required: false,
type: 'list',
default: []
},

authorsIndexes: {
of: {
type: 'number'
},
required: true,
type: 'list'
},

Expand All @@ -70,12 +79,6 @@ const _ALL_BLOG_FIELDS = {

headings: { of: DocumentHeading, required: false, type: 'list', default: [] },

authorsMetadatas: {
required: true,
type: 'list',
of: Author
},

draft: {
type: 'boolean',
required: false,
Expand Down Expand Up @@ -225,8 +228,11 @@ const _ALL_PAGES_FIELDS = {
// Stryker disable all

export const BLOG_DOCUMENTS_COMPUTED_FIELDS = {
authorsIndexes: {
resolve: (post) => buildBlogAuthorsIndexes(post, indexedBlogAuthorNames, authorNames),
type: _ALL_BLOG_FIELDS.authorsIndexes.type
},
tagsIndexes: { resolve: (post) => buildBlogTagsIndexes(post, indexedBlogTagOptions, blogTagOptions), type: _ALL_BLOG_FIELDS.tagsIndexes.type },
authorsMetadatas: { resolve: (post) => buildBlogAuthors(post, authors), type: _ALL_BLOG_FIELDS.authorsMetadatas.type },
subcategory: { resolve: (post) => buildBlogPostSubcategory(post), type: _ALL_BLOG_FIELDS.subcategory.type },
language: { resolve: (post) => buildBlogPostLanguageFlag(post), type: _ALL_BLOG_FIELDS.language.type },
category: { resolve: (post) => buildBlogPostCategory(post), type: _ALL_BLOG_FIELDS.category.type },
Expand Down Expand Up @@ -313,5 +319,4 @@ type _BlogDocumentsComputedFieldsKeys = MakeDocumentsAllFieldsSumType<keyof _Blo
type _PagesDocumentsComputedFieldsKeys = MakeDocumentsAllFieldsSumType<keyof _PagesComputedFields, _AllPagesFields>;
type _LandingPagesDocumentsComputedFieldsKeys = MakeDocumentsAllFieldsSumType<keyof _LandingPagesComputedFields, _AllLandingPagesFields>;

// export const badlyTypedBlogHeadings = 'headings' as const satisfies keyof typeof _ALL_BLOG_FIELDS;
// export const badlyTypedTagsIndexes = 'tagsIndexes' as const satisfies keyof typeof _ALL_BLOG_FIELDS;
export const DAMERAU_LEVENSHTEIN_THRESHOLD = 4;
36 changes: 0 additions & 36 deletions interop/config/contentlayer/nested-types/Author.ts

This file was deleted.

1 change: 1 addition & 0 deletions interop/config/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const _i18nsBase = {
blogTagsFilters: 'blog-tags-filters',
metadescriptions: 'metadescriptions',
blogCategories: 'blog-categories',
blogAuthors: 'blog-authors',
pagesTitles: 'pages-titles',
searchMenu: 'search-menu',
dashboard: 'dashboard',
Expand Down
5 changes: 2 additions & 3 deletions interop/errors/InvalidBlogAuthor.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import type { AuthorName } from '##/config/contentlayer/blog/authors';

import { TAB_SIZE } from '../lib/misc/contentlayerCornerCases';

type InvalidAuthor = string;
type ValidAuthor = string;

class InvalidBlogAuthor extends Error {
constructor(invalidBlogAuthors: InvalidAuthor[], validAuthorsNames: readonly AuthorName[]) {
constructor(invalidBlogAuthors: InvalidAuthor[], validAuthorsNames: readonly ValidAuthor[]) {
const invalidAuthorPart =
// eslint-disable-next-line no-magic-numbers
invalidBlogAuthors.length > 1
Expand Down
80 changes: 0 additions & 80 deletions interop/lib/builders/blog/computedFields/functions/authors.ts

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import type { DocumentToCompute } from '@rtm/shared-types/ContentlayerConfig';
import type { MaybeNull } from '@rtm/shared-types/CustomUtilityTypes';
import type { Index } from 'packages/shared-types/src/Numbers';

import { BlogAuthorDuplicates, InvalidBlogAuthor, BULLET } from '../../../unifiedImport';

function validateAuthorNames<AuthorName extends string>(
tagsArrayUniq: AuthorName[],
indexedBlogTagOptions: Record<AuthorName, Index>,
blogTagOptions: readonly AuthorName[]
): MaybeNull<InvalidBlogAuthor> {
const defects: string[] = [];

for (const tag of tagsArrayUniq) {
if (indexedBlogTagOptions[tag] === undefined) {
defects.push(tag);
continue;
}
}

// eslint-disable-next-line no-magic-numbers
if (defects.length > 0) return new InvalidBlogAuthor(defects, blogTagOptions);
return null;
}

function validateAuthorsNoDuplicates(authorsNamesArray: string[]): MaybeNull<BlogAuthorDuplicates> {
const authorsMemory: unknown[] = [];
const duplicatesSet = new Set<unknown>();

for (const currentName of authorsNamesArray) {
if (authorsMemory.includes(currentName)) {
duplicatesSet.add(currentName);
continue;
}
authorsMemory.push(currentName);
}

const duplicates = Array.from(duplicatesSet);
// eslint-disable-next-line no-magic-numbers
if (duplicates.length > 0) return new BlogAuthorDuplicates(duplicates);
return null;
}

/**
* @throws {[InvalidBlogAuthor, BlogAuthorDuplicates]}
*/
function buildBlogAuthorsFromPostObj<AuthorName extends string>(
authorsNamesArray: AuthorName[],
indexedAuthorsNames: Record<AuthorName, Index>,
authorsNames: readonly AuthorName[]
): Index[] {
const authorsNamesArrayUniq = Array.from(new Set<AuthorName>(authorsNamesArray));

const maybeValidateAuthorNamesError = validateAuthorNames(authorsNamesArrayUniq, indexedAuthorsNames, authorsNames);
const maybeValidateAuthorsNoDuplicatesError = validateAuthorsNoDuplicates(authorsNamesArray as string[]);

const mergedErrors = [maybeValidateAuthorNamesError, maybeValidateAuthorsNoDuplicatesError].filter((e) => e !== null);

// eslint-disable-next-line no-magic-numbers
if (mergedErrors.length > 0) throw mergedErrors.join('\n' + BULLET + ' ');

const res: Index[] = [];
for (const authorName of authorsNamesArrayUniq) res.push(indexedAuthorsNames[authorName]);

return res;
}

const buildBlogAuthorsIndexes = <AuthorName extends string>(
post: DocumentToCompute,
indexedAuthorsNames: Record<AuthorName, Index>,
authorsNames: readonly AuthorName[]
): Index[] => buildBlogAuthorsFromPostObj(post.authors._array as AuthorName[], indexedAuthorsNames, authorsNames);

export default buildBlogAuthorsIndexes;
Loading

0 comments on commit 44bcd00

Please sign in to comment.