From d7f4975330eb5cbd5c09bc812db957689e245ce5 Mon Sep 17 00:00:00 2001 From: Sami Mazouz Date: Tue, 17 Jan 2023 19:10:24 +0100 Subject: [PATCH] feat: introduce frontend extenders (#3645) * feat: reintroduce frontend extenders * chore: used `Routes` extender in bundled extensions * chore: used `PostTypes` extender in bundled extensions * chore: `yarn format` * chore: naming * chore(review): unnecessary check * chore(review): stay consistent * chore: unused import Signed-off-by: Sami Mazouz --- extensions/flags/js/src/forum/extend.ts | 4 ++ extensions/flags/js/src/forum/index.ts | 4 +- .../js/src/forum/addLikesTabToUserProfile.tsx | 4 +- extensions/likes/js/src/forum/extend.ts | 4 ++ extensions/likes/js/src/forum/index.js | 2 + extensions/likes/js/tsconfig.json | 20 +++++++++ extensions/lock/js/src/forum/extend.ts | 4 ++ extensions/lock/js/src/forum/index.js | 4 +- extensions/lock/js/tsconfig.json | 20 +++++++++ extensions/mentions/js/src/forum/extend.ts | 4 ++ extensions/mentions/js/src/forum/index.js | 4 +- extensions/mentions/js/tsconfig.json | 20 +++++++++ extensions/sticky/js/src/forum/extend.ts | 4 ++ extensions/sticky/js/src/forum/index.js | 5 +-- extensions/sticky/js/tsconfig.json | 20 +++++++++ .../subscriptions/js/src/forum/extend.ts | 4 ++ .../subscriptions/js/src/forum/index.js | 4 +- extensions/tags/js/src/forum/extend.ts | 14 +++++++ extensions/tags/js/src/forum/index.ts | 12 +----- framework/core/js/src/common/Application.tsx | 5 +-- framework/core/js/src/common/compat.ts | 5 ++- framework/core/js/src/common/extend/Model.js | 41 ------------------- .../core/js/src/common/extend/PostTypes.js | 13 ------ framework/core/js/src/common/extend/Routes.js | 13 ------ framework/core/js/src/common/extend/index.js | 3 -- .../core/js/src/common/extenders/IExtender.ts | 10 +++++ .../core/js/src/common/extenders/PostTypes.ts | 24 +++++++++++ .../core/js/src/common/extenders/Routes.ts | 33 +++++++++++++++ .../core/js/src/common/extenders/index.ts | 7 ++++ framework/core/js/src/common/index.ts | 3 +- 30 files changed, 213 insertions(+), 101 deletions(-) create mode 100644 extensions/flags/js/src/forum/extend.ts create mode 100644 extensions/likes/js/src/forum/extend.ts create mode 100644 extensions/likes/js/tsconfig.json create mode 100644 extensions/lock/js/src/forum/extend.ts create mode 100644 extensions/lock/js/tsconfig.json create mode 100644 extensions/mentions/js/src/forum/extend.ts create mode 100644 extensions/mentions/js/tsconfig.json create mode 100644 extensions/sticky/js/src/forum/extend.ts create mode 100644 extensions/sticky/js/tsconfig.json create mode 100644 extensions/subscriptions/js/src/forum/extend.ts create mode 100644 extensions/tags/js/src/forum/extend.ts delete mode 100644 framework/core/js/src/common/extend/Model.js delete mode 100644 framework/core/js/src/common/extend/PostTypes.js delete mode 100644 framework/core/js/src/common/extend/Routes.js delete mode 100644 framework/core/js/src/common/extend/index.js create mode 100644 framework/core/js/src/common/extenders/IExtender.ts create mode 100644 framework/core/js/src/common/extenders/PostTypes.ts create mode 100644 framework/core/js/src/common/extenders/Routes.ts create mode 100644 framework/core/js/src/common/extenders/index.ts diff --git a/extensions/flags/js/src/forum/extend.ts b/extensions/flags/js/src/forum/extend.ts new file mode 100644 index 000000000..21b191f93 --- /dev/null +++ b/extensions/flags/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import FlagsPage from './components/FlagsPage'; + +export default [new Extend.Routes().add('flags', '/flags', FlagsPage)]; diff --git a/extensions/flags/js/src/forum/index.ts b/extensions/flags/js/src/forum/index.ts index f59f00985..1cd9b4e7b 100644 --- a/extensions/flags/js/src/forum/index.ts +++ b/extensions/flags/js/src/forum/index.ts @@ -8,14 +8,14 @@ import addFlagControl from './addFlagControl'; import addFlagsDropdown from './addFlagsDropdown'; import addFlagsToPosts from './addFlagsToPosts'; +export { default as extend } from './extend'; + app.initializers.add('flarum-flags', () => { Post.prototype.flags = Model.hasMany('flags'); Post.prototype.canFlag = Model.attribute('canFlag'); app.store.models.flags = Flag; - app.routes.flags = { path: '/flags', component: FlagsPage }; - app.flags = new FlagListState(app); addFlagControl(); diff --git a/extensions/likes/js/src/forum/addLikesTabToUserProfile.tsx b/extensions/likes/js/src/forum/addLikesTabToUserProfile.tsx index 6603bcb74..6447856b8 100644 --- a/extensions/likes/js/src/forum/addLikesTabToUserProfile.tsx +++ b/extensions/likes/js/src/forum/addLikesTabToUserProfile.tsx @@ -2,17 +2,15 @@ import { extend } from 'flarum/common/extend'; import app from 'flarum/forum/app'; import UserPage from 'flarum/forum/components/UserPage'; import LinkButton from 'flarum/common/components/LinkButton'; -import LikesUserPage from './components/LikesUserPage'; import ItemList from 'flarum/common/utils/ItemList'; import type Mithril from 'mithril'; export default function addLikesTabToUserProfile() { - app.routes['user.likes'] = { path: '/u/:username/likes', component: LikesUserPage }; extend(UserPage.prototype, 'navItems', function (items: ItemList) { const user = this.user; items.add( 'likes', - + {app.translator.trans('flarum-likes.forum.user.likes_link')} , 88 diff --git a/extensions/likes/js/src/forum/extend.ts b/extensions/likes/js/src/forum/extend.ts new file mode 100644 index 000000000..d9171d936 --- /dev/null +++ b/extensions/likes/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import LikesUserPage from './components/LikesUserPage'; + +export default [new Extend.Routes().add('user.likes', '/u/:username/likes', LikesUserPage)]; diff --git a/extensions/likes/js/src/forum/index.js b/extensions/likes/js/src/forum/index.js index 5f9184a77..d36b5f082 100644 --- a/extensions/likes/js/src/forum/index.js +++ b/extensions/likes/js/src/forum/index.js @@ -9,6 +9,8 @@ import addLikesList from './addLikesList'; import PostLikedNotification from './components/PostLikedNotification'; import addLikesTabToUserProfile from './addLikesTabToUserProfile'; +export { default as extend } from './extend'; + app.initializers.add('flarum-likes', () => { app.notificationComponents.postLiked = PostLikedNotification; diff --git a/extensions/likes/js/tsconfig.json b/extensions/likes/js/tsconfig.json new file mode 100644 index 000000000..f427c289e --- /dev/null +++ b/extensions/likes/js/tsconfig.json @@ -0,0 +1,20 @@ +{ + // Use Flarum's tsconfig as a starting point + "extends": "flarum-tsconfig", + // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder + // and also tells your Typescript server to read core's global typings for + // access to `dayjs` and `$` in the global namespace. + "include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"], + "compilerOptions": { + // This will output typings to `dist-typings` + "declarationDir": "./dist-typings", + "paths": { + "flarum/*": ["../../../framework/core/js/dist-typings/*"], + // TODO: remove after export registry system implemented + // Without this, the old-style `@flarum/core` import is resolved to + // source code in flarum/core instead of the dist typings. + // This causes an inaccurate "duplicate export" error. + "@flarum/core/*": ["../../../framework/core/js/dist-typings/*"], + } + } +} diff --git a/extensions/lock/js/src/forum/extend.ts b/extensions/lock/js/src/forum/extend.ts new file mode 100644 index 000000000..ab717a167 --- /dev/null +++ b/extensions/lock/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import DiscussionLockedPost from './components/DiscussionLockedPost'; + +export default [new Extend.PostTypes().add('discussionLocked', DiscussionLockedPost)]; diff --git a/extensions/lock/js/src/forum/index.js b/extensions/lock/js/src/forum/index.js index b52ec4ae2..7e02ca761 100644 --- a/extensions/lock/js/src/forum/index.js +++ b/extensions/lock/js/src/forum/index.js @@ -4,13 +4,13 @@ import Model from 'flarum/common/Model'; import Discussion from 'flarum/common/models/Discussion'; import NotificationGrid from 'flarum/forum/components/NotificationGrid'; -import DiscussionLockedPost from './components/DiscussionLockedPost'; import DiscussionLockedNotification from './components/DiscussionLockedNotification'; import addLockBadge from './addLockBadge'; import addLockControl from './addLockControl'; +export { default as extend } from './extend'; + app.initializers.add('flarum-lock', () => { - app.postComponents.discussionLocked = DiscussionLockedPost; app.notificationComponents.discussionLocked = DiscussionLockedNotification; Discussion.prototype.isLocked = Model.attribute('isLocked'); diff --git a/extensions/lock/js/tsconfig.json b/extensions/lock/js/tsconfig.json new file mode 100644 index 000000000..f427c289e --- /dev/null +++ b/extensions/lock/js/tsconfig.json @@ -0,0 +1,20 @@ +{ + // Use Flarum's tsconfig as a starting point + "extends": "flarum-tsconfig", + // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder + // and also tells your Typescript server to read core's global typings for + // access to `dayjs` and `$` in the global namespace. + "include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"], + "compilerOptions": { + // This will output typings to `dist-typings` + "declarationDir": "./dist-typings", + "paths": { + "flarum/*": ["../../../framework/core/js/dist-typings/*"], + // TODO: remove after export registry system implemented + // Without this, the old-style `@flarum/core` import is resolved to + // source code in flarum/core instead of the dist typings. + // This causes an inaccurate "duplicate export" error. + "@flarum/core/*": ["../../../framework/core/js/dist-typings/*"], + } + } +} diff --git a/extensions/mentions/js/src/forum/extend.ts b/extensions/mentions/js/src/forum/extend.ts new file mode 100644 index 000000000..d860db4fd --- /dev/null +++ b/extensions/mentions/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import MentionsUserPage from './components/MentionsUserPage'; + +export default [new Extend.Routes().add('user.mentions', '/u/:username/mentions', MentionsUserPage)]; diff --git a/extensions/mentions/js/src/forum/index.js b/extensions/mentions/js/src/forum/index.js index 467e98e19..0ab3f120f 100644 --- a/extensions/mentions/js/src/forum/index.js +++ b/extensions/mentions/js/src/forum/index.js @@ -13,10 +13,11 @@ import UserMentionedNotification from './components/UserMentionedNotification'; import GroupMentionedNotification from './components/GroupMentionedNotification'; import UserPage from 'flarum/forum/components/UserPage'; import LinkButton from 'flarum/common/components/LinkButton'; -import MentionsUserPage from './components/MentionsUserPage'; import User from 'flarum/common/models/User'; import Model from 'flarum/common/Model'; +export { default as extend } from './extend'; + app.initializers.add('flarum-mentions', function () { User.prototype.canMentionGroups = Model.attribute('canMentionGroups'); @@ -65,7 +66,6 @@ app.initializers.add('flarum-mentions', function () { }); // Add mentions tab in user profile - app.routes['user.mentions'] = { path: '/u/:username/mentions', component: MentionsUserPage }; extend(UserPage.prototype, 'navItems', function (items) { const user = this.user; items.add( diff --git a/extensions/mentions/js/tsconfig.json b/extensions/mentions/js/tsconfig.json new file mode 100644 index 000000000..f427c289e --- /dev/null +++ b/extensions/mentions/js/tsconfig.json @@ -0,0 +1,20 @@ +{ + // Use Flarum's tsconfig as a starting point + "extends": "flarum-tsconfig", + // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder + // and also tells your Typescript server to read core's global typings for + // access to `dayjs` and `$` in the global namespace. + "include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"], + "compilerOptions": { + // This will output typings to `dist-typings` + "declarationDir": "./dist-typings", + "paths": { + "flarum/*": ["../../../framework/core/js/dist-typings/*"], + // TODO: remove after export registry system implemented + // Without this, the old-style `@flarum/core` import is resolved to + // source code in flarum/core instead of the dist typings. + // This causes an inaccurate "duplicate export" error. + "@flarum/core/*": ["../../../framework/core/js/dist-typings/*"], + } + } +} diff --git a/extensions/sticky/js/src/forum/extend.ts b/extensions/sticky/js/src/forum/extend.ts new file mode 100644 index 000000000..1e13921ec --- /dev/null +++ b/extensions/sticky/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import DiscussionStickiedPost from './components/DiscussionStickiedPost'; + +export default [new Extend.PostTypes().add('discussionStickied', DiscussionStickiedPost)]; diff --git a/extensions/sticky/js/src/forum/index.js b/extensions/sticky/js/src/forum/index.js index d7c9a7a43..d42713a93 100644 --- a/extensions/sticky/js/src/forum/index.js +++ b/extensions/sticky/js/src/forum/index.js @@ -2,15 +2,14 @@ import app from 'flarum/forum/app'; import Model from 'flarum/common/Model'; import Discussion from 'flarum/common/models/Discussion'; -import DiscussionStickiedPost from './components/DiscussionStickiedPost'; import addStickyBadge from './addStickyBadge'; import addStickyControl from './addStickyControl'; import addStickyExcerpt from './addStickyExcerpt'; import addStickyClass from './addStickyClass'; -app.initializers.add('flarum-sticky', () => { - app.postComponents.discussionStickied = DiscussionStickiedPost; +export { default as extend } from './extend'; +app.initializers.add('flarum-sticky', () => { Discussion.prototype.isSticky = Model.attribute('isSticky'); Discussion.prototype.canSticky = Model.attribute('canSticky'); diff --git a/extensions/sticky/js/tsconfig.json b/extensions/sticky/js/tsconfig.json new file mode 100644 index 000000000..f427c289e --- /dev/null +++ b/extensions/sticky/js/tsconfig.json @@ -0,0 +1,20 @@ +{ + // Use Flarum's tsconfig as a starting point + "extends": "flarum-tsconfig", + // This will match all .ts, .tsx, .d.ts, .js, .jsx files in your `src` folder + // and also tells your Typescript server to read core's global typings for + // access to `dayjs` and `$` in the global namespace. + "include": ["src/**/*", "../../../framework/core/js/dist-typings/@types/**/*", "@types/**/*"], + "compilerOptions": { + // This will output typings to `dist-typings` + "declarationDir": "./dist-typings", + "paths": { + "flarum/*": ["../../../framework/core/js/dist-typings/*"], + // TODO: remove after export registry system implemented + // Without this, the old-style `@flarum/core` import is resolved to + // source code in flarum/core instead of the dist typings. + // This causes an inaccurate "duplicate export" error. + "@flarum/core/*": ["../../../framework/core/js/dist-typings/*"], + } + } +} diff --git a/extensions/subscriptions/js/src/forum/extend.ts b/extensions/subscriptions/js/src/forum/extend.ts new file mode 100644 index 000000000..6caf9a48d --- /dev/null +++ b/extensions/subscriptions/js/src/forum/extend.ts @@ -0,0 +1,4 @@ +import Extend from 'flarum/common/extenders'; +import IndexPage from 'flarum/forum/components/IndexPage'; + +export default [new Extend.Routes().add('following', '/following', IndexPage)]; diff --git a/extensions/subscriptions/js/src/forum/index.js b/extensions/subscriptions/js/src/forum/index.js index 72b894837..091b61462 100644 --- a/extensions/subscriptions/js/src/forum/index.js +++ b/extensions/subscriptions/js/src/forum/index.js @@ -2,7 +2,6 @@ import { extend } from 'flarum/common/extend'; import app from 'flarum/forum/app'; import Model from 'flarum/common/Model'; import Discussion from 'flarum/common/models/Discussion'; -import IndexPage from 'flarum/forum/components/IndexPage'; import NotificationGrid from 'flarum/forum/components/NotificationGrid'; import addSubscriptionBadge from './addSubscriptionBadge'; @@ -12,8 +11,9 @@ import addSubscriptionSettings from './addSubscriptionSettings'; import NewPostNotification from './components/NewPostNotification'; +export { default as extend } from './extend'; + app.initializers.add('subscriptions', function () { - app.routes.following = { path: '/following', component: IndexPage }; app.notificationComponents.newPost = NewPostNotification; Discussion.prototype.subscription = Model.attribute('subscription'); diff --git a/extensions/tags/js/src/forum/extend.ts b/extensions/tags/js/src/forum/extend.ts new file mode 100644 index 000000000..40191cd3f --- /dev/null +++ b/extensions/tags/js/src/forum/extend.ts @@ -0,0 +1,14 @@ +import app from 'flarum/forum/app'; +import Extend from 'flarum/common/extenders'; +import IndexPage from 'flarum/forum/components/IndexPage'; +import DiscussionTaggedPost from './components/DiscussionTaggedPost'; +import TagsPage from './components/TagsPage'; + +export default [ + new Extend.Routes() + .add('tags', '/tags', TagsPage) + .add('tag', '/t/:tags', IndexPage) + .helper('tag', (tag) => app.route('tag', { tags: tag.slug() })), + + new Extend.PostTypes().add('discussionTagged', DiscussionTaggedPost), +]; diff --git a/extensions/tags/js/src/forum/index.ts b/extensions/tags/js/src/forum/index.ts index 0087ed79d..4822863b7 100644 --- a/extensions/tags/js/src/forum/index.ts +++ b/extensions/tags/js/src/forum/index.ts @@ -1,12 +1,9 @@ import app from 'flarum/forum/app'; import Model from 'flarum/common/Model'; import Discussion from 'flarum/common/models/Discussion'; -import IndexPage from 'flarum/forum/components/IndexPage'; import TagListState from '../common/states/TagListState'; import Tag from '../common/models/Tag'; -import TagsPage from './components/TagsPage'; -import DiscussionTaggedPost from './components/DiscussionTaggedPost'; import addTagList from './addTagList'; import addTagFilter from './addTagFilter'; @@ -14,14 +11,9 @@ import addTagLabels from './addTagLabels'; import addTagControl from './addTagControl'; import addTagComposer from './addTagComposer'; +export { default as extend } from './extend'; + app.initializers.add('flarum-tags', function () { - app.routes.tags = { path: '/tags', component: TagsPage }; - app.routes.tag = { path: '/t/:tags', component: IndexPage }; - - app.route.tag = (tag: Tag) => app.route('tag', { tags: tag.slug() }); - - app.postComponents.discussionTagged = DiscussionTaggedPost; - app.store.models.tags = Tag; app.tagList = new TagListState(); diff --git a/framework/core/js/src/common/Application.tsx b/framework/core/js/src/common/Application.tsx index 35d0aaae8..3b6814e01 100644 --- a/framework/core/js/src/common/Application.tsx +++ b/framework/core/js/src/common/Application.tsx @@ -35,6 +35,7 @@ import type { ComponentAttrs } from './Component'; import Model, { SavedModelData } from './Model'; import fireApplicationError from './helpers/fireApplicationError'; import IHistory from './IHistory'; +import IExtender from './extenders/IExtender'; export type FlarumScreens = 'phone' | 'tablet' | 'desktop' | 'desktop-hd'; @@ -300,8 +301,7 @@ export default class Application { caughtInitializationErrors.forEach((handler) => handler()); } - // TODO: This entire system needs a do-over for v2 - public bootExtensions(extensions: Record) { + public bootExtensions(extensions: Record) { Object.keys(extensions).forEach((name) => { const extension = extensions[name]; @@ -311,7 +311,6 @@ export default class Application { const extenders = extension.extend.flat(Infinity); for (const extender of extenders) { - // @ts-expect-error This is beyond saving atm. extender.extend(this, { name, exports: extension }); } }); diff --git a/framework/core/js/src/common/compat.ts b/framework/core/js/src/common/compat.ts index 394dc6fd7..5eb9e0ffb 100644 --- a/framework/core/js/src/common/compat.ts +++ b/framework/core/js/src/common/compat.ts @@ -1,5 +1,5 @@ -// @ts-expect-error We need to explicitly use the prefix to distinguish between the extend folder. -import * as extend from './extend.ts'; +import * as extend from './extend'; +import extenders from './extenders'; import Session from './Session'; import Store from './Store'; import BasicEditorDriver from './utils/BasicEditorDriver'; @@ -90,6 +90,7 @@ import ModalManagerState from './states/ModalManagerState'; import PageState from './states/PageState'; export default { + extenders, extend: extend, Session: Session, Store: Store, diff --git a/framework/core/js/src/common/extend/Model.js b/framework/core/js/src/common/extend/Model.js deleted file mode 100644 index b57420dbf..000000000 --- a/framework/core/js/src/common/extend/Model.js +++ /dev/null @@ -1,41 +0,0 @@ -export default class Model { - type; - attributes = []; - hasOnes = []; - hasManys = []; - - constructor(type, model = null) { - this.type = type; - this.model = model; - } - - attribute(name) { - this.attributes.push(name); - - return this; - } - - hasOne(type) { - this.hasOnes.push(type); - - return this; - } - - hasMany(type) { - this.hasManys.push(type); - - return this; - } - - extend(app, extension) { - if (this.model) { - app.store.models[this.type] = this.model; - } - - const model = app.store.models[this.type]; - - this.attributes.forEach((name) => (model.prototype[name] = model.attribute(name))); - this.hasOnes.forEach((name) => (model.prototype[name] = model.hasOne(name))); - this.hasManys.forEach((name) => (model.prototype[name] = model.hasMany(name))); - } -} diff --git a/framework/core/js/src/common/extend/PostTypes.js b/framework/core/js/src/common/extend/PostTypes.js deleted file mode 100644 index dc7475d56..000000000 --- a/framework/core/js/src/common/extend/PostTypes.js +++ /dev/null @@ -1,13 +0,0 @@ -export default class PostTypes { - postComponents = {}; - - add(name, component) { - this.postComponents[name] = component; - - return this; - } - - extend(app, extension) { - Object.assign(app.postComponents, this.postComponents); - } -} diff --git a/framework/core/js/src/common/extend/Routes.js b/framework/core/js/src/common/extend/Routes.js deleted file mode 100644 index 3d4603a1f..000000000 --- a/framework/core/js/src/common/extend/Routes.js +++ /dev/null @@ -1,13 +0,0 @@ -export default class Routes { - routes = {}; - - add(name, path, component) { - this.routes[name] = { path, component }; - - return this; - } - - extend(app, extension) { - Object.assign(app.routes, this.routes); - } -} diff --git a/framework/core/js/src/common/extend/index.js b/framework/core/js/src/common/extend/index.js deleted file mode 100644 index 6d17eb79a..000000000 --- a/framework/core/js/src/common/extend/index.js +++ /dev/null @@ -1,3 +0,0 @@ -export { default as Model } from './Model'; -export { default as PostTypes } from './PostTypes'; -export { default as Routes } from './Routes'; diff --git a/framework/core/js/src/common/extenders/IExtender.ts b/framework/core/js/src/common/extenders/IExtender.ts new file mode 100644 index 000000000..12a781e9d --- /dev/null +++ b/framework/core/js/src/common/extenders/IExtender.ts @@ -0,0 +1,10 @@ +import Application from '../Application'; + +export interface IExtensionModule { + name: string; + exports: unknown; +} + +export default interface IExtender { + extend(app: Application, extension: IExtensionModule): void; +} diff --git a/framework/core/js/src/common/extenders/PostTypes.ts b/framework/core/js/src/common/extenders/PostTypes.ts new file mode 100644 index 000000000..f361eef7e --- /dev/null +++ b/framework/core/js/src/common/extenders/PostTypes.ts @@ -0,0 +1,24 @@ +import IExtender, { IExtensionModule } from './IExtender'; +import Application from '../Application'; +import ForumApplication from '../../forum/ForumApplication'; + +export default class PostTypes implements IExtender { + private postComponents: Record = {}; + + /** + * Register a new post component type. + * Usually used for event posts. + * + * @param name The name of the post type. + * @param component The component class to render the post. + */ + add(name: string, component: any): PostTypes { + this.postComponents[name] = component; + + return this; + } + + extend(app: Application, extension: IExtensionModule): void { + Object.assign((app as unknown as ForumApplication).postComponents, this.postComponents); + } +} diff --git a/framework/core/js/src/common/extenders/Routes.ts b/framework/core/js/src/common/extenders/Routes.ts new file mode 100644 index 000000000..c593b8204 --- /dev/null +++ b/framework/core/js/src/common/extenders/Routes.ts @@ -0,0 +1,33 @@ +import Application, { FlarumGenericRoute } from '../Application'; +import IExtender, { IExtensionModule } from './IExtender'; + +type HelperRoute = (...args: any) => string; + +export default class Routes implements IExtender { + private routes: Record = {}; + private helpers: Record = {}; + + /** + * Add a mithril route to the application. + * + * @param name The name of the route. + * @param path The path of the route. + * @param component must extend `Page` component. + */ + add(name: string, path: `/${string}`, component: any): Routes { + this.routes[name] = { path, component }; + + return this; + } + + helper(name: string, callback: HelperRoute): Routes { + this.helpers[name] = callback; + + return this; + } + + extend(app: Application, extension: IExtensionModule) { + Object.assign(app.routes, this.routes); + Object.assign(app.route, this.helpers); + } +} diff --git a/framework/core/js/src/common/extenders/index.ts b/framework/core/js/src/common/extenders/index.ts new file mode 100644 index 000000000..58fe4f303 --- /dev/null +++ b/framework/core/js/src/common/extenders/index.ts @@ -0,0 +1,7 @@ +import PostTypes from './PostTypes'; +import Routes from './Routes'; + +export default { + PostTypes, + Routes, +}; diff --git a/framework/core/js/src/common/index.ts b/framework/core/js/src/common/index.ts index 2f6f7a018..bfc0955b5 100644 --- a/framework/core/js/src/common/index.ts +++ b/framework/core/js/src/common/index.ts @@ -19,10 +19,9 @@ import patchMithril from './utils/patchMithril'; patchMithril(window); -import * as Extend from './extend/index'; import app from './app'; -export { Extend, app }; +export { app }; import './utils/arrayFlatPolyfill';