Skip to content

Commit

Permalink
Revert "wip: remove concept of builtin modules"
Browse files Browse the repository at this point in the history
Until we have a store, or a bundle to import we need the builtin modules

This reverts commit 34c26c5b1a0f1c1989ad08af2986db65911a5757.
  • Loading branch information
Julusian committed Nov 4, 2024
1 parent f1773a5 commit 3c73fa1
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 32 deletions.
26 changes: 18 additions & 8 deletions companion/lib/Instance/Controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ import type { PageController } from '../Page/Controller.js'
import express from 'express'
import { InstanceInstalledModulesManager } from './InstalledModulesManager.js'
import type { ModuleVersionInfo } from '@companion-app/shared/Model/ModuleInfo.js'
import type { ModuleDirs } from './Types.js'
import path from 'path'
import { isPackaged } from '../Resources/Util.js'
import { fileURLToPath } from 'url'
import { ModuleStoreService } from './ModuleStore.js'
import type { AppInfo } from '../Registry.js'
import type { DataCache } from '../Data/Cache.js'
Expand Down Expand Up @@ -100,14 +103,26 @@ export class InstanceController extends EventEmitter<InstanceControllerEvents> {
this.#variablesController = variables
this.#controlsController = controls

const installedModulesDir = path.join(appInfo.modulesDir, 'store')
function generatePath(subpath: string): string {
if (isPackaged()) {
return path.join(__dirname, subpath)
} else {
return fileURLToPath(new URL(path.join('../../..', subpath), import.meta.url))
}
}

const moduleDirs: ModuleDirs = {
bundledLegacyModulesDir: path.resolve(generatePath('modules')),
bundledModulesDir: path.resolve(generatePath('bundled-modules')),
installedModulesDir: path.join(appInfo.modulesDir, 'store'),
}

this.#configStore = new ConnectionConfigStore(db, this.broadcastChanges.bind(this))

this.sharedUdpManager = new InstanceSharedUdpManager()
this.definitions = new InstanceDefinitions(io, controls, graphics, variables.values)
this.status = new InstanceStatus(io, controls)
this.modules = new InstanceModules(io, this, apiRouter, installedModulesDir)
this.modules = new InstanceModules(io, this, apiRouter, moduleDirs)
this.moduleHost = new ModuleHost(
{
controls: controls,
Expand All @@ -127,12 +142,7 @@ export class InstanceController extends EventEmitter<InstanceControllerEvents> {
this.#configStore
)
this.modulesStore = new ModuleStoreService(io, cache)
this.userModulesManager = new InstanceInstalledModulesManager(
appInfo,
this.modules,
this.modulesStore,
installedModulesDir
)
this.userModulesManager = new InstanceInstalledModulesManager(appInfo, this.modules, this.modulesStore, moduleDirs)

graphics.on('resubscribeFeedbacks', () => this.moduleHost.resubscribeAllFeedbacks())

Expand Down
10 changes: 3 additions & 7 deletions companion/lib/Instance/InstalledModulesManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import * as ts from 'tar-stream'
import { Readable } from 'node:stream'
import { ModuleManifest } from '@companion-module/base'
import * as tarfs from 'tar-fs'
import type { ModuleDirs } from './Types.js'
import type { ModuleStoreService } from './ModuleStore.js'
import type { AppInfo } from '../Registry.js'
import { promisify } from 'util'
Expand Down Expand Up @@ -41,16 +42,11 @@ export class InstanceInstalledModulesManager {
*/
readonly #modulesDir: string

constructor(
appInfo: AppInfo,
modulesManager: InstanceModules,
modulesStore: ModuleStoreService,
installedModulesDir: string
) {
constructor(appInfo: AppInfo, modulesManager: InstanceModules, modulesStore: ModuleStoreService, dirs: ModuleDirs) {
this.#appInfo = appInfo
this.#modulesManager = modulesManager
this.#modulesStore = modulesStore
this.#modulesDir = installedModulesDir
this.#modulesDir = dirs.installedModulesDir
}

/**
Expand Down
5 changes: 5 additions & 0 deletions companion/lib/Instance/ModuleInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ function translateStableVersion(version: SomeModuleVersionInfo | null): NewClien
displayName: 'Latest Stable (Dev)',
isLegacy: false,
isDev: true,
isBuiltin: false,
hasHelp: version.helpPath !== null,
version: {
mode: 'stable',
Expand All @@ -98,6 +99,7 @@ function translateStableVersion(version: SomeModuleVersionInfo | null): NewClien
displayName: `Latest Stable (v${version.versionId})`,
isLegacy: version.display.isLegacy ?? false,
isDev: false,
isBuiltin: version.isBuiltin,
hasHelp: version.helpPath !== null,
version: {
mode: 'stable',
Expand All @@ -116,6 +118,7 @@ function translatePrereleaseVersion(version: SomeModuleVersionInfo | null): NewC
displayName: 'Latest Prerelease (Dev)',
isLegacy: false,
isDev: true,
isBuiltin: false,
hasHelp: version.helpPath !== null,
version: {
mode: 'prerelease',
Expand All @@ -128,6 +131,7 @@ function translatePrereleaseVersion(version: SomeModuleVersionInfo | null): NewC
displayName: `Latest Prerelease (v${version.versionId})`,
isLegacy: version.display.isLegacy ?? false,
isDev: false,
isBuiltin: version.isBuiltin,
hasHelp: version.helpPath !== null,
version: {
mode: 'prerelease',
Expand All @@ -144,6 +148,7 @@ function translateReleaseVersion(version: ReleaseModuleVersionInfo): NewClientMo
displayName: `v${version.versionId}`,
isLegacy: version.display.isLegacy ?? false,
isDev: false,
isBuiltin: version.isBuiltin,
hasHelp: version.helpPath !== null,
version: {
mode: 'specific-version',
Expand Down
58 changes: 50 additions & 8 deletions companion/lib/Instance/Modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import type { HelpDescription } from '@companion-app/shared/Model/Common.js'
import LogController from '../Log/Controller.js'
import type { InstanceController } from './Controller.js'
import jsonPatch from 'fast-json-patch'
import type { SomeModuleVersionInfo } from './Types.js'
import type { ModuleDirs, SomeModuleVersionInfo } from './Types.js'
import { InstanceModuleInfo } from './ModuleInfo.js'

const ModulesRoom = 'modules'
Expand Down Expand Up @@ -65,12 +65,12 @@ export class InstanceModules {
*/
readonly #moduleScanner = new InstanceModuleScanner()

readonly #installedModulesDir: string
readonly #moduleDirs: ModuleDirs

constructor(io: UIHandler, instance: InstanceController, apiRouter: express.Router, installedModulesDir: string) {
constructor(io: UIHandler, instance: InstanceController, apiRouter: express.Router, moduleDirs: ModuleDirs) {
this.#io = io
this.#instanceController = instance
this.#installedModulesDir = installedModulesDir
this.#moduleDirs = moduleDirs

apiRouter.get('/help/module/:moduleId/:versionMode/:versionId/*path', this.#getHelpAsset)
}
Expand All @@ -96,6 +96,7 @@ export class InstanceModules {
type: 'release',
versionId: loadedModuleInfo.display.version,
releaseType: loadedModuleInfo.isPrerelease ? 'prerelease' : 'stable',
isBuiltin: false,
}

// Notify clients
Expand Down Expand Up @@ -141,15 +142,47 @@ export class InstanceModules {
* @param extraModulePath - extra directory to search for modules
*/
async initInstances(extraModulePath: string): Promise<void> {
// And modules from the installed modules dir
const storeModules = await this.#moduleScanner.loadInfoForModulesInDir(this.#installedModulesDir, true)
const legacyCandidates = await this.#moduleScanner.loadInfoForModulesInDir(
this.#moduleDirs.bundledLegacyModulesDir,
false
)

// Start with 'legacy' candidates
for (const candidate of legacyCandidates) {
candidate.display.isLegacy = true
const moduleInfo = this.#getOrCreateModuleEntry(candidate.manifest.id)
moduleInfo.installedVersions[candidate.display.version] = {
...candidate,
type: 'release',
releaseType: 'stable',
versionId: candidate.display.version,
isBuiltin: true,
}
}

// Load bundled modules
const bundledModules = await this.#moduleScanner.loadInfoForModulesInDir(this.#moduleDirs.bundledModulesDir, false)
for (const candidate of bundledModules) {
const moduleInfo = this.#getOrCreateModuleEntry(candidate.manifest.id)
moduleInfo.installedVersions[candidate.display.version] = {
...candidate,
type: 'release',
releaseType: 'stable',
versionId: candidate.display.version,
isBuiltin: true,
}
}

// And modules from the store
const storeModules = await this.#moduleScanner.loadInfoForModulesInDir(this.#moduleDirs.installedModulesDir, true)
for (const candidate of storeModules) {
const moduleInfo = this.#getOrCreateModuleEntry(candidate.manifest.id)
moduleInfo.installedVersions[candidate.display.version] = {
...candidate,
type: 'release',
releaseType: candidate.isPrerelease ? 'prerelease' : 'stable',
versionId: candidate.display.version,
isBuiltin: false,
}
}

Expand Down Expand Up @@ -190,15 +223,24 @@ export class InstanceModules {

if (moduleInfo.devModule) {
this.#logger.info(
`${moduleInfo.devModule.display.id}: ${moduleInfo.devModule.display.name} (Dev${
`${moduleInfo.devModule.display.id}: ${moduleInfo.devModule.display.name} (Overridden${
moduleInfo.devModule.isPackaged ? ' & Packaged' : ''
})`
)
}

for (const moduleVersion of Object.values(moduleInfo.installedVersions)) {
if (!moduleVersion) continue
this.#logger.info(`${moduleVersion.display.id}@${moduleVersion.display.version}: ${moduleVersion.display.name}`)
this.#logger.info(
`${moduleVersion.display.id}@${moduleVersion.display.version}: ${moduleVersion.display.name}${moduleVersion.isBuiltin ? ' (Builtin)' : ''}`
)
}

for (const moduleVersion of Object.values(moduleInfo.installedVersions)) {
if (!moduleVersion) continue
this.#logger.info(
`${moduleVersion.display.id}@${moduleVersion.display.version}: ${moduleVersion.display.name} (Custom)`
)
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions companion/lib/Instance/Types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import type { ModuleDisplayInfo } from '@companion-app/shared/Model/ModuleInfo.js'
import type { ModuleManifest } from '@companion-module/base'

export interface ModuleDirs {
readonly bundledLegacyModulesDir: string
readonly bundledModulesDir: string
readonly installedModulesDir: string
}

export interface ModuleVersionInfoBase {
basePath: string
helpPath: string | null
Expand All @@ -14,6 +20,7 @@ export interface ReleaseModuleVersionInfo extends ModuleVersionInfoBase {
type: 'release'
releaseType: 'stable' | 'prerelease'
versionId: string
isBuiltin: boolean
}
export interface DevModuleVersionInfo extends ModuleVersionInfoBase {
type: 'dev'
Expand Down
1 change: 1 addition & 0 deletions shared-lib/lib/Model/ModuleInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ export interface NewClientModuleVersionInfo2 {
displayName: string
isLegacy: boolean
isDev: boolean
isBuiltin: boolean
version: ModuleVersionInfo
hasHelp: boolean
}
Expand Down
16 changes: 11 additions & 5 deletions webui/src/Modules/ModuleVersionsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { socketEmitPromise } from '../util.js'
import { CButton, CButtonGroup } from '@coreui/react'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import {
faLock,
faPlus,
faQuestion,
faStar,
Expand Down Expand Up @@ -147,7 +148,7 @@ const ModuleVersionRow = observer(function ModuleVersionRow({
<tr>
<td>
{installedInfo ? (
<ModuleUninstallButton moduleId={moduleId} versionId={versionId} />
<ModuleUninstallButton moduleId={moduleId} versionId={versionId} isBuiltin={installedInfo.isBuiltin} />
) : (
<ModuleInstallButton
moduleId={moduleId}
Expand All @@ -159,9 +160,6 @@ const ModuleVersionRow = observer(function ModuleVersionRow({
</td>
<td>
{versionId}
{isLatestStable && <FontAwesomeIcon icon={faStar} title="Latest stable" />}
{isLatestPrerelease && <FontAwesomeIcon icon={faQuestion} title="Latest prerelease" />}

{storeInfo?.isPrerelease && <FontAwesomeIcon icon={faQuestion} title="Prerelease" />}
{storeInfo?.deprecationReason && <FontAwesomeIcon icon={faWarning} title="Deprecated" />}
</td>
Expand All @@ -173,6 +171,9 @@ const ModuleVersionRow = observer(function ModuleVersionRow({
)}
</td>
<td>
{isLatestStable && <FontAwesomeIcon icon={faStar} title="Latest stable" />}
{isLatestPrerelease && <FontAwesomeIcon icon={faQuestion} title="Latest prerelease" />}

<ModuleVersionUsageIcon
moduleId={moduleId}
moduleVersionMode="specific-version"
Expand All @@ -199,9 +200,10 @@ function LastUpdatedTimestamp({ releasedAt }: { releasedAt: number | undefined }
interface ModuleUninstallButtonProps {
moduleId: string
versionId: string
isBuiltin: boolean
}

function ModuleUninstallButton({ moduleId, versionId }: ModuleUninstallButtonProps) {
function ModuleUninstallButton({ moduleId, versionId, isBuiltin }: ModuleUninstallButtonProps) {
const { socket, notifier } = useContext(RootAppStoreContext)

const [isRunningInstallOrUninstall, setIsRunningInstallOrUninstall] = useState(false)
Expand All @@ -224,6 +226,10 @@ function ModuleUninstallButton({ moduleId, versionId }: ModuleUninstallButtonPro
})
}, [socket, moduleId, versionId])

if (isBuiltin) {
return <FontAwesomeIcon className="disabled" icon={faLock} title="Version cannot be removed" />
}

return (
<CButton color="white" disabled={isRunningInstallOrUninstall} onClick={doRemove}>
{isRunningInstallOrUninstall ? (
Expand Down
21 changes: 17 additions & 4 deletions webui/src/Modules/ModulesList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ import { useTableVisibilityHelper, VisibilityButton } from '../Components/TableV

interface VisibleModulesState {
dev: boolean
installed: boolean
builtin: boolean
store: boolean
}

interface ModulesListProps {
Expand All @@ -42,7 +43,8 @@ export const ModulesList = observer(function ModulesList({

const visibleModules = useTableVisibilityHelper<VisibleModulesState>('modules_visible', {
dev: true,
installed: true,
builtin: true,
store: true,
})

const [filter, setFilter] = useState('')
Expand All @@ -55,7 +57,17 @@ export const ModulesList = observer(function ModulesList({
for (const moduleInfo of searchResults) {
let isVisible = false
if (moduleInfo.hasDevVersion && visibleModules.visiblity.dev) isVisible = true
if (moduleInfo.installedVersions.length > 0 && visibleModules.visiblity.installed) isVisible = true

const [hasBuiltin, hasStore] = moduleInfo.installedVersions.reduce(
([builtin, release], v) => {
if (v.isBuiltin) return [true, release]
if (!v.isBuiltin) return [builtin, true]
return [builtin, release]
},
[false, false]
)
if (hasBuiltin && visibleModules.visiblity.builtin) isVisible = true
if (hasStore && visibleModules.visiblity.store) isVisible = true

if (!isVisible) continue

Expand Down Expand Up @@ -116,7 +128,8 @@ export const ModulesList = observer(function ModulesList({
<th colSpan={3} className="fit">
<CButtonGroup className="table-header-buttons">
<VisibilityButton {...visibleModules} keyId="dev" color="secondary" label="Dev" />
<VisibilityButton {...visibleModules} keyId="installed" color="warning" label="Installed" />
<VisibilityButton {...visibleModules} keyId="builtin" color="success" label="Builtin" />
<VisibilityButton {...visibleModules} keyId="store" color="warning" label="Store" />
</CButtonGroup>
</th>
</tr>
Expand Down

0 comments on commit 3c73fa1

Please sign in to comment.