Browse Source

docs: move build instructions from README to BUILDING.md

- Move detailed setup and build instructions from README.md to BUILDING.md
- Add concise reference to BUILDING.md in README.md
- Keep testing and other documentation in README.md
- Improve organization of documentation by separating build-specific content
pull/126/head
Matthew Raymer 1 week ago
parent
commit
4e0f9235cd
  1. 74
      README.md
  2. 70
      src/electron/main.js
  3. 41
      src/electron/preload.js
  4. 15
      src/registerServiceWorker.ts
  5. 2
      src/router/index.ts
  6. 13
      src/vite.config.utils.js

74
README.md

@ -8,79 +8,9 @@ and expand to crowd-fund with time & money, then record and see the impact of co
See [project.task.yaml](project.task.yaml) for current priorities.
(Numbers at the beginning of lines are estimated hours. See [taskyaml.org](https://taskyaml.org/) for details.)
## Setup
We like pkgx: `sh <(curl https://pkgx.sh) +vite sh`
```
npm install
```
### Compile and hot-reloads for development
```
npm run dev
```
See the test locations for "IMAGE_API_SERVER" or "PARTNER_API_SERVER" below, or use http://localhost:3000 for local endorser.ch
### Build the test & production app
```
npm run serve
```
### Lint and fix files
```
npm run lint
```
### Run all UI tests
Look below for the "test-all" instructions.
### Compile and minify for test & production
* If there are DB changes: before updating the test server, open browser(s) with current version to test DB migrations.
* `npx prettier --write ./sw_scripts/`
* Update the ClickUp tasks & CHANGELOG.md & the version in package.json, run `npm install`.
* Commit everything (since the commit hash is used the app).
* Put the commit hash in the changelog (which will help you remember to bump the version later).
* Tag with the new version, [online](https://gitea.anomalistdesign.com/trent_larson/crowd-funder-for-time-pwa/releases) or `git tag 0.3.36` && `git push origin 0.3.36`.
* For test, build the app (because test server is not yet set up to build):
```
TIME_SAFARI_APP_TITLE="TimeSafari_Test" VITE_APP_SERVER=https://test.timesafari.app VITE_BVC_MEETUPS_PROJECT_CLAIM_ID=https://endorser.ch/entity/01HWE8FWHQ1YGP7GFZYYPS272F VITE_DEFAULT_ENDORSER_API_SERVER=https://test-api.endorser.ch VITE_DEFAULT_IMAGE_API_SERVER=https://test-image-api.timesafari.app VITE_DEFAULT_PARTNER_API_SERVER=https://test-partner-api.endorser.ch VITE_PASSKEYS_ENABLED=true npm run build
```
... and transfer to the test server: `rsync -azvu -e "ssh -i ~/.ssh/..." dist ubuntutest@test.timesafari.app:time-safari`
(Let's replace that with a .env.development or .env.staging file.)
(Note: The test BVC_MEETUPS_PROJECT_CLAIM_ID does not resolve as a URL because it's only in the test DB and the prod redirect won't redirect there.)
* For prod, get on the server and run the correct build:
... and log onto the server:
* `pkgx +npm sh`
* `cd crowd-funder-for-time-pwa && git checkout master && git pull && git checkout 0.3.36 && npm install && npm run build && cd -`
(The plain `npm run build` uses the .env.production file.)
* Back up the time-safari/dist folder, then `mv time-safari/dist time-safari-dist-prev.0 && mv crowd-funder-for-time-pwa/dist time-safari/`
* Record the new hash in the changelog. Edit package.json to increment version & add "-beta", `npm install`, and commit. Also record what version is on production.
## Setup & Building
See [BUILDING.md](BUILDING.md) for detailed build and setup instructions.
## Tests

70
src/electron/main.js

@ -3,13 +3,13 @@ const path = require("path");
const fs = require("fs");
// Check if running in dev mode
const isDev = process.argv.includes('--inspect');
const isDev = process.argv.includes("--inspect");
function createWindow() {
// Add before createWindow function
const preloadPath = path.join(__dirname, 'preload.js');
console.log('Checking preload path:', preloadPath);
console.log('Preload exists:', fs.existsSync(preloadPath));
const preloadPath = path.join(__dirname, "preload.js");
console.log("Checking preload path:", preloadPath);
console.log("Preload exists:", fs.existsSync(preloadPath));
// Create the browser window.
const mainWindow = new BrowserWindow({
@ -20,7 +20,7 @@ function createWindow() {
contextIsolation: true,
webSecurity: true,
allowRunningInsecureContent: false,
preload: path.join(__dirname, 'preload.js')
preload: path.join(__dirname, "preload.js"),
},
});
@ -33,30 +33,32 @@ function createWindow() {
console.log("__dirname:", __dirname);
console.log("process.cwd():", process.cwd());
const indexPath = path.join(__dirname, 'www', 'index.html');
console.log("www path:", path.join(__dirname, 'www'));
console.log("www assets path:", path.join(__dirname, 'www', 'assets'));
const indexPath = path.join(__dirname, "www", "index.html");
console.log("www path:", path.join(__dirname, "www"));
console.log("www assets path:", path.join(__dirname, "www", "assets"));
if (!fs.existsSync(indexPath)) {
console.error(`Index file not found at: ${indexPath}`);
throw new Error('Index file not found');
throw new Error("Index file not found");
}
// Set CSP headers
mainWindow.webContents.session.webRequest.onHeadersReceived((details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
'Content-Security-Policy': [
"default-src 'self';" +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;" +
"font-src 'self' https://fonts.gstatic.com;" +
"script-src 'self' 'unsafe-eval' 'unsafe-inline';" +
"img-src 'self' data: https:;"
]
}
});
});
mainWindow.webContents.session.webRequest.onHeadersReceived(
(details, callback) => {
callback({
responseHeaders: {
...details.responseHeaders,
"Content-Security-Policy": [
"default-src 'self';" +
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com;" +
"font-src 'self' https://fonts.gstatic.com;" +
"script-src 'self' 'unsafe-eval' 'unsafe-inline';" +
"img-src 'self' data: https:;",
],
},
});
},
);
// Load the index.html
mainWindow
@ -79,17 +81,23 @@ function createWindow() {
});
// Add right after creating the BrowserWindow
mainWindow.webContents.on('did-fail-load', (event, errorCode, errorDescription) => {
console.error('Page failed to load:', errorCode, errorDescription);
});
mainWindow.webContents.on(
"did-fail-load",
(event, errorCode, errorDescription) => {
console.error("Page failed to load:", errorCode, errorDescription);
},
);
mainWindow.webContents.on('preload-error', (event, preloadPath, error) => {
console.error('Preload script error:', preloadPath, error);
mainWindow.webContents.on("preload-error", (event, preloadPath, error) => {
console.error("Preload script error:", preloadPath, error);
});
mainWindow.webContents.on('console-message', (event, level, message, line, sourceId) => {
console.log('Renderer Console:', message);
});
mainWindow.webContents.on(
"console-message",
(event, level, message, line, sourceId) => {
console.log("Renderer Console:", line, sourceId, message);
},
);
// Enable remote debugging when in dev mode
if (isDev) {

41
src/electron/preload.js

@ -1,39 +1,40 @@
const { contextBridge, ipcRenderer } = require('electron');
const { contextBridge, ipcRenderer } = require("electron");
// Use a more direct path resolution approach
const getPath = (pathType) => {
switch(pathType) {
case 'userData':
return process.env.APPDATA || (
process.platform === 'darwin'
switch (pathType) {
case "userData":
return (
process.env.APPDATA ||
(process.platform === "darwin"
? `${process.env.HOME}/Library/Application Support`
: `${process.env.HOME}/.local/share`
: `${process.env.HOME}/.local/share`)
);
case 'home':
case "home":
return process.env.HOME;
case 'appPath':
case "appPath":
return process.resourcesPath;
default:
return '';
return "";
}
};
console.log('Preload script starting...');
console.log("Preload script starting...");
try {
contextBridge.exposeInMainWorld('electronAPI', {
contextBridge.exposeInMainWorld("electronAPI", {
// Path utilities
getPath,
// IPC functions
send: (channel, data) => {
const validChannels = ['toMain'];
const validChannels = ["toMain"];
if (validChannels.includes(channel)) {
ipcRenderer.send(channel, data);
}
},
receive: (channel, func) => {
const validChannels = ['fromMain'];
const validChannels = ["fromMain"];
if (validChannels.includes(channel)) {
ipcRenderer.on(channel, (event, ...args) => func(...args));
}
@ -41,15 +42,15 @@ try {
// Environment info
env: {
isElectron: true,
isDev: process.env.NODE_ENV === 'development'
isDev: process.env.NODE_ENV === "development",
},
// Path utilities
getBasePath: () => {
return process.env.NODE_ENV === 'development' ? '/' : './';
}
return process.env.NODE_ENV === "development" ? "/" : "./";
},
});
console.log('Preload script completed successfully');
console.log("Preload script completed successfully");
} catch (error) {
console.error('Error in preload script:', error);
}
console.error("Error in preload script:", error);
}

15
src/registerServiceWorker.ts

@ -3,7 +3,10 @@
import { register } from "register-service-worker";
// Only register service worker if explicitly enabled and in production
if (process.env.VITE_PWA_ENABLED === 'true' && process.env.NODE_ENV === "production") {
if (
process.env.VITE_PWA_ENABLED === "true" &&
process.env.NODE_ENV === "production"
) {
register(`${process.env.BASE_URL}sw.js`, {
ready() {
console.log("Service worker is active.");
@ -21,12 +24,16 @@ if (process.env.VITE_PWA_ENABLED === 'true' && process.env.NODE_ENV === "product
console.log("New content is available; please refresh.");
},
offline() {
console.log("No internet connection found. App is running in offline mode.");
console.log(
"No internet connection found. App is running in offline mode.",
);
},
error(error) {
console.error("Error during service worker registration:", error);
}
},
});
} else {
console.log("Service worker registration skipped - not enabled or not in production");
console.log(
"Service worker registration skipped - not enabled or not in production",
);
}

2
src/router/index.ts

@ -286,7 +286,7 @@ const routes: Array<RouteRecordRaw> = [
const isElectron = window.location.protocol === "file:";
const initialPath = isElectron
? window.location.pathname.split('/dist-electron/www/')[1] || '/'
? window.location.pathname.split("/dist-electron/www/")[1] || "/"
: window.location.pathname;
const history = isElectron

13
src/vite.config.utils.js

@ -1,6 +1,6 @@
import * as path from "path";
import { promises as fs } from "fs";
import { fileURLToPath } from 'url';
import { fileURLToPath } from "url";
export async function loadAppConfig() {
const packageJson = await loadPackageJson();
@ -34,15 +34,16 @@ export async function loadAppConfig() {
sizes: "512x512",
type: "image/png",
purpose: "maskable",
}
]
}
},
],
},
},
aliasConfig: {
"@": path.resolve(path.dirname(__dirname), "src"),
buffer: path.resolve(path.dirname(__dirname), "node_modules", "buffer"),
"dexie-export-import/dist/import": "dexie-export-import/dist/import/index.js",
}
"dexie-export-import/dist/import":
"dexie-export-import/dist/import/index.js",
},
};
}

Loading…
Cancel
Save