erudit 3.0.0-dev.2 → 3.0.0-dev.21
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/app/app.vue +195 -172
- package/app/assets/icons/cameo-add.svg +3 -0
- package/app/assets/icons/diamond.svg +3 -0
- package/app/assets/icons/graduation.svg +3 -0
- package/app/components/Avatar.vue +118 -0
- package/app/components/EruditLink.vue +17 -0
- package/app/components/Loading.vue +23 -23
- package/app/components/SiteAside.vue +393 -382
- package/app/components/SiteMain.vue +32 -35
- package/app/components/ads/Ads.vue +33 -0
- package/app/components/ads/AdsBannerAside.vue +61 -0
- package/app/components/ads/AdsBannerBottom.vue +22 -0
- package/app/components/ads/AdsProviderCustom.vue +35 -0
- package/app/components/ads/AdsProviderYandex.vue +91 -0
- package/app/components/ads/AdsReplacer.vue +73 -0
- package/app/components/aside/AsideListItem.vue +91 -74
- package/app/components/aside/AsideMajor.vue +56 -56
- package/app/components/aside/AsideMinor.vue +97 -71
- package/app/components/aside/major/PaneContentScroll.vue +23 -23
- package/app/components/aside/major/PaneSwitch.vue +54 -54
- package/app/components/aside/major/PaneSwitchButton.vue +63 -63
- package/app/components/aside/major/SiteInfo.vue +85 -85
- package/app/components/aside/major/panes/Language.vue +79 -79
- package/app/components/aside/major/panes/Pages.vue +50 -34
- package/app/components/aside/major/panes/Search.vue +11 -11
- package/app/components/aside/major/panes/nav/Nav.vue +92 -91
- package/app/components/aside/major/panes/nav/NavBook.vue +95 -86
- package/app/components/aside/major/panes/nav/NavBookLoading.vue +24 -24
- package/app/components/aside/major/panes/nav/NavGlobal.vue +16 -16
- package/app/components/aside/major/panes/nav/fnav/FNav.vue +105 -105
- package/app/components/aside/major/panes/nav/fnav/FNavBook.vue +32 -32
- package/app/components/aside/major/panes/nav/fnav/FNavFlags.vue +40 -40
- package/app/components/aside/major/panes/nav/fnav/FNavFolder.vue +60 -60
- package/app/components/aside/major/panes/nav/fnav/FNavItem.vue +34 -34
- package/app/components/aside/major/panes/nav/fnav/FNavSeparator.vue +80 -80
- package/app/components/aside/major/panes/nav/fnav/FNavTopic.vue +24 -24
- package/app/components/aside/major/panes/other/ItemContent.vue +29 -29
- package/app/components/aside/major/panes/other/ItemGenerator.vue +13 -15
- package/app/components/aside/major/panes/other/ItemTheme.vue +54 -54
- package/app/components/aside/major/panes/other/Other.vue +16 -16
- package/app/components/aside/minor/{Contribute.vue → AsideMinorContribute.vue} +175 -145
- package/app/components/aside/minor/AsideMinorNews.vue +11 -11
- package/app/components/aside/minor/AsideMinorPane.vue +15 -15
- package/app/components/aside/minor/AsideMinorTopLink.vue +66 -67
- package/app/components/aside/minor/content/AsideMinorContent.vue +89 -92
- package/app/components/aside/minor/contributor/AsideMinorContributor.vue +78 -0
- package/app/components/aside/minor/contributor/BookContribution.vue +64 -0
- package/app/components/aside/minor/topic/AsideMinorTopic.vue +31 -32
- package/app/components/aside/minor/topic/TopicContributors.vue +183 -177
- package/app/components/aside/minor/topic/TopicNav.vue +49 -49
- package/app/components/aside/minor/topic/TopicToc.vue +212 -203
- package/app/components/aside/minor/topic/TopicTocItem.vue +19 -31
- package/app/components/aside/utils/AsideOverlayPane.vue +40 -40
- package/app/components/bitran/BitranContent.vue +90 -63
- package/app/components/bitran/RenderWrapper.vue +10 -10
- package/app/components/contributor/ContributorListItem.vue +43 -35
- package/app/components/main/MainActionButton.vue +51 -0
- package/app/components/main/MainBitranContent.vue +55 -0
- package/app/components/main/{utils/Breadcrumb.vue → MainBreadcrumb.vue} +63 -75
- package/app/components/main/MainDescription.vue +24 -0
- package/app/components/main/MainSection.vue +58 -0
- package/app/components/main/MainTitle.vue +76 -0
- package/app/components/main/cameo/MainCameo.vue +135 -0
- package/app/components/main/cameo/MainCameoData.vue +232 -0
- package/app/components/main/content/ContentBreadcrumb.vue +28 -0
- package/app/components/main/{utils → content}/ContentDecoration.vue +29 -29
- package/app/components/main/{utils → content}/ContentPopover.vue +188 -176
- package/app/components/main/{utils → content}/ContentPopovers.vue +111 -105
- package/app/components/main/{utils → content}/ContentReferences.vue +70 -70
- package/app/components/main/{utils → content}/reference/ReferenceGroup.vue +38 -38
- package/app/components/main/{utils → content}/reference/ReferenceItem.vue +70 -68
- package/app/components/main/{utils → content}/reference/ReferenceSource.vue +120 -116
- package/app/components/main/topic/MainTopic.vue +76 -79
- package/app/components/main/topic/TopicPartSwitch.vue +119 -118
- package/app/components/preview/Preview.vue +186 -177
- package/app/components/preview/PreviewDisplay.vue +139 -139
- package/app/components/preview/PreviewFooterAction.vue +73 -73
- package/app/components/preview/PreviewLoading.vue +14 -14
- package/app/components/preview/PreviewScreen.vue +141 -99
- package/app/components/preview/display/Alert.vue +50 -50
- package/app/components/preview/display/Custom.vue +18 -18
- package/app/components/preview/display/GenericLink.vue +48 -48
- package/app/components/preview/display/PageLink.vue +22 -20
- package/app/components/preview/display/Unique.vue +46 -49
- package/app/components/sponsor/SponsorTier1.vue +89 -0
- package/app/components/sponsor/SponsorTier2.vue +109 -0
- package/app/components/transition/Fade.vue +19 -19
- package/app/components/tree/TreeContainer.vue +11 -11
- package/app/components/tree/TreeItem.vue +93 -89
- package/app/composables/adsAllowed.ts +11 -0
- package/app/composables/asset.ts +12 -0
- package/app/composables/bitran.ts +108 -127
- package/app/composables/bitranLocation.ts +7 -7
- package/app/composables/contentData.ts +38 -36
- package/app/composables/contentPage.ts +168 -156
- package/app/composables/contentRoute.ts +45 -45
- package/app/composables/darkMagic.ts +24 -24
- package/app/composables/externalApi.ts +69 -63
- package/app/composables/favicon.ts +8 -8
- package/app/composables/formatText.ts +99 -86
- package/app/composables/head.ts +24 -0
- package/app/composables/majorPane.ts +62 -60
- package/app/composables/phrases.ts +77 -80
- package/app/composables/theme.ts +29 -29
- package/app/composables/url.ts +43 -33
- package/app/pages/_test/preview.vue +110 -110
- package/app/pages/article/[...articleId].vue +3 -3
- package/app/pages/book/[...bookId].vue +42 -47
- package/app/pages/contributor/[contributorId].vue +227 -0
- package/app/pages/contributors.vue +184 -0
- package/app/pages/group/[...groupId].vue +53 -65
- package/app/pages/index.vue +32 -32
- package/app/pages/practice/[...practice].vue +3 -3
- package/app/pages/sponsors.vue +95 -0
- package/app/pages/summary/[...summaryId].vue +3 -3
- package/app/plugins/analytics.ts +95 -0
- package/app/plugins/prerender.server.ts +34 -0
- package/app/public/favicon/article.svg +5 -5
- package/app/public/favicon/default.svg +3 -3
- package/app/public/favicon/practice.svg +3 -3
- package/app/public/favicon/summary.svg +4 -4
- package/app/public/logotype.svg +2 -2
- package/app/scripts/_immediate.js +9 -9
- package/app/scripts/aside/index.ts +59 -59
- package/app/scripts/aside/major/nav.ts +26 -26
- package/app/scripts/aside/minor/state.ts +37 -37
- package/app/scripts/flag.ts +28 -28
- package/app/scripts/og.ts +28 -27
- package/app/scripts/preview/build.ts +76 -73
- package/app/scripts/preview/data/alert.ts +19 -19
- package/app/scripts/preview/data/custom.ts +8 -8
- package/app/scripts/preview/data/genericLink.ts +24 -24
- package/app/scripts/preview/data/pageLink.ts +23 -20
- package/app/scripts/preview/data/unique.ts +69 -70
- package/app/scripts/preview/data.ts +24 -24
- package/app/scripts/preview/display.ts +37 -37
- package/app/scripts/preview/footer.ts +9 -9
- package/app/scripts/preview/request.ts +51 -51
- package/app/scripts/preview/state.ts +63 -63
- package/app/styles/_immediate.css +7 -7
- package/app/styles/_util.scss +43 -43
- package/app/styles/_utils.scss +44 -44
- package/app/styles/app.scss +91 -91
- package/app/styles/def/_bp.scss +27 -27
- package/app/styles/def/_size.scss +7 -7
- package/app/styles/def/_z.scss +5 -5
- package/app/styles/normalize.scss +49 -63
- package/app/styles/partials/_darkMagic.scss +5 -5
- package/app/styles/partials/_fnav.scss +15 -15
- package/app/styles/partials/_preview.scss +5 -5
- package/bin/erudit.mjs +2 -0
- package/const.ts +3 -0
- package/globalPath.ts +21 -21
- package/globals/bitran.ts +1 -47
- package/globals/cameo.ts +5 -0
- package/globals/content.ts +27 -22
- package/globals/contributor.ts +5 -5
- package/globals/erudit.ts +5 -5
- package/globals/register.ts +23 -18
- package/globals/sponsor.ts +17 -0
- package/languages/en.ts +108 -95
- package/languages/ru.ts +112 -99
- package/module/bitran.ts +66 -34
- package/module/config.ts +35 -34
- package/module/imports.ts +74 -46
- package/module/index.ts +47 -47
- package/module/logger.ts +10 -10
- package/module/paths.ts +22 -22
- package/module/restart.ts +61 -61
- package/nuxt.config.ts +126 -112
- package/package.json +22 -15
- package/server/api/aside/major/nav/bookIds.ts +5 -5
- package/server/api/aside/major/nav/bookNav/[...bookId].ts +17 -20
- package/server/api/aside/major/nav/global.ts +7 -7
- package/server/api/aside/minor/book/[...bookId].ts +18 -0
- package/server/api/aside/minor/contributor/[contributorId].ts +18 -0
- package/server/api/aside/minor/group/[...groupId].ts +18 -0
- package/server/api/aside/minor/news.ts +7 -7
- package/server/api/aside/minor/topic.ts +36 -0
- package/server/api/bitran/content/[...location].ts +13 -0
- package/server/api/bitran/toc/[...location].ts +9 -0
- package/server/api/cameo/data/[cameoId].ts +42 -0
- package/server/api/cameo/ids.ts +5 -0
- package/server/api/content/data.ts +75 -72
- package/server/api/contributor/count.ts +6 -6
- package/server/api/contributor/list.ts +44 -0
- package/server/api/contributor/page/[contributorId].ts +14 -0
- package/server/api/fake/content.ts +11 -11
- package/server/api/fake/shared/languages.ts +12 -12
- package/server/api/language/functions.ts +12 -12
- package/server/api/language/phrase/[phraseId].ts +19 -19
- package/server/api/language/phraseIds.ts +8 -8
- package/server/api/prerender/assets/cameo.ts +14 -0
- package/server/api/prerender/assets/contributor.ts +12 -0
- package/server/api/prerender/assets/sponsor.ts +13 -0
- package/server/api/prerender/cameos.ts +12 -0
- package/server/api/prerender/language.ts +9 -0
- package/server/api/preview/page/[...parts].ts +78 -51
- package/server/api/preview/unique/{[location].ts → [...location].ts} +48 -55
- package/server/api/problem/generator/[...path].ts +26 -0
- package/server/api/sponsor/cameo/data/[sponsorId].ts +51 -0
- package/server/api/sponsor/cameo/ids.ts +5 -0
- package/server/api/sponsor/count.ts +5 -0
- package/server/api/sponsor/list.ts +36 -0
- package/server/plugin/bitran/content.ts +252 -187
- package/server/plugin/bitran/{products → elements}/include.ts +229 -230
- package/server/plugin/bitran/location.ts +43 -25
- package/server/plugin/bitran/toc.ts +94 -83
- package/server/plugin/bitran/transpiler.ts +18 -46
- package/server/plugin/build/close.ts +12 -10
- package/server/plugin/build/jobs/content/builderArgs.ts +8 -8
- package/server/plugin/build/jobs/content/generic.ts +191 -176
- package/server/plugin/build/jobs/content/parse.ts +113 -100
- package/server/plugin/build/jobs/content/path.ts +6 -6
- package/server/plugin/build/jobs/content/type/book.ts +9 -9
- package/server/plugin/build/jobs/content/type/group.ts +37 -37
- package/server/plugin/build/jobs/content/type/topic.ts +36 -36
- package/server/plugin/build/jobs/contributors.ts +69 -66
- package/server/plugin/build/jobs/language.ts +36 -36
- package/server/plugin/build/jobs/nav.ts +345 -210
- package/server/plugin/build/process.ts +34 -25
- package/server/plugin/build/rebuild.ts +68 -55
- package/server/plugin/build/setup.ts +19 -21
- package/server/plugin/content/context.ts +119 -112
- package/server/plugin/db/entities/Book.ts +7 -7
- package/server/plugin/db/entities/Content.ts +45 -49
- package/server/plugin/db/entities/Contribution.ts +10 -10
- package/server/plugin/db/entities/Contributor.ts +25 -16
- package/server/plugin/db/entities/File.ts +10 -0
- package/server/plugin/db/entities/Group.ts +14 -14
- package/server/plugin/db/entities/Hash.ts +15 -15
- package/server/plugin/db/entities/Topic.ts +20 -20
- package/server/plugin/db/entities/Unique.ts +21 -21
- package/server/plugin/db/reset.ts +12 -0
- package/server/plugin/db/setup.ts +49 -34
- package/server/plugin/global.ts +18 -18
- package/server/plugin/importer.ts +16 -12
- package/server/plugin/index.ts +9 -9
- package/server/plugin/logger.ts +23 -23
- package/server/plugin/nav/node.ts +27 -26
- package/server/plugin/nav/utils.ts +179 -129
- package/server/plugin/repository/asideMinor.ts +51 -0
- package/server/plugin/repository/book.ts +39 -21
- package/server/plugin/repository/cameo.ts +16 -0
- package/server/plugin/repository/content.ts +240 -238
- package/server/plugin/repository/contentId.ts +40 -0
- package/server/plugin/repository/contributor.ts +129 -8
- package/server/plugin/repository/file.ts +10 -0
- package/server/plugin/repository/frontNav.ts +145 -148
- package/server/plugin/repository/topic.ts +35 -32
- package/server/plugin/sponsor/build.ts +82 -0
- package/server/plugin/sponsor/index.ts +5 -0
- package/server/plugin/sponsor/repository.ts +56 -0
- package/server/routes/asset/[...assetPath].ts +34 -0
- package/server/routes/robots.txt.ts +9 -0
- package/server/routes/sitemap.xml.ts +103 -0
- package/server/tsconfig.json +9 -9
- package/shared/aside/minor.ts +55 -50
- package/shared/asset.ts +17 -15
- package/shared/bitran/content.ts +9 -0
- package/shared/bitran/contentId.ts +56 -0
- package/shared/bitran/toc.ts +8 -8
- package/shared/breadcrumb.ts +7 -0
- package/shared/content/bookId.ts +12 -0
- package/shared/content/context.ts +9 -9
- package/shared/content/data/base.ts +32 -32
- package/shared/content/data/index.ts +5 -5
- package/shared/content/data/type/book.ts +5 -5
- package/shared/content/data/type/group.ts +6 -6
- package/shared/content/data/type/topic.ts +11 -11
- package/shared/content/previousNext.ts +9 -9
- package/shared/contributor.ts +34 -5
- package/shared/frontNav.ts +41 -41
- package/shared/icons.ts +38 -38
- package/shared/image.ts +5 -5
- package/shared/link.ts +28 -25
- package/shared/popover.ts +8 -0
- package/shared/types/language.ts +84 -75
- package/shared/utils/objectsEqual.ts +4 -4
- package/shared/utils/stringColor.ts +9 -9
- package/test/contentId.test.ts +91 -0
- package/test/utils/url.test.ts +99 -0
- package/tsconfig.json +8 -8
- package/utils/contentPath.ts +67 -0
- package/utils/ext.ts +41 -0
- package/utils/stress.ts +9 -9
- package/utils/url.ts +23 -0
- package/app/components/ads/BannerTemplate.vue +0 -51
- package/app/components/ads/BottomBanner.vue +0 -45
- package/app/components/ads/LeftBanner.vue +0 -50
- package/app/components/aside/minor/AsideMinorContributor.vue +0 -5
- package/app/components/contributor/ContributorAvatar.vue +0 -43
- package/app/components/main/utils/ContentDescription.vue +0 -19
- package/app/components/main/utils/ContentFlag.vue +0 -15
- package/app/components/main/utils/ContentSection.vue +0 -45
- package/app/components/main/utils/ContentTitle.vue +0 -39
- package/app/composables/bitranContent.ts +0 -37
- package/app/pages/members.vue +0 -6
- package/app/public/user.svg +0 -10
- package/app/scripts/aside/minor/topic.ts +0 -3
- package/app/styles/default.scss +0 -83
- package/server/api/aside/minor/path.ts +0 -78
- package/server/api/bitran/content/[location].ts +0 -7
- package/server/api/bitran/toc/[location].ts +0 -7
- package/server/plugin/bitran/products/link.ts +0 -116
- package/server/plugin/bitran/setup.ts +0 -9
- package/server/plugin/content/absoluteId.ts +0 -94
- package/shared/bitran/context.ts +0 -8
- package/shared/bitran/default.ts +0 -46
- package/shared/bitran/link/Link.vue +0 -167
- package/shared/bitran/link/factory.ts +0 -24
- package/shared/bitran/link/icon.svg +0 -3
- package/shared/bitran/link/languages/en.ts +0 -7
- package/shared/bitran/link/languages/ru.ts +0 -7
- package/shared/bitran/link/renderer.ts +0 -21
- package/shared/bitran/link/shared.ts +0 -17
- package/shared/bitran/link/target.ts +0 -134
- package/shared/bitran/link/transpiler.ts +0 -10
- package/shared/bitran/location.ts +0 -166
- package/test/bitran/link/target.test.ts +0 -141
- package/test/bitran/location.test.ts +0 -143
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
2
|
+
import { DbFile } from '@server/db/entities/File';
|
|
3
|
+
|
|
4
|
+
export async function getFileFullPath(path: string) {
|
|
5
|
+
const dbFile = await ERUDIT_SERVER.DB.manager.findOne(DbFile, {
|
|
6
|
+
where: { path },
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
return dbFile?.fullPath;
|
|
10
|
+
}
|
|
@@ -1,148 +1,145 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
FrontNav,
|
|
3
|
-
FrontNavBase,
|
|
4
|
-
FrontNavBook,
|
|
5
|
-
FrontNavFolder,
|
|
6
|
-
FrontNavItem,
|
|
7
|
-
FrontNavSeparator,
|
|
8
|
-
FrontNavTopic,
|
|
9
|
-
} from '@erudit/shared/frontNav';
|
|
10
|
-
|
|
11
|
-
import type { NavNode, RootNavNode } from '@server/nav/node';
|
|
12
|
-
import { ERUDIT_SERVER } from '@server/global';
|
|
13
|
-
import { DbContent } from '@server/db/entities/Content';
|
|
14
|
-
import { DbGroup } from '@server/db/entities/Group';
|
|
15
|
-
|
|
16
|
-
import { getTopicPart } from './topic';
|
|
17
|
-
|
|
18
|
-
export async function createGlobalFrontNav(
|
|
19
|
-
from: RootNavNode | NavNode | undefined,
|
|
20
|
-
): Promise<FrontNav | []> {
|
|
21
|
-
if (!from || !from.children) return [];
|
|
22
|
-
|
|
23
|
-
return await Promise.all(
|
|
24
|
-
from.children.map((node) =>
|
|
25
|
-
toFrontNavItem({ node, level: 0, includeBookNav: true }),
|
|
26
|
-
),
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export async function createBookFrontNav(from: NavNode): Promise<FrontNavBook> {
|
|
31
|
-
return await toFrontNavBook({ node: from, level: 0, includeBookNav: true });
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
type ToFuncArg = {
|
|
35
|
-
node: NavNode;
|
|
36
|
-
level: number;
|
|
37
|
-
includeBookNav?: boolean;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
async function toFrontNavItem(arg: ToFuncArg): Promise<FrontNavItem> {
|
|
41
|
-
switch (arg.node.type) {
|
|
42
|
-
case 'book':
|
|
43
|
-
return await toFrontNavBook(arg);
|
|
44
|
-
case 'topic':
|
|
45
|
-
return await toFrontNavTopic(arg);
|
|
46
|
-
case 'group':
|
|
47
|
-
const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
|
|
48
|
-
select: ['type'],
|
|
49
|
-
where: { contentId: arg.node.
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
if (!dbGroup)
|
|
53
|
-
throw new Error(
|
|
54
|
-
`Missing group content item "${arg.node.
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
if (dbGroup.type === 'folder') return await toFrontNavFolder(arg);
|
|
58
|
-
else return await toFrontNavSeparator(arg);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async function toFrontNavBook({
|
|
63
|
-
node,
|
|
64
|
-
level,
|
|
65
|
-
includeBookNav,
|
|
66
|
-
}: ToFuncArg): Promise<FrontNavBook> {
|
|
67
|
-
return {
|
|
68
|
-
type: 'book',
|
|
69
|
-
children: await toFrontNavChildren({
|
|
70
|
-
node,
|
|
71
|
-
level: 0,
|
|
72
|
-
includeBookNav,
|
|
73
|
-
}),
|
|
74
|
-
...(await toFrontNavBase({ node, level })),
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
async function toFrontNavSeparator({
|
|
79
|
-
node,
|
|
80
|
-
level,
|
|
81
|
-
includeBookNav,
|
|
82
|
-
}: ToFuncArg): Promise<FrontNavSeparator> {
|
|
83
|
-
return {
|
|
84
|
-
type: 'separator',
|
|
85
|
-
children: await toFrontNavChildren({ node, level, includeBookNav }),
|
|
86
|
-
...(await toFrontNavBase({ node, level })),
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async function toFrontNavFolder({
|
|
91
|
-
node,
|
|
92
|
-
level,
|
|
93
|
-
includeBookNav,
|
|
94
|
-
}: ToFuncArg): Promise<FrontNavFolder> {
|
|
95
|
-
return {
|
|
96
|
-
type: 'folder',
|
|
97
|
-
children: await toFrontNavChildren({
|
|
98
|
-
node,
|
|
99
|
-
level: level + 1,
|
|
100
|
-
includeBookNav,
|
|
101
|
-
}),
|
|
102
|
-
...(await toFrontNavBase({ node, level })),
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
async function toFrontNavTopic({
|
|
107
|
-
node,
|
|
108
|
-
level,
|
|
109
|
-
}: ToFuncArg): Promise<FrontNavTopic> {
|
|
110
|
-
const topicPart = await getTopicPart(node.
|
|
111
|
-
return {
|
|
112
|
-
type: 'topic',
|
|
113
|
-
part: topicPart,
|
|
114
|
-
...(await toFrontNavBase({ node, level })),
|
|
115
|
-
};
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function toFrontNavBase({
|
|
119
|
-
node,
|
|
120
|
-
level,
|
|
121
|
-
}: ToFuncArg): Promise<Omit<FrontNavBase, 'type'>> {
|
|
122
|
-
const dbContent = await ERUDIT_SERVER.DB.manager.findOne(DbContent, {
|
|
123
|
-
select: ['title', 'navTitle', 'flags'],
|
|
124
|
-
where: { contentId: node.
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
return {
|
|
128
|
-
id: node.
|
|
129
|
-
fullId: node.fullId,
|
|
130
|
-
level,
|
|
131
|
-
flags: dbContent?.flags,
|
|
132
|
-
label:
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
),
|
|
147
|
-
);
|
|
148
|
-
}
|
|
1
|
+
import type {
|
|
2
|
+
FrontNav,
|
|
3
|
+
FrontNavBase,
|
|
4
|
+
FrontNavBook,
|
|
5
|
+
FrontNavFolder,
|
|
6
|
+
FrontNavItem,
|
|
7
|
+
FrontNavSeparator,
|
|
8
|
+
FrontNavTopic,
|
|
9
|
+
} from '@erudit/shared/frontNav';
|
|
10
|
+
|
|
11
|
+
import type { NavNode, RootNavNode } from '@server/nav/node';
|
|
12
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
13
|
+
import { DbContent } from '@server/db/entities/Content';
|
|
14
|
+
import { DbGroup } from '@server/db/entities/Group';
|
|
15
|
+
|
|
16
|
+
import { getTopicPart } from './topic';
|
|
17
|
+
|
|
18
|
+
export async function createGlobalFrontNav(
|
|
19
|
+
from: RootNavNode | NavNode | undefined,
|
|
20
|
+
): Promise<FrontNav | []> {
|
|
21
|
+
if (!from || !from.children) return [];
|
|
22
|
+
|
|
23
|
+
return await Promise.all(
|
|
24
|
+
from.children.map((node) =>
|
|
25
|
+
toFrontNavItem({ node, level: 0, includeBookNav: true }),
|
|
26
|
+
),
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function createBookFrontNav(from: NavNode): Promise<FrontNavBook> {
|
|
31
|
+
return await toFrontNavBook({ node: from, level: 0, includeBookNav: true });
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type ToFuncArg = {
|
|
35
|
+
node: NavNode;
|
|
36
|
+
level: number;
|
|
37
|
+
includeBookNav?: boolean;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
async function toFrontNavItem(arg: ToFuncArg): Promise<FrontNavItem> {
|
|
41
|
+
switch (arg.node.type) {
|
|
42
|
+
case 'book':
|
|
43
|
+
return await toFrontNavBook(arg);
|
|
44
|
+
case 'topic':
|
|
45
|
+
return await toFrontNavTopic(arg);
|
|
46
|
+
case 'group':
|
|
47
|
+
const dbGroup = await ERUDIT_SERVER.DB.manager.findOne(DbGroup, {
|
|
48
|
+
select: ['type'],
|
|
49
|
+
where: { contentId: arg.node.fullId },
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
if (!dbGroup)
|
|
53
|
+
throw new Error(
|
|
54
|
+
`Missing group content item "${arg.node.fullId}" when creating front nav!`,
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (dbGroup.type === 'folder') return await toFrontNavFolder(arg);
|
|
58
|
+
else return await toFrontNavSeparator(arg);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async function toFrontNavBook({
|
|
63
|
+
node,
|
|
64
|
+
level,
|
|
65
|
+
includeBookNav,
|
|
66
|
+
}: ToFuncArg): Promise<FrontNavBook> {
|
|
67
|
+
return {
|
|
68
|
+
type: 'book',
|
|
69
|
+
children: await toFrontNavChildren({
|
|
70
|
+
node,
|
|
71
|
+
level: 0,
|
|
72
|
+
includeBookNav,
|
|
73
|
+
}),
|
|
74
|
+
...(await toFrontNavBase({ node, level })),
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function toFrontNavSeparator({
|
|
79
|
+
node,
|
|
80
|
+
level,
|
|
81
|
+
includeBookNav,
|
|
82
|
+
}: ToFuncArg): Promise<FrontNavSeparator> {
|
|
83
|
+
return {
|
|
84
|
+
type: 'separator',
|
|
85
|
+
children: await toFrontNavChildren({ node, level, includeBookNav }),
|
|
86
|
+
...(await toFrontNavBase({ node, level })),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async function toFrontNavFolder({
|
|
91
|
+
node,
|
|
92
|
+
level,
|
|
93
|
+
includeBookNav,
|
|
94
|
+
}: ToFuncArg): Promise<FrontNavFolder> {
|
|
95
|
+
return {
|
|
96
|
+
type: 'folder',
|
|
97
|
+
children: await toFrontNavChildren({
|
|
98
|
+
node,
|
|
99
|
+
level: level + 1,
|
|
100
|
+
includeBookNav,
|
|
101
|
+
}),
|
|
102
|
+
...(await toFrontNavBase({ node, level })),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
async function toFrontNavTopic({
|
|
107
|
+
node,
|
|
108
|
+
level,
|
|
109
|
+
}: ToFuncArg): Promise<FrontNavTopic> {
|
|
110
|
+
const topicPart = await getTopicPart(node.fullId);
|
|
111
|
+
return {
|
|
112
|
+
type: 'topic',
|
|
113
|
+
part: topicPart,
|
|
114
|
+
...(await toFrontNavBase({ node, level })),
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function toFrontNavBase({
|
|
119
|
+
node,
|
|
120
|
+
level,
|
|
121
|
+
}: ToFuncArg): Promise<Omit<FrontNavBase, 'type'>> {
|
|
122
|
+
const dbContent = await ERUDIT_SERVER.DB.manager.findOne(DbContent, {
|
|
123
|
+
select: ['title', 'navTitle', 'flags'],
|
|
124
|
+
where: { contentId: node.fullId },
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
return {
|
|
128
|
+
id: node.shortId,
|
|
129
|
+
fullId: node.fullId,
|
|
130
|
+
level,
|
|
131
|
+
flags: dbContent?.flags,
|
|
132
|
+
label: dbContent?.navTitle || dbContent?.title || node.idPart,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async function toFrontNavChildren({ node, includeBookNav, level }: ToFuncArg) {
|
|
137
|
+
if (node.type === 'book' && !includeBookNav) return undefined;
|
|
138
|
+
if (!node.children) return undefined;
|
|
139
|
+
|
|
140
|
+
return Promise.all(
|
|
141
|
+
node.children!.map((child) =>
|
|
142
|
+
toFrontNavItem({ node: child, level, includeBookNav }),
|
|
143
|
+
),
|
|
144
|
+
);
|
|
145
|
+
}
|
|
@@ -1,32 +1,35 @@
|
|
|
1
|
-
import type { TopicPart } from 'erudit-cog/schema';
|
|
2
|
-
|
|
3
|
-
import { ERUDIT_SERVER } from '@server/global';
|
|
4
|
-
import { DbTopic } from '@server/db/entities/Topic';
|
|
5
|
-
import
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
import type { TopicPart } from '@erudit-js/cog/schema';
|
|
2
|
+
|
|
3
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
4
|
+
import { DbTopic } from '@server/db/entities/Topic';
|
|
5
|
+
import { getShortContentId } from '@server/repository/contentId';
|
|
6
|
+
|
|
7
|
+
import type { TopicPartLinks } from '@shared/content/data/type/topic';
|
|
8
|
+
import { createTopicPartLink } from '@shared/link';
|
|
9
|
+
|
|
10
|
+
export async function getTopicParts(contentId: string) {
|
|
11
|
+
const dbTopic = await ERUDIT_SERVER.DB.manager.findOne(DbTopic, {
|
|
12
|
+
select: ['parts'],
|
|
13
|
+
where: { contentId },
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
if (!dbTopic) throw new Error(`Missing topic "${contentId}".`);
|
|
17
|
+
|
|
18
|
+
return dbTopic.parts;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export async function getTopicPart(contentId: string): Promise<TopicPart> {
|
|
22
|
+
const topicParts = await getTopicParts(contentId);
|
|
23
|
+
return topicParts.shift()!;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export async function getTopicPartsLinks(topicId: string) {
|
|
27
|
+
const existingTopicParts = await getTopicParts(topicId);
|
|
28
|
+
const shortTopicId = await getShortContentId(topicId);
|
|
29
|
+
const links: TopicPartLinks = {};
|
|
30
|
+
|
|
31
|
+
for (const topicPart of existingTopicParts)
|
|
32
|
+
links[topicPart] = createTopicPartLink(topicPart, shortTopicId);
|
|
33
|
+
|
|
34
|
+
return links;
|
|
35
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { glob } from 'glob';
|
|
3
|
+
import type { Sponsor, SponsorConfig } from '@erudit-js/cog/schema';
|
|
4
|
+
|
|
5
|
+
import { PROJECT_DIR } from '#erudit/globalPaths';
|
|
6
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
7
|
+
import { debug, logger } from '@server/logger';
|
|
8
|
+
|
|
9
|
+
import { getSponsorCount, readSponsorConfig } from './repository';
|
|
10
|
+
|
|
11
|
+
export async function buildSponsors() {
|
|
12
|
+
if (!ERUDIT_SERVER.CONFIG.sponsors) {
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
debug.start('Building sponsors...');
|
|
17
|
+
|
|
18
|
+
const sponsorIds = await searchSponsorIds();
|
|
19
|
+
|
|
20
|
+
if (sponsorIds.length === 0) {
|
|
21
|
+
logger.warn('No sponsors found!');
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
ERUDIT_SERVER.SPONSORS = {
|
|
26
|
+
tier1Ids: [],
|
|
27
|
+
tier2Ids: [],
|
|
28
|
+
avatars: {},
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
for (const sponsorId of sponsorIds) {
|
|
32
|
+
const sponsorAvatar = await searchSponsorAvatar(sponsorId);
|
|
33
|
+
|
|
34
|
+
let config: SponsorConfig<Sponsor>;
|
|
35
|
+
try {
|
|
36
|
+
config = await readSponsorConfig(sponsorId);
|
|
37
|
+
} catch (error) {
|
|
38
|
+
logger.error(
|
|
39
|
+
`Failed to read sponsor config for: ${sponsorId}! ${error}`,
|
|
40
|
+
);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (config.tier === 'tier1') {
|
|
45
|
+
ERUDIT_SERVER.SPONSORS.tier1Ids.push(sponsorId);
|
|
46
|
+
} else if (config.tier === 'tier2') {
|
|
47
|
+
ERUDIT_SERVER.SPONSORS.tier2Ids.push(sponsorId);
|
|
48
|
+
} else {
|
|
49
|
+
logger.warn(
|
|
50
|
+
`Sponsor ${sponsorId} has an unknown tier: ${config.tier}!`,
|
|
51
|
+
);
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
ERUDIT_SERVER.SPONSORS.avatars[sponsorId] = sponsorAvatar;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
logger.success(
|
|
59
|
+
`Sponsors built successfully!`,
|
|
60
|
+
chalk.dim(`(${getSponsorCount()})`),
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async function searchSponsorIds() {
|
|
65
|
+
const dirs = await glob(PROJECT_DIR + '/sponsors/*/sponsor.{ts,js}', {
|
|
66
|
+
posix: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return dirs.map((dir) => dir.split('/').slice(-2, -1)[0]!);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export async function searchSponsorAvatar(
|
|
73
|
+
sponsorId: string,
|
|
74
|
+
): Promise<string | undefined> {
|
|
75
|
+
const pattern = `sponsors/${sponsorId}/avatar.*`;
|
|
76
|
+
const avatars = await glob(pattern, {
|
|
77
|
+
cwd: PROJECT_DIR,
|
|
78
|
+
posix: true,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
return avatars.pop();
|
|
82
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { SponsorConfig, Sponsor } from '@erudit-js/cog/schema';
|
|
2
|
+
|
|
3
|
+
import { PROJECT_DIR } from '#erudit/globalPaths';
|
|
4
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
5
|
+
import { IMPORT } from '@server/importer';
|
|
6
|
+
|
|
7
|
+
export function getSponsorIds() {
|
|
8
|
+
const sponsors = ERUDIT_SERVER?.SPONSORS;
|
|
9
|
+
|
|
10
|
+
if (!sponsors) {
|
|
11
|
+
return [];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const tier1Ids = sponsors.tier1Ids || [];
|
|
15
|
+
const tier2Ids = sponsors.tier2Ids || [];
|
|
16
|
+
|
|
17
|
+
return [...tier1Ids, ...tier2Ids];
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function getSponsorCount() {
|
|
21
|
+
return getSponsorIds().length;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function readSponsorConfig(sponsorId: string) {
|
|
25
|
+
const config = (await IMPORT(
|
|
26
|
+
`${PROJECT_DIR}/sponsors/${sponsorId}/sponsor`,
|
|
27
|
+
{ default: true },
|
|
28
|
+
)) as SponsorConfig<Sponsor>;
|
|
29
|
+
|
|
30
|
+
return config;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export async function retrieveSponsor(sponsorId: string): Promise<Sponsor> {
|
|
34
|
+
const config = await readSponsorConfig(sponsorId);
|
|
35
|
+
const avatar = ERUDIT_SERVER.SPONSORS?.avatars[sponsorId];
|
|
36
|
+
|
|
37
|
+
if (!config) {
|
|
38
|
+
throw new Error(`Sponsor config not found for ID: ${sponsorId}`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
...config,
|
|
43
|
+
sponsorId,
|
|
44
|
+
avatar,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export function getTier2SponsorIds() {
|
|
49
|
+
const sponsors = ERUDIT_SERVER?.SPONSORS;
|
|
50
|
+
|
|
51
|
+
if (!sponsors) {
|
|
52
|
+
return [];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return sponsors.tier2Ids || [];
|
|
56
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
|
|
4
|
+
import { PROJECT_DIR } from '#erudit/globalPaths';
|
|
5
|
+
|
|
6
|
+
export default defineEventHandler(async (event) => {
|
|
7
|
+
setHeader(event, 'Content-Type', 'application/octet-stream');
|
|
8
|
+
const assetPath = event.context.params?.assetPath?.trim();
|
|
9
|
+
|
|
10
|
+
if (typeof assetPath !== 'string' || !assetPath) {
|
|
11
|
+
throw createError({
|
|
12
|
+
statusCode: 400,
|
|
13
|
+
message: 'Invalid asset path!',
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const fsPath = PROJECT_DIR + '/' + assetPath;
|
|
18
|
+
|
|
19
|
+
if (!existsSync(fsPath)) {
|
|
20
|
+
throw createError({
|
|
21
|
+
statusCode: 404,
|
|
22
|
+
message: `Asset not found: ${assetPath}`,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const fileContent = await readFile(fsPath).catch((err) => {
|
|
27
|
+
throw createError({
|
|
28
|
+
statusCode: 500,
|
|
29
|
+
message: `Failed to read asset "${assetPath}"! Error: ${err.message}`,
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
return fileContent;
|
|
34
|
+
});
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Not } from 'typeorm';
|
|
2
|
+
import type { ContentType } from '@erudit-js/cog/schema';
|
|
3
|
+
|
|
4
|
+
import { ERUDIT_SERVER } from '@server/global';
|
|
5
|
+
import { DbTopic } from '@server/db/entities/Topic';
|
|
6
|
+
import { getShortContentId } from '@server/repository/contentId';
|
|
7
|
+
import { DbContent } from '@server/db/entities/Content';
|
|
8
|
+
import { DbContributor } from '@server/db/entities/Contributor';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
createContentLink,
|
|
12
|
+
createContributorLink,
|
|
13
|
+
createTopicPartLink,
|
|
14
|
+
} from '@shared/link';
|
|
15
|
+
import { trailingSlash } from '@erudit/utils/url';
|
|
16
|
+
|
|
17
|
+
export default defineEventHandler(async (event) => {
|
|
18
|
+
setHeader(event, 'Content-Type', 'application/xml');
|
|
19
|
+
|
|
20
|
+
const routes = [
|
|
21
|
+
...staticRoutes(),
|
|
22
|
+
...(await topicRoutes()),
|
|
23
|
+
...(await contentRoutes()),
|
|
24
|
+
...(await contributorsRoutes()),
|
|
25
|
+
];
|
|
26
|
+
|
|
27
|
+
const buildUrl = ERUDIT_SERVER.CONFIG.site?.buildUrl || '';
|
|
28
|
+
const baseUrl = ERUDIT_SERVER.CONFIG.site?.baseUrl || '/';
|
|
29
|
+
|
|
30
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
31
|
+
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
|
32
|
+
${routes
|
|
33
|
+
.map(
|
|
34
|
+
(route) =>
|
|
35
|
+
` <url>
|
|
36
|
+
<loc>${trailingSlash(buildUrl + baseUrl, false) + route}</loc>
|
|
37
|
+
<lastmod>${new Date().toISOString().slice(0, 10)}</lastmod>
|
|
38
|
+
</url>`,
|
|
39
|
+
)
|
|
40
|
+
.join('\n')}
|
|
41
|
+
</urlset>`;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
function staticRoutes() {
|
|
45
|
+
const routes = ['/', '/contributors/'];
|
|
46
|
+
|
|
47
|
+
if (ERUDIT_SERVER.CONFIG.sponsors) {
|
|
48
|
+
routes.push('/sponsors/');
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return routes;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
async function topicRoutes() {
|
|
55
|
+
const dbTopics = await ERUDIT_SERVER.DB.manager.find(DbTopic, {
|
|
56
|
+
select: ['contentId', 'parts'],
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const topicRoutes: string[] = [];
|
|
60
|
+
|
|
61
|
+
for (const dbTopic of dbTopics) {
|
|
62
|
+
const shortId = getShortContentId(dbTopic.contentId);
|
|
63
|
+
for (const part of dbTopic.parts) {
|
|
64
|
+
topicRoutes.push(createTopicPartLink(part, shortId));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return topicRoutes;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async function contentRoutes() {
|
|
72
|
+
const dbContentItems = await ERUDIT_SERVER.DB.manager.find(DbContent, {
|
|
73
|
+
select: ['contentId', 'type'],
|
|
74
|
+
where: {
|
|
75
|
+
type: Not('topic' as ContentType),
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const contentRoutes: string[] = [];
|
|
80
|
+
|
|
81
|
+
for (const dbContent of dbContentItems) {
|
|
82
|
+
const shortId = getShortContentId(dbContent.contentId);
|
|
83
|
+
contentRoutes.push(createContentLink(dbContent.type, shortId));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return contentRoutes;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
async function contributorsRoutes() {
|
|
90
|
+
const dbContributors = await ERUDIT_SERVER.DB.manager.find(DbContributor, {
|
|
91
|
+
select: ['contributorId'],
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const contributorRoutes: string[] = [];
|
|
95
|
+
|
|
96
|
+
for (const dbContributor of dbContributors) {
|
|
97
|
+
contributorRoutes.push(
|
|
98
|
+
createContributorLink(dbContributor.contributorId),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
return contributorRoutes;
|
|
103
|
+
}
|