Skip to content

Commit

Permalink
Merge pull request #18 from studiorack/feature/clean-start
Browse files Browse the repository at this point in the history
Pure ES modules, vitest and TypeScript upgrade
  • Loading branch information
kmturley authored Aug 12, 2024
2 parents c3f2291 + 672cb41 commit 30a64c2
Show file tree
Hide file tree
Showing 77 changed files with 9,361 additions and 8,466 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Release
on:
push:
tags:
- "v*"
- 'v*'

jobs:
create_release:
Expand Down Expand Up @@ -66,8 +66,8 @@ jobs:
needs: [create_release, build_release]
runs-on: ubuntu-latest
steps:
- uses: eregon/publish-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release_id: ${{ needs.create_release.outputs.upload_id }}
- uses: eregon/publish-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
release_id: ${{ needs.create_release.outputs.upload_id }}
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ name: Test

on:
push:
pull_request:

jobs:
test_code:
Expand Down
55 changes: 25 additions & 30 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,38 +1,33 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# Logs
logs
*.log
npm-debug.log*

# dependencies
/node_modules
/.pnp
.pnp.js
# Dependencies
node_modules/

# testing
/coverage
# Coverage
coverage

# next.js
/.next/
/out/
/renderer/.next/
/renderer/out/
/main/
/dist/
# Transpiled files
build/
main/
out/
.next/
test/tool

# production
/build
# VS Code
.vscode
!.vscode/tasks.js

# misc
.DS_Store
*.pem
# JetBrains IDEs
.idea/

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Optional npm cache directory
.npm

# local env files
.env.local
.env.development.local
.env.test.local
.env.production.local
# Optional eslint cache
.eslintcache

# vercel
.vercel
# Misc
.DS_Store
5 changes: 0 additions & 5 deletions .prettierrc

This file was deleted.

15 changes: 15 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"arrowParens": "avoid",
"bracketSpacing": true,
"endOfLine": "lf",
"bracketSameLine": false,
"jsxSingleQuote": false,
"printWidth": 120,
"proseWrap": "preserve",
"quoteProps": "as-needed",
"semi": true,
"singleQuote": true,
"tabWidth": 2,
"trailingComma": "all",
"useTabs": false
}
21 changes: 12 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# studiorack-app

