Skip to content

Commit 30a64c2

Browse files
authored
Merge pull request #18 from studiorack/feature/clean-start
Pure ES modules, vitest and TypeScript upgrade
2 parents c3f2291 + 672cb41 commit 30a64c2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

77 files changed

+9361
-8466
lines changed

.github/workflows/release.yml

+6-6
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Release
33
on:
44
push:
55
tags:
6-
- "v*"
6+
- 'v*'
77

88
jobs:
99
create_release:
@@ -66,8 +66,8 @@ jobs:
6666
needs: [create_release, build_release]
6767
runs-on: ubuntu-latest
6868
steps:
69-
- uses: eregon/publish-release@v1
70-
env:
71-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72-
with:
73-
release_id: ${{ needs.create_release.outputs.upload_id }}
69+
- uses: eregon/publish-release@v1
70+
env:
71+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
72+
with:
73+
release_id: ${{ needs.create_release.outputs.upload_id }}

.github/workflows/test.yml

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ name: Test
22

33
on:
44
push:
5+
pull_request:
56

67
jobs:
78
test_code:

.gitignore

+25-30
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
1-
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
25

3-
# dependencies
4-
/node_modules
5-
/.pnp
6-
.pnp.js
6+
# Dependencies
7+
node_modules/
78

8-
# testing
9-
/coverage
9+
# Coverage
10+
coverage
1011

11-
# next.js
12-
/.next/
13-
/out/
14-
/renderer/.next/
15-
/renderer/out/
16-
/main/
17-
/dist/
12+
# Transpiled files
13+
build/
14+
main/
15+
out/
16+
.next/
17+
test/tool
1818

19-
# production
20-
/build
19+
# VS Code
20+
.vscode
21+
!.vscode/tasks.js
2122

22-
# misc
23-
.DS_Store
24-
*.pem
23+
# JetBrains IDEs
24+
.idea/
2525

26-
# debug
27-
npm-debug.log*
28-
yarn-debug.log*
29-
yarn-error.log*
26+
# Optional npm cache directory
27+
.npm
3028

31-
# local env files
32-
.env.local
33-
.env.development.local
34-
.env.test.local
35-
.env.production.local
29+
# Optional eslint cache
30+
.eslintcache
3631

37-
# vercel
38-
.vercel
32+
# Misc
33+
.DS_Store

.prettierrc

-5
This file was deleted.

.prettierrc.json

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"arrowParens": "avoid",
3+
"bracketSpacing": true,
4+
"endOfLine": "lf",
5+
"bracketSameLine": false,
6+
"jsxSingleQuote": false,
7+
"printWidth": 120,
8+
"proseWrap": "preserve",
9+
"quoteProps": "as-needed",
10+
"semi": true,
11+
"singleQuote": true,
12+
"tabWidth": 2,
13+
"trailingComma": "all",
14+
"useTabs": false
15+
}

README.md

