Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@
*
* This is also true for any additional architecture beyond whatever macos supports.
*/
const { packager } = require("@electron/packager");
const { rebuild } = require("@electron/rebuild");
const path = require("path");
import { packager } from "@electron/packager";
import { rebuild } from "@electron/rebuild";
import path from "path";

// These arguments are provided by build.sh
const srcDir = process.argv[2];
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"name": "Chronicles",
"version": "1.0.0",
"main": "main.bundle.js",
"main": "main.bundle.mjs",
"engines": {
"node": ">=22.0.0"
},
"type": "module",
"scripts": {
"build": "./build.sh",
"lint": "yarn run lint:prettier:check && yarn run lint:types:check",
Expand All @@ -16,14 +17,14 @@
"prebuild": "yarn run lint && tailwindcss -i ./src/index.css -o ./src/index-compiled.css && node ./scripts/icons.js",
"start": "node ./scripts/dev.mjs",
"pretest": "node ./scripts/test.mjs",
"test": "mocha 'src/**/*.test.bundle.js'"
"test": "mocha 'src/**/*.test.bundle.mjs'"
},
"dependencies": {
"@ariakit/react": "^0.4.8",
"ajv": "^8.6.2",
"ajv-formats": "^2.1.0",
"better-sqlite3": "^12.1.1",
"electron-store": "^8.0.1",
"electron-store": "^10.1.0",
"knex": "^2.5.0",
"sharp": "^0.33.5",
"uuid25": "^0.1.5",
Expand Down
9 changes: 5 additions & 4 deletions scripts/dev.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ let eprocess;
function startElectron() {
console.log("starting electron");
checkTypes();
eprocess = cp.spawn(`${electron}`, ["src/main.bundle.js"], {
eprocess = cp.spawn(`${electron}`, ["src/main.bundle.mjs"], {
stdio: "inherit",
});

Expand All @@ -68,7 +68,7 @@ const restartElectron = lodash.debounce(function startElectron() {
// is incremental or something, rather than a fresh sub-process)
checkTypes();
console.log("restarting electron");
eprocess = cp.spawn(`${electron}`, ["src/main.bundle.js"], {
eprocess = cp.spawn(`${electron}`, ["src/main.bundle.mjs"], {
stdio: "inherit",
});

Expand Down Expand Up @@ -127,10 +127,11 @@ async function watchPreload() {

async function watchMain() {
const ctxMain = await esbuild.context({
entryPoints: ["src/electron/index.js"],
outfile: "src/main.bundle.js",
entryPoints: ["src/electron/index.ts"],
outfile: "src/main.bundle.mjs",
bundle: true,
platform: "node",
format: "esm",
external: ["electron", "electron-store", "better-sqlite3"],
plugins: [startElectronPlugin("main")],
});
Expand Down
8 changes: 4 additions & 4 deletions scripts/icons.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
const sharp = require("sharp");
import sharp from "sharp";
// https://github.com/akabekobeko/npm-icon-gen
const iconGen = require("icon-gen");
const path = require("path");
const fs = require("fs");
import fs from "fs";
import iconGen from "icon-gen";
import path from "path";

/**
* This file is used to generate icons for the app based off of an input asset. Not much
Expand Down
12 changes: 7 additions & 5 deletions scripts/production.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const esbuild = require("esbuild");
import esbuild from "esbuild";

// After successful build, log results
function afterBuild(name) {
Expand All @@ -20,8 +20,9 @@ function afterBuild(name) {
// build renderer bundle
esbuild.build({
entryPoints: ["src/index.tsx"],
outfile: "src/renderer.bundle.js",
outfile: "src/renderer.bundle.mjs",
bundle: true,
format: "esm",
platform: "browser",
plugins: [afterBuild("renderer")],
loader: {
Expand All @@ -40,15 +41,16 @@ esbuild.build({
bundle: true,
platform: "node",
format: "esm",
external: ["knex", "electron", "electron-store", "better-sqlite3"],
external: ["knex", "electron", "electron-store", "better-sqlite3", "sharp"],
plugins: [afterBuild("preload")],
});

// build electron main bundle
esbuild.build({
entryPoints: ["src/electron/index.js"],
outfile: "src/main.bundle.js",
entryPoints: ["src/electron/index.ts"],
outfile: "src/main.bundle.mjs",
bundle: true,
format: "esm",
platform: "node",
external: ["electron", "electron-store", "better-sqlite3"],
plugins: [afterBuild("main")],
Expand Down
8 changes: 6 additions & 2 deletions scripts/set-packaged-version.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
// ./scripts/set-packaged-version.js
const fs = require("fs");
const path = require("path");
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const inferVersionFromEnv = () => {
const tag = process.env.GIT_TAG || "0.0.0";
Expand Down
3 changes: 2 additions & 1 deletion scripts/test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,9 @@ testFiles.forEach(async (file) => {
entryPoints: [file],
// NOTE: If changing filename, also update findTestFiles glob above to avoid
// bundled test files being used as source!
outfile: file.replace(".test.ts", ".test.bundle.js"),
outfile: file.replace(".test.ts", ".test.bundle.mjs"),
bundle: true,
format: "esm",
platform: "node",
external: ["mocha"],
plugins: [],
Expand Down
12 changes: 7 additions & 5 deletions src/electron/ensureDir.js → src/electron/ensureDir.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
const fs = require("fs");
import fs from "fs";

/**
* Borrowed from api files, since its typescript and this is not
* Reconcile that later
*/
exports.ensureDir = function ensureDir(directory, create = true) {
export function ensureDir(directory: string, create = true) {
if (!directory) {
throw new Error("ensureDir called with no directory path");
}
Expand All @@ -17,16 +17,18 @@ exports.ensureDir = function ensureDir(directory, create = true) {
);
}
} catch (err) {
if (err.code !== "ENOENT") throw err;
if (err instanceof Error && "code" in err && err.code !== "ENOENT")
throw err;
try {
fs.mkdirSync(directory, { recursive: true });
} catch (err) {
if (err.code !== "EEXIST") throw err;
if (err instanceof Error && "code" in err && err.code !== "EEXIST")
throw err;
}
}

// NOTE: Documentation suggests Windows may report ok here, but then choke
// when actually writing. Better to move this logic to the actual file
// upload handlers.
fs.accessSync(directory, fs.constants.R_OK | fs.constants.W_OK);
};
}
73 changes: 42 additions & 31 deletions src/electron/index.js → src/electron/index.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
const {
app,
import {
BrowserWindow,
ipcMain,
shell,
Menu,
MenuItem,
app,
dialog,
ipcMain,
protocol,
Menu,
MenuItemConstructorOptions,
} = require("electron");
const path = require("path");
const fs = require("fs");
const url = require("url");
const { initUserFilesDir } = require("./userFilesInit");
const settings = require("./settings");
const migrate = require("./migrations");
const { ensureDir } = require("./ensureDir");
shell,
} from "electron";
import fs from "fs";
import path from "path";
import url, { fileURLToPath } from "url";
import { ensureDir } from "./ensureDir.js";
import migrate from "./migrations/index.js";
import settings from "./settings.js";
import { initUserFilesDir } from "./userFilesInit.js";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// when packaged, it should be in Library/Application Support/Chronicles/settings.json
// when in dev, Library/Application Support/Chronicles/settings.json
initUserFilesDir(app.getPath("userData"));
console.log("application settings at startup:", settings.store);

const DATABASE_URL = "DATABASE_URL";

// Used by createWindow, but needed in database routine because of the filepicker call
let mainWindow;
let mainWindow: BrowserWindow | null = null;

function setupDefaultDatabaseUrl() {
let dbUrl = settings.get(DATABASE_URL);
let dbUrl = settings.get("databaseUrl");
if (!dbUrl) {
dbUrl = path.join(app.getPath("userData"), "chronicles.db");
settings.set(DATABASE_URL, dbUrl);
settings.set("databaseUrl", dbUrl);
}

return dbUrl;
Expand All @@ -54,7 +55,10 @@ ipcMain.handle("setup-database", async (event, dbUrl) => {
return { success: true };
} catch (err) {
console.error(`Error migrating the database using url: ${dbUrl}:`, err);
return { success: false, error: err.message };
return {
success: false,
error: err instanceof Error ? err.message : "Unknown error",
};
}
});

Expand All @@ -64,7 +68,12 @@ app.whenReady().then(() => {
// todo: registerFileProtocol is deprecated; using the new protocol method works,
// but videos don't seek properly.
protocol.registerFileProtocol("chronicles", (request, callback) => {
callback({ path: validateChroniclesUrl(request.url) });
const path = validateChroniclesUrl(request.url);
if (path) {
callback({ path });
} else {
callback({ path: undefined });
}
});
});

Expand All @@ -78,7 +87,7 @@ app.whenReady().then(() => {
*
* @param {string} chroniclesUrl The "chronicles://" URL to convert
*/
function validateChroniclesUrl(chroniclesUrl) {
function validateChroniclesUrl(chroniclesUrl: string) {
// NOTE: chroniclesUrl SHOULD start with chronicles://../_attachments/<filename>
// NOTE: UI should also validate this, to tell user how to fix (if it comes up)
if (!chroniclesUrl?.startsWith("chronicles://../_attachments")) {
Expand Down Expand Up @@ -126,7 +135,7 @@ function validateChroniclesUrl(chroniclesUrl) {
}

// Checks if the resolved path is within the specified directory
function isPathWithinDirectory(resolvedPath, directory) {
function isPathWithinDirectory(resolvedPath: string, directory: string) {
const relative = path.relative(directory, resolvedPath);
return !relative.startsWith("..") && !path.isAbsolute(relative);
}
Expand All @@ -136,7 +145,7 @@ function isPathWithinDirectory(resolvedPath, directory) {
* @param {string} urlString The URL to check.
* @returns {boolean} True if the URL is considered safe, false otherwise.
*/
function isSafeForExternalOpen(urlString) {
function isSafeForExternalOpen(urlString: string) {
try {
const parsedUrl = new url.URL(urlString);

Expand All @@ -156,7 +165,7 @@ function isSafeForExternalOpen(urlString) {
* Handle opening web and file links in system default applications.
* @param {string} url
*/
function handleLinkClick(url) {
function handleLinkClick(url: string) {
if (url.startsWith("chronicles://")) {
const sanitized = validateChroniclesUrl(url);
if (sanitized) {
Expand Down Expand Up @@ -214,7 +223,7 @@ function createWindow() {
mainWindow.loadFile("index.html");
mainWindow.once("ready-to-show", () => {
if (!process.env.HEADLESS) {
mainWindow.show();
mainWindow?.show();
}
});

Expand All @@ -236,18 +245,20 @@ function createWindow() {
* DevTools.
* @param {Electron.Main.BrowserWindow} mainWindow
*/
function setupInspectElement(mainWindow) {
function setupInspectElement(mainWindow: BrowserWindow) {
// type is MenuItemConstructorOptions[]
let rightClickPosition;
const contextMenuTemplate = [
let rightClickPosition: { x: number; y: number } | null = null;
const contextMenuTemplate: any[] = [
// todo: MenuItemConstructorOptions[]
{
label: "Inspect Element",
click: (item, focusedWindow) => {
if (focusedWindow)
click: (item: MenuItem, focusedWindow?: BrowserWindow) => {
if (focusedWindow && rightClickPosition) {
focusedWindow.webContents.inspectElement(
rightClickPosition.x,
rightClickPosition.y,
);
}
},
},
];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
const fs = require("fs");
const path = require("path");
const DB = require("better-sqlite3");
import DB from "better-sqlite3";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// A hacky "migration" script after bailing on Prisma and realizing
// better-sqlite3 is not compatible with knex yet :|
// https://github.com/knex/knex/issues/4511
// todo: real migrations, backup database while migrating
module.exports = function (dbUrl) {
export default function (dbUrl: string) {
const db = DB(dbUrl);

try {
Expand All @@ -23,4 +27,4 @@ module.exports = function (dbUrl) {
console.error("Error running migrations!", err);
throw err;
}
};
}
8 changes: 0 additions & 8 deletions src/electron/settings.js

This file was deleted.

Loading