![Release](https://github.com/studiorack/studiorack-app/workflows/Release/badge.svg)

Audio plugin app, searchable list of plugins to install and share.
Expand All @@ -17,28 +18,31 @@ Download the file and open to install the app on to your machine. Follow instruc

StudioRack App was built using:

* NodeJS 17.x
* TypeScript 4.x
* NextJS 12.x
* React 17.x
* Electron 15.x

- NodeJS 20.x
- TypeScript 5.x
- NextJS 14.x
- React 18.x
- Electron

## Installation

Install dependencies using:

npm install


## Usage

Run the development server using:

npm run dev

View the app in the application window opened automatically
View the site at:

http://localhost:3000

Get the api at:

http://localhost:3000/api/plugins

## Deployment

Expand All @@ -51,7 +55,6 @@ This will run an automated build and deploy process on GitHub Actions:

.github/workflows/release.yml


## Contact

For more information please contact kmturley
26 changes: 13 additions & 13 deletions electron-src/api.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,52 @@
import { ipcRenderer } from 'electron';
import { PluginInterface } from '@studiorack/core';
import { PluginVersion, PluginVersionLocal, ProjectVersionLocal, ProjectVersionPlugins } from '@studiorack/core';

function message(val: any) {
function message(val: string | object) {
return ipcRenderer.send('message', val);
}

async function pluginsGetLocal(): Promise<any> {
async function pluginsGetLocal(): Promise<PluginVersionLocal[]> {
return ipcRenderer.invoke('pluginsGetLocal');
}

async function pluginGetLocal(id: string): Promise<any> {
async function pluginGetLocal(id: string): Promise<PluginVersionLocal> {
return ipcRenderer.invoke('pluginGetLocal', id);
}

async function pluginInstall(plugin: PluginInterface): Promise<any> {
async function pluginInstall(plugin: PluginVersion): Promise<PluginVersionLocal> {
console.log('pluginInstall api', plugin);
return ipcRenderer.invoke('pluginInstall', plugin);
}

async function pluginsInstall(plugins: any): Promise<any> {
async function pluginsInstall(plugins: ProjectVersionPlugins): Promise<PluginVersionLocal[]> {
return ipcRenderer.invoke('pluginsInstall', plugins);
}

async function pluginUninstall(plugin: PluginInterface): Promise<any> {
async function pluginUninstall(plugin: PluginVersion): Promise<PluginVersionLocal> {
return ipcRenderer.invoke('pluginUninstall', plugin);
}

async function projectsGetLocal(): Promise<any> {
async function projectsGetLocal(): Promise<ProjectVersionLocal[]> {
return ipcRenderer.invoke('projectsGetLocal');
}

async function projectGetLocal(id: string): Promise<any> {
async function projectGetLocal(id: string): Promise<ProjectVersionLocal> {
return ipcRenderer.invoke('projectGetLocal', id);
}

async function projectOpen(path: string): Promise<any> {
async function projectOpen(path: string): Promise<ProjectVersionLocal> {
return ipcRenderer.invoke('projectOpen', path);
}

async function folderSelect(path: string): Promise<any> {
async function folderSelect(path: string): Promise<Electron.OpenDialogReturnValue> {
return ipcRenderer.invoke('folderSelect', path);
}

async function storeGet(key: string): Promise<any> {
async function storeGet(key: string): Promise<string> {
return ipcRenderer.invoke('storeGet', key);
}

async function storeSet(key: string, val: any): Promise<any> {
async function storeSet(key: string, val: string | object): Promise<string> {
return ipcRenderer.invoke('storeSet', key, val);
}

Expand Down
42 changes: 22 additions & 20 deletions electron-src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import { parse } from 'url';
import { BrowserWindow, app, dialog, session, ipcMain, IpcMainEvent, protocol } from 'electron';
import fixPath from 'fix-path';
import isDev from 'electron-is-dev';
import { createServer } from 'http';
import next from 'next';
import { createServer as createServerHttp, IncomingMessage, ServerResponse } from 'http';
import createServer from 'next/dist/server/next.js';

// Ensure Electron apps subprocess on macOS and Linux inherit system $PATH
fixPath();

// custom code
import {
fileOpen,
PluginInterface,
PluginVersion,
pluginGetLocal,
pluginInstall,
pluginsGetLocal,
Expand All @@ -25,14 +25,16 @@ import {
configGet,
ConfigInterface,
configSet,
ProjectVersionPlugins,
} from '@studiorack/core';

const DEFAULT_PAGE = 'projects';

// Prepare the renderer once the app is ready
app.on('ready', async () => {
// Use server-side rendering for both dev and production builds
const nextApp = next({
// @ts-expect-error incorrect types returned
const nextApp = createServer({
dev: isDev,
dir: join(app.getAppPath(), 'renderer'),
});
Expand All @@ -42,8 +44,8 @@ app.on('ready', async () => {
await nextApp.prepare();

// Create a new native HTTP server (which supports hot code reloading)
createServer((req: any, res: any) => {
const parsedUrl = parse(req.url, true);
createServerHttp((req: IncomingMessage, res: ServerResponse) => {
const parsedUrl = parse(req.url ? req.url : '', true);
requestHandler(req, res, parsedUrl);
}).listen(3000, () => {
console.log('> Ready on http://localhost:3000');
Expand All @@ -68,13 +70,13 @@ app.on('ready', async () => {
'Content-Security-Policy': [
`
default-src 'self' *.youtube.com;
connect-src 'self' *.github.io data: *.google-analytics.com;
connect-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.google-analytics.com *.doubleclick.net *.google.com *.googleapis.com data:;
font-src 'self' fonts.gstatic.com;
img-src 'self' github.com *.githubusercontent.com *.s3.amazonaws.com *.youtube.com data: media:;
media-src 'self' github.com *.githubusercontent.com *.s3.amazonaws.com *.youtube.com media:;
img-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.s3.amazonaws.com *.youtube.com *.ytimg.com data: media:;
media-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.s3.amazonaws.com *.youtube.com media:;
object-src 'none';
script-src 'self' 'unsafe-inline' 'unsafe-eval' *.doubleclick.net *.google.com *.gstatic.com *.googletagmanager.com *.google-analytics.com;
style-src 'self' 'unsafe-inline' fonts.googleapis.com
script-src 'self' 'unsafe-inline' 'unsafe-eval' github.com *.github.com *.github.io *.githubusercontent.com *.doubleclick.net *.google.com *.gstatic.com *.googletagmanager.com *.google-analytics.com;
style-src 'self' 'unsafe-inline' github.com *.github.com *.github.io *.githubusercontent.com fonts.googleapis.com
`,
],
},
Expand All @@ -85,7 +87,8 @@ app.on('ready', async () => {
width: isDev ? 1024 + 445 : 1024,
height: 768,
webPreferences: {
preload: join(app.getAppPath(), 'main', 'preload.js'),
sandbox: false,
preload: join(app.getAppPath(), 'main', 'preload.mjs'),
},
});

Expand All @@ -101,7 +104,7 @@ app.on('ready', async () => {
app.on('window-all-closed', app.quit);

// Listen the channel `message` and resend the received message to the renderer process
ipcMain.on('message', (event: IpcMainEvent, message: any) => {
ipcMain.on('message', (event: IpcMainEvent, message: string | object) => {
event.sender.send('message', message);
});

Expand All @@ -118,25 +121,24 @@ ipcMain.handle('pluginGetLocal', async (_event, id: string) => {
});

// Install plugin into root plugin folder locally
ipcMain.handle('pluginInstall', async (_event, plugin: PluginInterface) => {
ipcMain.handle('pluginInstall', async (_event, plugin: PluginVersion) => {
console.log('pluginInstall index', plugin);
return await pluginInstall(`${plugin.repo}/${plugin.id}`, plugin.version);
return await pluginInstall(plugin.id || '', plugin.version);
});

// Install plugin into root plugin folder locally
ipcMain.handle('pluginsInstall', async (_event, plugins: any) => {
ipcMain.handle('pluginsInstall', async (_event, plugins: ProjectVersionPlugins) => {
console.log('pluginsInstall', plugins);
const promises = Object.keys(plugins).map((pluginId: string) => {
const plugin = plugins[pluginId];
return pluginInstall(`${plugin.repo}/${plugin.id}`, plugin.version);
return pluginInstall(pluginId, plugins[pluginId]);
});
return Promise.all(promises);
});

// Uninstall plugin from root plugin folder locally
ipcMain.handle('pluginUninstall', async (_event, plugin) => {
console.log('pluginUninstall', plugin);
return await pluginUninstall(`${plugin.repo}/${plugin.id}`, plugin.version);
return await pluginUninstall(plugin.id || '', plugin.version);
});

// Get projects installed locally
Expand Down Expand Up @@ -178,7 +180,7 @@ ipcMain.handle('storeGet', async (_event, key: keyof ConfigInterface) => {
});

// Set user-specific setting
ipcMain.handle('storeSet', async (_event, key: keyof ConfigInterface, val: any) => {
ipcMain.handle('storeSet', async (_event, key: keyof ConfigInterface, val: string | object) => {
console.log('storeSet', key, val);
if (!key || !val) return;
return configSet(key, val);
Expand Down
6 changes: 6 additions & 0 deletions electron-src/preload.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// This file is intentionally .mjs to ensure Electron treats it as an ES module.
// https://www.electronjs.org/docs/latest/tutorial/esm
import { contextBridge } from 'electron';
import api from './api.js';

contextBridge.exposeInMainWorld('electronAPI', api);
4 changes: 0 additions & 4 deletions electron-src/preload.ts

This file was deleted.

Loading

0 comments on commit 30a64c2

Please sign in to comment.