+12-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# studiorack-app
2+
23
![Release](https://github.com/studiorack/studiorack-app/workflows/Release/badge.svg)
34

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

1819
StudioRack App was built using:
1920

20-
* NodeJS 17.x
21-
* TypeScript 4.x
22-
* NextJS 12.x
23-
* React 17.x
24-
* Electron 15.x
25-
21+
- NodeJS 20.x
22+
- TypeScript 5.x
23+
- NextJS 14.x
24+
- React 18.x
25+
- Electron
2626

2727
## Installation
2828

2929
Install dependencies using:
3030

3131
npm install
3232

33-
3433
## Usage
3534

3635
Run the development server using:
3736

3837
npm run dev
3938

40-
View the app in the application window opened automatically
39+
View the site at:
4140

41+
http://localhost:3000
42+
43+
Get the api at:
44+
45+
http://localhost:3000/api/plugins
4246

4347
## Deployment
4448

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

5256
.github/workflows/release.yml
5357

54-
5558
## Contact
5659

5760
For more information please contact kmturley

electron-src/api.ts

+13-13
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,52 @@
11
import { ipcRenderer } from 'electron';
2-
import { PluginInterface } from '@studiorack/core';
2+
import { PluginVersion, PluginVersionLocal, ProjectVersionLocal, ProjectVersionPlugins } from '@studiorack/core';
33

4-
function message(val: any) {
4+
function message(val: string | object) {
55
return ipcRenderer.send('message', val);
66
}
77

8-
async function pluginsGetLocal(): Promise<any> {
8+
async function pluginsGetLocal(): Promise<PluginVersionLocal[]> {
99
return ipcRenderer.invoke('pluginsGetLocal');
1010
}
1111

12-
async function pluginGetLocal(id: string): Promise<any> {
12+
async function pluginGetLocal(id: string): Promise<PluginVersionLocal> {
1313
return ipcRenderer.invoke('pluginGetLocal', id);
1414
}
1515

16-
async function pluginInstall(plugin: PluginInterface): Promise<any> {
16+
async function pluginInstall(plugin: PluginVersion): Promise<PluginVersionLocal> {
1717
console.log('pluginInstall api', plugin);
1818
return ipcRenderer.invoke('pluginInstall', plugin);
1919
}
2020

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

25-
async function pluginUninstall(plugin: PluginInterface): Promise<any> {
25+
async function pluginUninstall(plugin: PluginVersion): Promise<PluginVersionLocal> {
2626
return ipcRenderer.invoke('pluginUninstall', plugin);
2727
}
2828

29-
async function projectsGetLocal(): Promise<any> {
29+
async function projectsGetLocal(): Promise<ProjectVersionLocal[]> {
3030
return ipcRenderer.invoke('projectsGetLocal');
3131
}
3232

33-
async function projectGetLocal(id: string): Promise<any> {
33+
async function projectGetLocal(id: string): Promise<ProjectVersionLocal> {
3434
return ipcRenderer.invoke('projectGetLocal', id);
3535
}
3636

37-
async function projectOpen(path: string): Promise<any> {
37+
async function projectOpen(path: string): Promise<ProjectVersionLocal> {
3838
return ipcRenderer.invoke('projectOpen', path);
3939
}
4040

41-
async function folderSelect(path: string): Promise<any> {
41+
async function folderSelect(path: string): Promise<Electron.OpenDialogReturnValue> {
4242
return ipcRenderer.invoke('folderSelect', path);
4343
}
4444

45-
async function storeGet(key: string): Promise<any> {
45+
async function storeGet(key: string): Promise<string> {
4646
return ipcRenderer.invoke('storeGet', key);
4747
}
4848

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

electron-src/index.ts

+22-20
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ import { parse } from 'url';
66
import { BrowserWindow, app, dialog, session, ipcMain, IpcMainEvent, protocol } from 'electron';
77
import fixPath from 'fix-path';
88
import isDev from 'electron-is-dev';
9-
import { createServer } from 'http';
10-
import next from 'next';
9+
import { createServer as createServerHttp, IncomingMessage, ServerResponse } from 'http';
10+
import createServer from 'next/dist/server/next.js';
1111

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

1515
// custom code
1616
import {
1717
fileOpen,
18-
PluginInterface,
18+
PluginVersion,
1919
pluginGetLocal,
2020
pluginInstall,
2121
pluginsGetLocal,
@@ -25,14 +25,16 @@ import {
2525
configGet,
2626
ConfigInterface,
2727
configSet,
28+
ProjectVersionPlugins,
2829
} from '@studiorack/core';
2930

3031
const DEFAULT_PAGE = 'projects';
3132

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

4446
// Create a new native HTTP server (which supports hot code reloading)
45-
createServer((req: any, res: any) => {
46-
const parsedUrl = parse(req.url, true);
47+
createServerHttp((req: IncomingMessage, res: ServerResponse) => {
48+
const parsedUrl = parse(req.url ? req.url : '', true);
4749
requestHandler(req, res, parsedUrl);
4850
}).listen(3000, () => {
4951
console.log('> Ready on http://localhost:3000');
@@ -68,13 +70,13 @@ app.on('ready', async () => {
6870
'Content-Security-Policy': [
6971
`
7072
default-src 'self' *.youtube.com;
71-
connect-src 'self' *.github.io data: *.google-analytics.com;
73+
connect-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.google-analytics.com *.doubleclick.net *.google.com *.googleapis.com data:;
7274
font-src 'self' fonts.gstatic.com;
73-
img-src 'self' github.com *.githubusercontent.com *.s3.amazonaws.com *.youtube.com data: media:;
74-
media-src 'self' github.com *.githubusercontent.com *.s3.amazonaws.com *.youtube.com media:;
75+
img-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.s3.amazonaws.com *.youtube.com *.ytimg.com data: media:;
76+
media-src 'self' github.com *.github.com *.github.io *.githubusercontent.com *.s3.amazonaws.com *.youtube.com media:;
7577
object-src 'none';
76-
script-src 'self' 'unsafe-inline' 'unsafe-eval' *.doubleclick.net *.google.com *.gstatic.com *.googletagmanager.com *.google-analytics.com;
77-
style-src 'self' 'unsafe-inline' fonts.googleapis.com
78+
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;
79+
style-src 'self' 'unsafe-inline' github.com *.github.com *.github.io *.githubusercontent.com fonts.googleapis.com
7880
`,
7981
],
8082
},
@@ -85,7 +87,8 @@ app.on('ready', async () => {
8587
width: isDev ? 1024 + 445 : 1024,
8688
height: 768,
8789
webPreferences: {
88-
preload: join(app.getAppPath(), 'main', 'preload.js'),
90+
sandbox: false,
91+
preload: join(app.getAppPath(), 'main', 'preload.mjs'),
8992
},
9093
});
9194

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

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

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

120123
// Install plugin into root plugin folder locally
121-
ipcMain.handle('pluginInstall', async (_event, plugin: PluginInterface) => {
124+
ipcMain.handle('pluginInstall', async (_event, plugin: PluginVersion) => {
122125
console.log('pluginInstall index', plugin);
123-
return await pluginInstall(`${plugin.repo}/${plugin.id}`, plugin.version);
126+
return await pluginInstall(plugin.id || '', plugin.version);
124127
});
125128

126129
// Install plugin into root plugin folder locally
127-
ipcMain.handle('pluginsInstall', async (_event, plugins: any) => {
130+
ipcMain.handle('pluginsInstall', async (_event, plugins: ProjectVersionPlugins) => {
128131
console.log('pluginsInstall', plugins);
129132
const promises = Object.keys(plugins).map((pluginId: string) => {
130-
const plugin = plugins[pluginId];
131-
return pluginInstall(`${plugin.repo}/${plugin.id}`, plugin.version);
133+
return pluginInstall(pluginId, plugins[pluginId]);
132134
});
133135
return Promise.all(promises);
134136
});
135137

136138
// Uninstall plugin from root plugin folder locally
137139
ipcMain.handle('pluginUninstall', async (_event, plugin) => {
138140
console.log('pluginUninstall', plugin);
139-
return await pluginUninstall(`${plugin.repo}/${plugin.id}`, plugin.version);
141+
return await pluginUninstall(plugin.id || '', plugin.version);
140142
});
141143

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

180182
// Set user-specific setting
181-
ipcMain.handle('storeSet', async (_event, key: keyof ConfigInterface, val: any) => {
183+
ipcMain.handle('storeSet', async (_event, key: keyof ConfigInterface, val: string | object) => {
182184
console.log('storeSet', key, val);
183185
if (!key || !val) return;
184186
return configSet(key, val);

electron-src/preload.mjs

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// This file is intentionally .mjs to ensure Electron treats it as an ES module.
2+
// https://www.electronjs.org/docs/latest/tutorial/esm
3+
import { contextBridge } from 'electron';
4+
import api from './api.js';
5+
6+
contextBridge.exposeInMainWorld('electronAPI', api);

electron-src/preload.ts

-4
This file was deleted.

0 commit comments

Comments
 (0)