Skip to content
Draft
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ combined.log
error.log
assets/build/snap-hooks
test-results/
src/esm-bundle.cjs
src/esm-bundle.cjs.map
1 change: 1 addition & 0 deletions .npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
legacy-peer-deps=true
23,370 changes: 7,036 additions & 16,334 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@
"lint:fix": "ts-standard --fix && standard --fix",
"test": "cross-env NODE_ENV=test playwright test 'test/unit/.*.spec.js'",
"test:e2e": "xvfb-maybe cross-env NODE_ENV=test playwright test -c test/e2e/playwright.config.js",
"postinstall": "run-s install-app-deps patch-deps macos-universal-kubo",
"postinstall": "run-s install-app-deps patch-deps bundle-esm macos-universal-kubo",
"bundle-esm": "node scripts/bundle-esm.js",
"install-app-deps": "electron-builder install-app-deps",
"macos-universal-kubo": "node pkgs/macos/build-universal-kubo-binary.js",
"patch-deps": "patch-package",
Expand Down Expand Up @@ -47,13 +48,18 @@
"devDependencies": {
"@electron/notarize": "^1.2.3",
"@ipfs-shipyard/release-please-ipfs-plugin": "^1.0.0",
"@multiformats/multiaddr": "^13.0.0",
"@multiformats/multiaddr-to-uri": "^12.0.0",
"@playwright/test": "^1.50.0",
"cross-env": "^7.0.3",
"dotenv": "^16.0.0",
"electron": "^39.2.4",
"electron-builder": "26.0.11",
"esbuild": "^0.27.2",
"got": "^12.0.3",
"ipfs-or-gateway": "^4.1.0",
"ipfsd-ctl": "^16.0.0",
"kubo-rpc-client": "^6.0.0",
"npm-run-all": "^4.1.5",
"patch-package": "^6.5.1",
"playwright": "^1.51.1",
Expand All @@ -78,21 +84,17 @@
"i18next-fs-backend": "1.1.4",
"i18next-icu": "^2.0.3",
"intl-messageformat": "^9.13.0",
"ipfs-http-client": "56.0.2",
"ipfs-utils": "^9.0.10",
"ipfsd-ctl": "10.0.6",
"it-last": "^1.0.6",
"kubo": "0.39.0",
"multiaddr": "10.0.1",
"multiaddr-to-uri": "8.0.0",
"portfinder": "^1.0.32",
"untildify": "^4.0.0",
"v8-compile-cache": "^2.4.0",
"winston": "^3.7.2"
},
"standard": {
"ignore": [
"**/*.ts"
"**/*.ts",
"src/esm-bundle.cjs"
]
},
"ts-standard": {
Expand Down
28 changes: 0 additions & 28 deletions patches/ipfsd-ctl+10.0.6.patch

This file was deleted.

48 changes: 0 additions & 48 deletions patches/multiaddr+10.0.1.patch

This file was deleted.

37 changes: 37 additions & 0 deletions scripts/bundle-esm.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#!/usr/bin/env node
/**
* Bundle ESM-only dependencies into CommonJS for Electron compatibility.
*
* Electron's main process doesn't support dynamic import() properly,
* so we pre-bundle the ESM modules into a single CJS file.
*/
const esbuild = require('esbuild')
const path = require('path')

const outfile = path.join(__dirname, '..', 'src', 'esm-bundle.cjs')

async function build () {
await esbuild.build({
entryPoints: [path.join(__dirname, 'esm-entry.mjs')],
bundle: true,
platform: 'node',
target: 'node20',
format: 'cjs',
outfile,
external: [
'electron',
// Native modules that shouldn't be bundled
'bufferutil',
'utf-8-validate'
],
// Don't minify for debuggability
minify: false,
sourcemap: true
})
console.log(`Bundled ESM modules to ${outfile}`)
}

build().catch(err => {
console.error('Bundle failed:', err)
process.exit(1)
})
8 changes: 8 additions & 0 deletions scripts/esm-entry.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* ESM entry point for bundling.
* Exports all the ESM-only modules we need.
*/
export { createNode, createFactory } from 'ipfsd-ctl'
export { create, globSource } from 'kubo-rpc-client'
export { multiaddr } from '@multiformats/multiaddr'
export { multiaddrToUri } from '@multiformats/multiaddr-to-uri'
3 changes: 2 additions & 1 deletion src/add-to-ipfs.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { extname, basename } = require('path')
const { clipboard } = require('electron')
const { globSource } = require('ipfs-http-client')
const i18n = require('i18next')
const { getModules } = require('./esm-loader')
const last = require('it-last')
const fs = require('fs-extra')
const logger = require('./common/logger')
Expand Down Expand Up @@ -90,6 +90,7 @@ async function addFileOrDirectory (ipfs, filepath) {
let cid = null

if (stat.isDirectory()) {
const { globSource } = getModules()
const files = globSource(filepath, '**/*', { recursive: true, cidVersion: 1 })
const res = await last(ipfs.addAll(files, {
pin: false,
Expand Down
20 changes: 17 additions & 3 deletions src/context.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
// @ts-check
const pDefer = require('p-defer')
const logger = require('./common/logger')

/**
* Creates a deferred promise (p-defer inline replacement)
* @template T
* @returns {{ promise: Promise<T>, resolve: (value: T) => void, reject: (reason?: unknown) => void }}
*/
function pDefer () {
/** @type {{ promise: Promise<T>, resolve: (value: T) => void, reject: (reason?: unknown) => void }} */
const deferred = /** @type {any} */ ({})
deferred.promise = new Promise((resolve, reject) => {
deferred.resolve = resolve
deferred.reject = reject
})
return deferred
}

/**
* @typedef { 'tray' | 'tray.update-menu' | 'countlyDeviceId' | 'manualCheckForUpdates' | 'startIpfs' | 'stopIpfs' | 'restartIpfs' | 'getIpfsd' | 'launchWebUI' | 'webui' | 'splashScreen' | 'i18n.initDone' } ContextProperties
*/
Expand Down Expand Up @@ -38,7 +52,7 @@ class Context {

/**
* Stores prop->Promise mappings.
* @type {Map<string|symbol, pDefer.DeferredPromise<unknown>>}
* @type {Map<string|symbol, ReturnType<typeof pDefer<unknown>>>}
*/
this._promiseMap = new Map()
}
Expand Down Expand Up @@ -137,7 +151,7 @@ class Context {
* @private
* @template T
* @param {ContextProperties} propertyName
* @returns {pDefer.DeferredPromise<T>}
* @returns {ReturnType<typeof pDefer<T>>}
*/
_createDeferredForProp (propertyName) {
let deferred = this._promiseMap.get(propertyName)
Expand Down
Loading
Loading