Cleanup Electron App + Dependency Update (#139)
* electron: clean-up / remove unused code in main process, including: - remove native plugin init (no longer supported) - remove auto-js-ipfs (used in render process) - remove ipfs handling logic (handled in render process) - use custom file2:// scheme for loading files, instead of custom prefix - proxyLive supports POST requests, using original UA (if set, for archiveweb.page) - webpack: remove unused __IPFS_CORE_URL__ - ci: add lint check * dependency update: - update to wabac.js 2.13.15 for latest auto-js-ipfs (2.1.0) and wombat (3.3.13) - update to electron 22.0 - update webpack + electron updater to latest * bump to 1.7.8
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
name: Build + Lint
|
||||||
|
|
||||||
|
on: push
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Check out Git repository
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: Install Node.js, NPM and Yarn
|
||||||
|
uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 18
|
||||||
|
cache: 'yarn'
|
||||||
|
|
||||||
|
- name: Yarn Install
|
||||||
|
run: yarn install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Yarn Lint
|
||||||
|
run: yarn run lint
|
||||||
|
|
||||||
|
- name: Yarn Build
|
||||||
|
run: yarn run build
|
||||||
+9
-8
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "replaywebpage",
|
"name": "replaywebpage",
|
||||||
"productName": "ReplayWeb.page",
|
"productName": "ReplayWeb.page",
|
||||||
"version": "1.7.7",
|
"version": "1.7.8",
|
||||||
"description": "Serverless Web Archive Replay",
|
"description": "Serverless Web Archive Replay",
|
||||||
"repository": "https://github.com/webrecorder/replayweb.page",
|
"repository": "https://github.com/webrecorder/replayweb.page",
|
||||||
"homepage": "https://replayweb.page/",
|
"homepage": "https://replayweb.page/",
|
||||||
@@ -9,11 +9,10 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||||
"@webrecorder/wabac": "^2.13.14",
|
"@webrecorder/wabac": "^2.13.15",
|
||||||
"auto-js-ipfs": "^1.5.1",
|
|
||||||
"bulma": "^0.9.3",
|
"bulma": "^0.9.3",
|
||||||
"electron-log": "^4.4.1",
|
"electron-log": "^4.4.1",
|
||||||
"electron-updater": "^4.3.9",
|
"electron-updater": "^5.3.0",
|
||||||
"fetch-ndjson": "^1.1.6",
|
"fetch-ndjson": "^1.1.6",
|
||||||
"flexsearch": "^0.7.21",
|
"flexsearch": "^0.7.21",
|
||||||
"keyword-mark-element": "^0.2.0",
|
"keyword-mark-element": "^0.2.0",
|
||||||
@@ -21,6 +20,7 @@
|
|||||||
"marked": "^4.0.10",
|
"marked": "^4.0.10",
|
||||||
"mime-types": "^2.1.32",
|
"mime-types": "^2.1.32",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
|
"node-fetch": "^3.3.0",
|
||||||
"pretty-bytes": "^5.6.0",
|
"pretty-bytes": "^5.6.0",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"querystring-es3": "^0.2.1",
|
"querystring-es3": "^0.2.1",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"copy-webpack-plugin": "^9.0.1",
|
"copy-webpack-plugin": "^9.0.1",
|
||||||
"css-loader": "^6.2.0",
|
"css-loader": "^6.2.0",
|
||||||
"electron": "^21.3.1",
|
"electron": "^22.0.0",
|
||||||
"electron-builder": "^23.0.3",
|
"electron-builder": "^23.0.3",
|
||||||
"electron-notarize": "^1.1.1",
|
"electron-notarize": "^1.1.1",
|
||||||
"eslint": "^8.23.1",
|
"eslint": "^8.23.1",
|
||||||
@@ -42,9 +42,10 @@
|
|||||||
"sass-loader": "^12.1.0",
|
"sass-loader": "^12.1.0",
|
||||||
"style-loader": "^3.2.1",
|
"style-loader": "^3.2.1",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"webpack": "^5.74.0",
|
"url": "^0.11.0",
|
||||||
"webpack-cli": "^4.8.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-dev-server": "^4.2.1"
|
"webpack-cli": "^5.0.1",
|
||||||
|
"webpack-dev-server": "^4.11.1"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"/assets",
|
"/assets",
|
||||||
|
|||||||
+9
-8
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "replaywebpage",
|
"name": "replaywebpage",
|
||||||
"productName": "ReplayWeb.page",
|
"productName": "ReplayWeb.page",
|
||||||
"version": "1.7.7",
|
"version": "1.7.8",
|
||||||
"description": "Serverless Web Archive Replay",
|
"description": "Serverless Web Archive Replay",
|
||||||
"repository": "https://github.com/webrecorder/replayweb.page",
|
"repository": "https://github.com/webrecorder/replayweb.page",
|
||||||
"homepage": "https://replayweb.page/",
|
"homepage": "https://replayweb.page/",
|
||||||
@@ -9,11 +9,10 @@
|
|||||||
"license": "AGPL-3.0-or-later",
|
"license": "AGPL-3.0-or-later",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^5.15.4",
|
"@fortawesome/fontawesome-free": "^5.15.4",
|
||||||
"@webrecorder/wabac": "^2.13.14",
|
"@webrecorder/wabac": "^2.13.15",
|
||||||
"auto-js-ipfs": "^1.5.1",
|
|
||||||
"bulma": "^0.9.3",
|
"bulma": "^0.9.3",
|
||||||
"electron-log": "^4.4.1",
|
"electron-log": "^4.4.1",
|
||||||
"electron-updater": "^4.3.9",
|
"electron-updater": "^5.3.0",
|
||||||
"fetch-ndjson": "^1.1.6",
|
"fetch-ndjson": "^1.1.6",
|
||||||
"flexsearch": "^0.7.21",
|
"flexsearch": "^0.7.21",
|
||||||
"keyword-mark-element": "^0.2.0",
|
"keyword-mark-element": "^0.2.0",
|
||||||
@@ -21,6 +20,7 @@
|
|||||||
"marked": "^4.0.10",
|
"marked": "^4.0.10",
|
||||||
"mime-types": "^2.1.32",
|
"mime-types": "^2.1.32",
|
||||||
"minimist": "^1.2.5",
|
"minimist": "^1.2.5",
|
||||||
|
"node-fetch": "^3.3.0",
|
||||||
"pretty-bytes": "^5.6.0",
|
"pretty-bytes": "^5.6.0",
|
||||||
"process": "^0.11.10",
|
"process": "^0.11.10",
|
||||||
"querystring-es3": "^0.2.1",
|
"querystring-es3": "^0.2.1",
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"copy-webpack-plugin": "^9.0.1",
|
"copy-webpack-plugin": "^9.0.1",
|
||||||
"css-loader": "^6.2.0",
|
"css-loader": "^6.2.0",
|
||||||
"electron": "^21.3.1",
|
"electron": "^22.0.0",
|
||||||
"electron-builder": "^23.0.3",
|
"electron-builder": "^23.0.3",
|
||||||
"electron-notarize": "^1.1.1",
|
"electron-notarize": "^1.1.1",
|
||||||
"eslint": "^8.23.1",
|
"eslint": "^8.23.1",
|
||||||
@@ -42,9 +42,10 @@
|
|||||||
"sass-loader": "^12.1.0",
|
"sass-loader": "^12.1.0",
|
||||||
"style-loader": "^3.2.1",
|
"style-loader": "^3.2.1",
|
||||||
"svg-inline-loader": "^0.8.2",
|
"svg-inline-loader": "^0.8.2",
|
||||||
"webpack": "^5.74.0",
|
"url": "^0.11.0",
|
||||||
"webpack-cli": "^4.8.0",
|
"webpack": "^5.75.0",
|
||||||
"webpack-dev-server": "^4.2.1"
|
"webpack-cli": "^5.0.1",
|
||||||
|
"webpack-dev-server": "^4.11.1"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"/assets",
|
"/assets",
|
||||||
|
|||||||
+1
-4
@@ -401,12 +401,9 @@ class ReplayWebApp extends LitElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (IS_APP && this.sourceUrl.startsWith("file://")) {
|
if (IS_APP && this.sourceUrl.startsWith("file://")) {
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
const url = new URL(__APP_FILE_SERVE_PREFIX__);
|
|
||||||
url.searchParams.set("filename", this.sourceUrl.slice("file://".length));
|
|
||||||
this.loadInfo = {
|
this.loadInfo = {
|
||||||
sourceUrl: this.sourceUrl,
|
sourceUrl: this.sourceUrl,
|
||||||
loadUrl: url.href,
|
loadUrl: this.sourceUrl.replace("file://", "file2://")
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-3
@@ -79,9 +79,7 @@ class Chooser extends LitElement
|
|||||||
// file.path only available in electron app
|
// file.path only available in electron app
|
||||||
if (this.file.path) {
|
if (this.file.path) {
|
||||||
// eslint-disable-next-line no-undef
|
// eslint-disable-next-line no-undef
|
||||||
const url = new URL(__APP_FILE_SERVE_PREFIX__);
|
loadInfo.loadUrl = "file2://" + this.file.path;
|
||||||
url.searchParams.set("filename", this.file.path);
|
|
||||||
loadInfo.loadUrl = url.href;
|
|
||||||
loadInfo.noCache = true;
|
loadInfo.noCache = true;
|
||||||
} else if (this.fileHandle) {
|
} else if (this.fileHandle) {
|
||||||
loadInfo.loadUrl = this.fileDisplayName;
|
loadInfo.loadUrl = this.fileDisplayName;
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
import { protocol, session } from "electron";
|
|
||||||
|
|
||||||
import fetchToHandler from "fetch-to-electron-protocol-handler";
|
|
||||||
import makeIPFSFetch from "js-ipfs-fetch";
|
|
||||||
import * as IPFS from "ipfs-core";
|
|
||||||
|
|
||||||
export const PROTOCOL_PERMISSIONS = {
|
|
||||||
standard: true,
|
|
||||||
secure: true,
|
|
||||||
allowServiceWorkers: true,
|
|
||||||
supportFetchAPI: true,
|
|
||||||
bypassCSP: false,
|
|
||||||
corsEnabled: true,
|
|
||||||
stream: true
|
|
||||||
};
|
|
||||||
|
|
||||||
export function registerPrivileges(privileges = PROTOCOL_PERMISSIONS) {
|
|
||||||
protocol.registerSchemesAsPrivileged([
|
|
||||||
{scheme: "ipfs", privileges},
|
|
||||||
{scheme: "ipns", privileges},
|
|
||||||
{scheme: "ipld", privileges}
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function registerHandler(ipfsRepoPath) {
|
|
||||||
const handler = createHandler(ipfsRepoPath);
|
|
||||||
protocol.registerStreamProtocol("ipfs", handler);
|
|
||||||
protocol.registerStreamProtocol("ipns", handler);
|
|
||||||
protocol.registerStreamProtocol("ipld", handler);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createHandler (ipfsRepoPath) {
|
|
||||||
const {handler} = fetchToHandler(async () => {
|
|
||||||
const ipfs = await IPFS.create({
|
|
||||||
repo: ipfsRepoPath
|
|
||||||
});
|
|
||||||
|
|
||||||
const fetch = await makeIPFSFetch({ ipfs });
|
|
||||||
|
|
||||||
return fetch;
|
|
||||||
}, session.defaultSession);
|
|
||||||
|
|
||||||
return handler;
|
|
||||||
}
|
|
||||||
+85
-102
@@ -3,13 +3,12 @@
|
|||||||
import fetch from "node-fetch";
|
import fetch from "node-fetch";
|
||||||
import { Headers } from "node-fetch";
|
import { Headers } from "node-fetch";
|
||||||
|
|
||||||
import {app, session, BrowserWindow, ipcMain, screen, shell } from "electron";
|
import {app, session, BrowserWindow, ipcMain, protocol, screen, shell } from "electron";
|
||||||
|
|
||||||
import path from "path";
|
import path from "path";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
|
|
||||||
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac/src/rewrite";
|
import { ArchiveResponse, Rewriter } from "@webrecorder/wabac/src/rewrite";
|
||||||
import {create as createIPFS} from "auto-js-ipfs";
|
|
||||||
|
|
||||||
import { PassThrough, Readable } from "stream";
|
import { PassThrough, Readable } from "stream";
|
||||||
|
|
||||||
@@ -17,6 +16,7 @@ import { autoUpdater } from "electron-updater";
|
|||||||
import log from "electron-log";
|
import log from "electron-log";
|
||||||
|
|
||||||
import mime from "mime-types";
|
import mime from "mime-types";
|
||||||
|
import url from "url";
|
||||||
|
|
||||||
global.Headers = Headers;
|
global.Headers = Headers;
|
||||||
global.fetch = fetch;
|
global.fetch = fetch;
|
||||||
@@ -25,6 +25,8 @@ const STATIC_PREFIX = "http://localhost:5471/";
|
|||||||
|
|
||||||
const REPLAY_PREFIX = STATIC_PREFIX + "w/";
|
const REPLAY_PREFIX = STATIC_PREFIX + "w/";
|
||||||
|
|
||||||
|
const FILE_PROTO = "file2";
|
||||||
|
|
||||||
const URL_RX = /([^/]+)\/([\d]+)(?:\w\w_)?\/(.*)$/;
|
const URL_RX = /([^/]+)\/([\d]+)(?:\w\w_)?\/(.*)$/;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -50,7 +52,7 @@ class ElectronReplayApp
|
|||||||
|
|
||||||
this.screenSize = {width: 1024, height: 768};
|
this.screenSize = {width: 1024, height: 768};
|
||||||
|
|
||||||
this.ipfsClient = null;
|
this.origUA = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
get mainWindowWebPreferences() {
|
get mainWindowWebPreferences() {
|
||||||
@@ -69,7 +71,7 @@ class ElectronReplayApp
|
|||||||
return "index.html";
|
return "index.html";
|
||||||
}
|
}
|
||||||
|
|
||||||
init(includePlugins = false) {
|
init() {
|
||||||
// Single instance check
|
// Single instance check
|
||||||
const gotTheLock = app.requestSingleInstanceLock();
|
const gotTheLock = app.requestSingleInstanceLock();
|
||||||
|
|
||||||
@@ -83,36 +85,10 @@ class ElectronReplayApp
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (includePlugins) {
|
|
||||||
switch (process.platform) {
|
|
||||||
case "win32":
|
|
||||||
this.pluginPath = path.join(this.projPath, "plugins-win", `pepflashplayer-x86${process.arch === "x64" ? "_64" : ""}.dll`);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "darwin":
|
|
||||||
this.pluginPath = path.join(this.projPath, "plugins-mac", "PepperFlashPlayer.plugin");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "linux":
|
|
||||||
this.pluginPath = path.join(this.projPath, "plugins-mac", "libpepflashplayer.so");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
console.log("platform unsupported: " + process.platform);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
app.commandLine.appendSwitch("ppapi-flash-path", this.pluginPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("app path", this.appPath);
|
console.log("app path", this.appPath);
|
||||||
console.log("dir name", __dirname);
|
console.log("dir name", __dirname);
|
||||||
console.log("proj path", this.projPath);
|
console.log("proj path", this.projPath);
|
||||||
|
|
||||||
if (includePlugins) {
|
|
||||||
console.log("plugin path", this.pluginPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("app data", app.getPath("appData"));
|
console.log("app data", app.getPath("appData"));
|
||||||
console.log("user data", app.getPath("userData"));
|
console.log("user data", app.getPath("userData"));
|
||||||
|
|
||||||
@@ -120,6 +96,19 @@ class ElectronReplayApp
|
|||||||
app.setPath("userData", path.join(app.getPath("appData"), this.profileName));
|
app.setPath("userData", path.join(app.getPath("appData"), this.profileName));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protocol.registerSchemesAsPrivileged([{
|
||||||
|
scheme: FILE_PROTO,
|
||||||
|
privileges: {
|
||||||
|
standard: false,
|
||||||
|
secure: true,
|
||||||
|
bypassCSP: true,
|
||||||
|
allowServiceWorkers: true,
|
||||||
|
supportFetchAPI: true,
|
||||||
|
corsEnabled: true,
|
||||||
|
stream: true
|
||||||
|
}
|
||||||
|
}]);
|
||||||
|
|
||||||
app.on("will-finish-launching", () => {
|
app.on("will-finish-launching", () => {
|
||||||
app.on("open-file", (event, filePath) => {
|
app.on("open-file", (event, filePath) => {
|
||||||
this.openNextFile = filePath;
|
this.openNextFile = filePath;
|
||||||
@@ -155,9 +144,6 @@ class ElectronReplayApp
|
|||||||
}
|
}
|
||||||
|
|
||||||
onAppReady() {
|
onAppReady() {
|
||||||
const ipfsRepoPath = path.join(app.getPath("userData"), "js-ipfs");
|
|
||||||
console.log("ipfs path", ipfsRepoPath);
|
|
||||||
|
|
||||||
this.checkUpdates();
|
this.checkUpdates();
|
||||||
|
|
||||||
this.screenSize = screen.getPrimaryDisplay().workAreaSize;
|
this.screenSize = screen.getPrimaryDisplay().workAreaSize;
|
||||||
@@ -184,9 +170,48 @@ class ElectronReplayApp
|
|||||||
|
|
||||||
sesh.protocol.interceptStreamProtocol("http", (request, callback) => this.doIntercept(request, callback));
|
sesh.protocol.interceptStreamProtocol("http", (request, callback) => this.doIntercept(request, callback));
|
||||||
|
|
||||||
|
protocol.registerStreamProtocol(FILE_PROTO, (request, callback) => this.doHandleFile(request, callback));
|
||||||
|
|
||||||
|
this.origUA = sesh.getUserAgent();
|
||||||
|
|
||||||
this.mainWindow = this.createMainWindow(process.argv);
|
this.mainWindow = this.createMainWindow(process.argv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async doHandleFile(request, callback) {
|
||||||
|
//const parsedUrl = new URL(request.url);
|
||||||
|
//const filename = parsedUrl.searchParams.get("filename");
|
||||||
|
|
||||||
|
if (request.url === FILE_PROTO + "://localhost") {
|
||||||
|
callback({statusCode: 200, data: null});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const filename = url.fileURLToPath(request.url.replace(FILE_PROTO, "file"));
|
||||||
|
|
||||||
|
const headers = {"Content-Type": "application/octet-stream"};
|
||||||
|
const reqHeaders = new Headers(request.headers);
|
||||||
|
|
||||||
|
if (filename) {
|
||||||
|
const stat = await fs.promises.lstat(filename);
|
||||||
|
|
||||||
|
if (!stat.isFile()) {
|
||||||
|
return this.notFound(filename, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
const size = stat.size;
|
||||||
|
|
||||||
|
const {statusCode, start, end} = this.parseRange(reqHeaders, headers, size);
|
||||||
|
|
||||||
|
const data = request.method === "HEAD" ? null : fs.createReadStream(filename, {start, end});
|
||||||
|
|
||||||
|
callback({statusCode, headers, data});
|
||||||
|
return;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return this.notFound("No Resource Specified", callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_bufferToStream(data) {
|
_bufferToStream(data) {
|
||||||
const rv = new PassThrough();
|
const rv = new PassThrough();
|
||||||
rv.push(data);
|
rv.push(data);
|
||||||
@@ -243,73 +268,6 @@ class ElectronReplayApp
|
|||||||
return this.notFound(request.url, callback);
|
return this.notFound(request.url, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
if (request.url.startsWith(__APP_FILE_SERVE_PREFIX__)) {
|
|
||||||
const parsedUrl = new URL(request.url);
|
|
||||||
|
|
||||||
const filename = parsedUrl.searchParams.get("filename");
|
|
||||||
const ipfsCID = parsedUrl.searchParams.get("ipfs");
|
|
||||||
|
|
||||||
const headers = {"Content-Type": "application/octet-stream"};
|
|
||||||
const reqHeaders = new Headers(request.headers);
|
|
||||||
|
|
||||||
if (filename) {
|
|
||||||
console.log("file serve:", filename);
|
|
||||||
|
|
||||||
const stat = await fs.promises.lstat(filename);
|
|
||||||
|
|
||||||
if (!stat.isFile()) {
|
|
||||||
return this.notFound(filename, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
const size = stat.size;
|
|
||||||
|
|
||||||
const {statusCode, start, end} = this.parseRange(reqHeaders, headers, size);
|
|
||||||
|
|
||||||
const data = request.method === "HEAD" ? null : fs.createReadStream(filename, {start, end});
|
|
||||||
|
|
||||||
callback({statusCode, headers, data});
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else if (ipfsCID) {
|
|
||||||
const ipfsURL = `ipfs://${ipfsCID}}`;
|
|
||||||
|
|
||||||
console.log("ipfs serve:", ipfsCID);
|
|
||||||
|
|
||||||
// TODO: Pass in config?
|
|
||||||
this.ipfsClient = await createIPFS();
|
|
||||||
|
|
||||||
console.log("inited");
|
|
||||||
|
|
||||||
let size = await this.ipfsClient.getSize(ipfsURL);
|
|
||||||
|
|
||||||
console.log("got size", size);
|
|
||||||
|
|
||||||
if (size === null) {
|
|
||||||
return this.notFound(ipfsCID, callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
const {statusCode, start, end} = this.parseRange(reqHeaders, headers, size);
|
|
||||||
|
|
||||||
let data = null;
|
|
||||||
|
|
||||||
if (request.method === "GET") {
|
|
||||||
const offset = start || 0;
|
|
||||||
const length = end ? end - start + 1 : size;
|
|
||||||
data = Readable.from(await this.ipfsClient.get(ipfsURL, {
|
|
||||||
start: offset,
|
|
||||||
end: offset +length
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
callback({statusCode, headers, data});
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return this.notFound("No Resource Specified", callback);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// possible 'live leak' attempt, return archived version, if any
|
// possible 'live leak' attempt, return archived version, if any
|
||||||
if (request.referrer && request.referrer.startsWith(REPLAY_PREFIX)) {
|
if (request.referrer && request.referrer.startsWith(REPLAY_PREFIX)) {
|
||||||
return await this.resolveArchiveResponse(request, callback);
|
return await this.resolveArchiveResponse(request, callback);
|
||||||
@@ -320,9 +278,24 @@ class ElectronReplayApp
|
|||||||
|
|
||||||
async proxyLive(request, callback) {
|
async proxyLive(request, callback) {
|
||||||
let headers = request.headers;
|
let headers = request.headers;
|
||||||
|
const {method, url, uploadData} = request;
|
||||||
|
|
||||||
const method = request.method;
|
const body = uploadData ? Readable.from(readBody(uploadData, session.defaultSession)) : null;
|
||||||
const response = await fetch(request.url, {method, headers});
|
|
||||||
|
if (this.origUA) {
|
||||||
|
// pass UA if origUA is set
|
||||||
|
headers["User-Agent"] = this.origUA;
|
||||||
|
}
|
||||||
|
|
||||||
|
let response;
|
||||||
|
|
||||||
|
try {
|
||||||
|
response = await fetch(url, {method, headers, body});
|
||||||
|
} catch (e) {
|
||||||
|
console.warn("fetch failed for: " + url);
|
||||||
|
callback({statusCode: 502, headers: {}, data: null});
|
||||||
|
return;
|
||||||
|
}
|
||||||
const data = method === "HEAD" ? null : response.body;
|
const data = method === "HEAD" ? null : response.body;
|
||||||
const statusCode = response.status;
|
const statusCode = response.status;
|
||||||
|
|
||||||
@@ -478,4 +451,14 @@ class ElectronReplayApp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function * readBody (body, session) {
|
||||||
|
for (const chunk of body) {
|
||||||
|
if (chunk.bytes) {
|
||||||
|
yield await Promise.resolve(chunk.bytes);
|
||||||
|
} else if (chunk.blobUUID) {
|
||||||
|
yield await session.getBlobData(chunk.blobUUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export { ElectronReplayApp, STATIC_PREFIX };
|
export { ElectronReplayApp, STATIC_PREFIX };
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ class oe extends re{constructor(e){if(super(e),this.it=R,e.type!==ie)throw Error
|
|||||||
* Copyright 2017 Google LLC
|
* Copyright 2017 Google LLC
|
||||||
* SPDX-License-Identifier: BSD-3-Clause
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
*/
|
*/
|
||||||
class se extends oe{}se.directiveName="unsafeSVG",se.resultType=2;const le=ae(se),ce=ae(class extends re{constructor(e){var t;if(super(e),e.type!==te||"style"!==e.name||(null===(t=e.strings)||void 0===t?void 0:t.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(e){return Object.keys(e).reduce(((t,i)=>{const a=e[i];return null==a?t:t+`${i=i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${a};`}),"")}update(e,[t]){const{style:i}=e.element;if(void 0===this.ct){this.ct=new Set;for(const e in t)this.ct.add(e);return this.render(t)}this.ct.forEach((e=>{null==t[e]&&(this.ct.delete(e),e.includes("-")?i.removeProperty(e):i[e]="")}));for(const e in t){const a=t[e];null!=a&&(this.ct.add(e),e.includes("-")?i.setProperty(e,a):i[e]=a)}return U}});var de=__webpack_require__(6274),he=__webpack_require__(3029),fe=__webpack_require__.n(he);const be=r(de.Z);function ue(e){return[be,e]}const pe=window.IS_APP||window.electron&&window.electron.IS_APP||window.matchMedia("(display-mode: standalone)").matches,me="1.7.7";function ge(e){" "==e.key&&(e.preventDefault(),e.target.click())}class ve extends X{constructor(){super(),this.size="1.1em",this.width=null,this.height=null}static get properties(){return{svg:{type:String},size:{type:String},width:{type:String},height:{type:String}}}static get styles(){return o`
|
class se extends oe{}se.directiveName="unsafeSVG",se.resultType=2;const le=ae(se),ce=ae(class extends re{constructor(e){var t;if(super(e),e.type!==te||"style"!==e.name||(null===(t=e.strings)||void 0===t?void 0:t.length)>2)throw Error("The `styleMap` directive must be used in the `style` attribute and must be the only part in the attribute.")}render(e){return Object.keys(e).reduce(((t,i)=>{const a=e[i];return null==a?t:t+`${i=i.replace(/(?:^(webkit|moz|ms|o)|)(?=[A-Z])/g,"-$&").toLowerCase()}:${a};`}),"")}update(e,[t]){const{style:i}=e.element;if(void 0===this.ct){this.ct=new Set;for(const e in t)this.ct.add(e);return this.render(t)}this.ct.forEach((e=>{null==t[e]&&(this.ct.delete(e),e.includes("-")?i.removeProperty(e):i[e]="")}));for(const e in t){const a=t[e];null!=a&&(this.ct.add(e),e.includes("-")?i.setProperty(e,a):i[e]=a)}return U}});var de=__webpack_require__(6274),he=__webpack_require__(3029),fe=__webpack_require__.n(he);const be=r(de.Z);function ue(e){return[be,e]}const pe=window.IS_APP||window.electron&&window.electron.IS_APP||window.matchMedia("(display-mode: standalone)").matches,me="1.7.8";function ge(e){" "==e.key&&(e.preventDefault(),e.target.click())}class ve extends X{constructor(){super(),this.size="1.1em",this.width=null,this.height=null}static get properties(){return{svg:{type:String},size:{type:String},width:{type:String},height:{type:String}}}static get styles(){return o`
|
||||||
:host {
|
:host {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@@ -273,7 +273,7 @@ class se extends oe{}se.directiveName="unsafeSVG",se.resultType=2;const le=ae(se
|
|||||||
${this.sourceUrl?this.renderColl():this.renderHomeIndex()}
|
${this.sourceUrl?this.renderColl():this.renderHomeIndex()}
|
||||||
|
|
||||||
${this.showAbout?this.renderAbout():""}
|
${this.showAbout?this.renderAbout():""}
|
||||||
`:P``}firstUpdated(){this.initRoute(),window.addEventListener("popstate",(()=>{this.initRoute()}))}updated(e){e.has("sourceUrl")&&(this.collTitle=null)}onFavIcons(e){const t=document.querySelector("head"),i=document.querySelectorAll("link[rel*='icon']");for(const e of i)t.removeChild(e);for(const i of e.detail.icons){const e=document.createElement("link");e.rel=i.rel,e.href=i.href,t.appendChild(e)}}skipMenu(e){e.preventDefault(),this.renderRoot.querySelector("#skip-main-target").focus()}onNavMenu(e){e.preventDefault(),e.stopPropagation(),this.navMenuShown=!this.navMenuShown,this.navMenuShown&&(document.addEventListener("click",(e=>{e.preventDefault(),this.navMenuShown=!1,this.renderRoot.querySelector("#menu-button").focus()}),{once:!0}),document.addEventListener("keypress",(e=>{"Escape"==e.key&&(e.preventDefault(),this.navMenuShown=!1,this.renderRoot.querySelector("#menu-button").focus())}),{once:!0}))}initRoute(){this.inited=!0,this.pageParams=new URLSearchParams(window.location.search);let e=this.pageParams.get("state");if(e)try{if(e=JSON.parse(e),e.ids instanceof Array&&e.userId&&"open"===e.action)return this.pageParams.set("source","googledrive://"+e.ids[0]),this.pageParams.delete("state"),void(window.location.search=this.pageParams.toString())}catch(e){console.log(e)}if(this.source){this.pageParams.set("source",this.source);const e=new URL(window.location.href);e.search=this.pageParams.toString(),window.history.replaceState({},document.title,e.href)}if(this.sourceUrl=this.pageParams.get("source")||"",this.embed=this.pageParams.get("embed")||"",this.pageParams.has("terms")&&(this.showAbout=!0),this.pageParams.has("embed")&&(this.loadInfo||(this.loadInfo={})),this.pageParams.get("config"))try{this.loadInfo.extraConfig=JSON.parse(this.pageParams.get("config"))}catch(e){console.log("invalid config: "+e)}if(this.pageParams.get("baseUrlSourcePrefix")&&(this.loadInfo.extraConfig=this.loadInfo.extraConfig||{},this.loadInfo.extraConfig.baseUrlSourcePrefix=this.pageParams.get("baseUrlSourcePrefix")),this.pageParams.get("basePageUrl")&&(this.loadInfo.extraConfig=this.loadInfo.extraConfig||{},this.loadInfo.extraConfig.baseUrl=this.pageParams.get("basePageUrl")),this.pageParams.get("customColl")&&(this.loadInfo.customColl=this.pageParams.get("customColl")),"1"===this.pageParams.get("noWebWorker")&&(this.loadInfo.noWebWorker=!0),"1"===this.pageParams.get("noCache")&&(this.loadInfo.noCache=!0),"1"===this.pageParams.get("hideOffscreen")&&(this.loadInfo.hideOffscreen=!0),"eager"===this.pageParams.get("loading")&&(this.loadInfo.loadEager=!0),pe&&this.sourceUrl.startsWith("file://")){const e=new URL("http://files.replayweb.page/");e.searchParams.set("filename",this.sourceUrl.slice("file://".length)),this.loadInfo={sourceUrl:this.sourceUrl,loadUrl:e.href}}}onStartLoad(e){this.pageParams.set("source",e.detail.sourceUrl);const t=new URL(window.location.href);t.search=this.pageParams.toString(),this.collPageUrl=t.toString(),e.detail.isFile?(window.history.pushState({},"",this.collPageUrl),this.sourceUrl=e.detail.sourceUrl,this.loadInfo=e.detail):window.location.search=this.pageParams.toString()}onCollLoaded(e){this.loadInfo=null,e.detail.collInfo&&(this.collTitle=e.detail.collInfo.title),e.detail.alreadyLoaded||e.detail.sourceUrl!==this.sourceUrl&&(this.pageParams.set("source",e.detail.sourceUrl),window.location.search=this.pageParams.toString())}onTitle(e){e.detail.title&&(this.pageTitle=e.detail.title,this.pageReplay=e.detail.replayTitle,document.title=(e.detail.replayTitle?"Archive of ":"")+this.pageTitle+" | "+this.appName)}safariKeyframes(){const e=document.createElement("style");document.head.appendChild(e),e.appendChild(document.createTextNode("\n @keyframes spinAround {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(359deg);\n }\n }\n "))}renderAbout(){return P`
|
`:P``}firstUpdated(){this.initRoute(),window.addEventListener("popstate",(()=>{this.initRoute()}))}updated(e){e.has("sourceUrl")&&(this.collTitle=null)}onFavIcons(e){const t=document.querySelector("head"),i=document.querySelectorAll("link[rel*='icon']");for(const e of i)t.removeChild(e);for(const i of e.detail.icons){const e=document.createElement("link");e.rel=i.rel,e.href=i.href,t.appendChild(e)}}skipMenu(e){e.preventDefault(),this.renderRoot.querySelector("#skip-main-target").focus()}onNavMenu(e){e.preventDefault(),e.stopPropagation(),this.navMenuShown=!this.navMenuShown,this.navMenuShown&&(document.addEventListener("click",(e=>{e.preventDefault(),this.navMenuShown=!1,this.renderRoot.querySelector("#menu-button").focus()}),{once:!0}),document.addEventListener("keypress",(e=>{"Escape"==e.key&&(e.preventDefault(),this.navMenuShown=!1,this.renderRoot.querySelector("#menu-button").focus())}),{once:!0}))}initRoute(){this.inited=!0,this.pageParams=new URLSearchParams(window.location.search);let e=this.pageParams.get("state");if(e)try{if(e=JSON.parse(e),e.ids instanceof Array&&e.userId&&"open"===e.action)return this.pageParams.set("source","googledrive://"+e.ids[0]),this.pageParams.delete("state"),void(window.location.search=this.pageParams.toString())}catch(e){console.log(e)}if(this.source){this.pageParams.set("source",this.source);const e=new URL(window.location.href);e.search=this.pageParams.toString(),window.history.replaceState({},document.title,e.href)}if(this.sourceUrl=this.pageParams.get("source")||"",this.embed=this.pageParams.get("embed")||"",this.pageParams.has("terms")&&(this.showAbout=!0),this.pageParams.has("embed")&&(this.loadInfo||(this.loadInfo={})),this.pageParams.get("config"))try{this.loadInfo.extraConfig=JSON.parse(this.pageParams.get("config"))}catch(e){console.log("invalid config: "+e)}this.pageParams.get("baseUrlSourcePrefix")&&(this.loadInfo.extraConfig=this.loadInfo.extraConfig||{},this.loadInfo.extraConfig.baseUrlSourcePrefix=this.pageParams.get("baseUrlSourcePrefix")),this.pageParams.get("basePageUrl")&&(this.loadInfo.extraConfig=this.loadInfo.extraConfig||{},this.loadInfo.extraConfig.baseUrl=this.pageParams.get("basePageUrl")),this.pageParams.get("customColl")&&(this.loadInfo.customColl=this.pageParams.get("customColl")),"1"===this.pageParams.get("noWebWorker")&&(this.loadInfo.noWebWorker=!0),"1"===this.pageParams.get("noCache")&&(this.loadInfo.noCache=!0),"1"===this.pageParams.get("hideOffscreen")&&(this.loadInfo.hideOffscreen=!0),"eager"===this.pageParams.get("loading")&&(this.loadInfo.loadEager=!0),pe&&this.sourceUrl.startsWith("file://")&&(this.loadInfo={sourceUrl:this.sourceUrl,loadUrl:this.sourceUrl.replace("file://","file2://")})}onStartLoad(e){this.pageParams.set("source",e.detail.sourceUrl);const t=new URL(window.location.href);t.search=this.pageParams.toString(),this.collPageUrl=t.toString(),e.detail.isFile?(window.history.pushState({},"",this.collPageUrl),this.sourceUrl=e.detail.sourceUrl,this.loadInfo=e.detail):window.location.search=this.pageParams.toString()}onCollLoaded(e){this.loadInfo=null,e.detail.collInfo&&(this.collTitle=e.detail.collInfo.title),e.detail.alreadyLoaded||e.detail.sourceUrl!==this.sourceUrl&&(this.pageParams.set("source",e.detail.sourceUrl),window.location.search=this.pageParams.toString())}onTitle(e){e.detail.title&&(this.pageTitle=e.detail.title,this.pageReplay=e.detail.replayTitle,document.title=(e.detail.replayTitle?"Archive of ":"")+this.pageTitle+" | "+this.appName)}safariKeyframes(){const e=document.createElement("style");document.head.appendChild(e),e.appendChild(document.createTextNode("\n @keyframes spinAround {\n from {\n transform: rotate(0deg);\n }\n to {\n transform: rotate(359deg);\n }\n }\n "))}renderAbout(){return P`
|
||||||
<div class="modal is-active">
|
<div class="modal is-active">
|
||||||
<div class="modal-background" @click="${this.onAboutClose}"></div>
|
<div class="modal-background" @click="${this.onAboutClose}"></div>
|
||||||
<div class="modal-card">
|
<div class="modal-card">
|
||||||
@@ -328,7 +328,7 @@ class se extends oe{}se.directiveName="unsafeSVG",se.resultType=2;const le=ae(se
|
|||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`}onAboutClose(){this.showAbout=!1}}customElements.define("replay-app-main",Ie);var Le=__webpack_require__(8135),Te=__webpack_require__.n(Le);class Pe extends X{constructor(){super(),this.fileDisplayName="",this.file=null,this.hasNativeFS=!!window.showOpenFilePicker&&!pe,this.newFullImport=!1,this.noHead=!1}static get properties(){return{fileDisplayName:{type:String},newFullImport:{type:Boolean},noHead:{type:Boolean}}}onChooseFile(e){0!==e.currentTarget.files.length&&(this.file=e.currentTarget.files[0],this.fileDisplayName="file://"+(this.file.path||this.file.name))}async onChooseNativeFile(){if(!this.hasNativeFS)return;const[e]=await window.showOpenFilePicker({types:[{description:"WARC, WACZ, HAR and WBN Files",accept:{"application/warc":[".warc",".gz"],"application/har":[".har"],"application/wacz":[".wacz"],"application/wbn":[".wbn"],"application/json":[".json"]}}]});this.fileHandle=e,this.file=await e.getFile(),this.fileDisplayName="file://"+e.name}randomId(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)}onStartLoad(e){e.preventDefault();const t={sourceUrl:this.fileDisplayName};if(this.file){if(t.isFile=!0,this.file.path){const e=new URL("http://files.replayweb.page/");e.searchParams.set("filename",this.file.path),t.loadUrl=e.href,t.noCache=!0}else this.fileHandle?(t.loadUrl=this.fileDisplayName,t.extra={fileHandle:this.fileHandle},t.noCache=!1):(t.loadUrl=URL.createObjectURL(this.file),t.blob=this.file,t.noCache=!1);t.size=this.file.size,t.name=this.fileDisplayName}return t.newFullImport=this.newFullImport,this.dispatchEvent(new CustomEvent("load-start",{bubbles:!0,composed:!0,detail:t})),!1}onInput(e){this.fileDisplayName=e.currentTarget.value,this.file&&this.fileDisplayName&&this.fileDisplayName.startsWith("file://")&&(this.file=null,this.fileDisplayName="")}static get styles(){return ue(o`
|
</div>`}onAboutClose(){this.showAbout=!1}}customElements.define("replay-app-main",Ie);var Le=__webpack_require__(8135),Te=__webpack_require__.n(Le);class Pe extends X{constructor(){super(),this.fileDisplayName="",this.file=null,this.hasNativeFS=!!window.showOpenFilePicker&&!pe,this.newFullImport=!1,this.noHead=!1}static get properties(){return{fileDisplayName:{type:String},newFullImport:{type:Boolean},noHead:{type:Boolean}}}onChooseFile(e){0!==e.currentTarget.files.length&&(this.file=e.currentTarget.files[0],this.fileDisplayName="file://"+(this.file.path||this.file.name))}async onChooseNativeFile(){if(!this.hasNativeFS)return;const[e]=await window.showOpenFilePicker({types:[{description:"WARC, WACZ, HAR and WBN Files",accept:{"application/warc":[".warc",".gz"],"application/har":[".har"],"application/wacz":[".wacz"],"application/wbn":[".wbn"],"application/json":[".json"]}}]});this.fileHandle=e,this.file=await e.getFile(),this.fileDisplayName="file://"+e.name}randomId(){return Math.random().toString(36).substring(2,15)+Math.random().toString(36).substring(2,15)}onStartLoad(e){e.preventDefault();const t={sourceUrl:this.fileDisplayName};return this.file&&(t.isFile=!0,this.file.path?(t.loadUrl="file2://"+this.file.path,t.noCache=!0):this.fileHandle?(t.loadUrl=this.fileDisplayName,t.extra={fileHandle:this.fileHandle},t.noCache=!1):(t.loadUrl=URL.createObjectURL(this.file),t.blob=this.file,t.noCache=!1),t.size=this.file.size,t.name=this.fileDisplayName),t.newFullImport=this.newFullImport,this.dispatchEvent(new CustomEvent("load-start",{bubbles:!0,composed:!0,detail:t})),!1}onInput(e){this.fileDisplayName=e.currentTarget.value,this.file&&this.fileDisplayName&&this.fileDisplayName.startsWith("file://")&&(this.file=null,this.fileDisplayName="")}static get styles(){return ue(o`
|
||||||
:host {
|
:host {
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,11 +7,6 @@ const CopyPlugin = require("copy-webpack-plugin");
|
|||||||
const TerserPlugin = require("terser-webpack-plugin");
|
const TerserPlugin = require("terser-webpack-plugin");
|
||||||
const package_json = require("./package.json");
|
const package_json = require("./package.json");
|
||||||
|
|
||||||
// fake url used in app to serve files
|
|
||||||
// can not use custom scheme due to service worker issues
|
|
||||||
const APP_FILE_SERVE_PREFIX = "http://files.replayweb.page/";
|
|
||||||
//const APP_FILE_SERVE_PREFIX = "file://files.replayweb.page";
|
|
||||||
|
|
||||||
|
|
||||||
// helper proxy URL, run locally for app
|
// helper proxy URL, run locally for app
|
||||||
const HELPER_PROXY = "https://helper-proxy.webrecorder.workers.dev";
|
const HELPER_PROXY = "https://helper-proxy.webrecorder.workers.dev";
|
||||||
@@ -66,9 +61,7 @@ const electronMainConfig = (/*env, argv*/) => {
|
|||||||
},
|
},
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
__APP_FILE_SERVE_PREFIX__ : JSON.stringify(APP_FILE_SERVE_PREFIX),
|
|
||||||
__HELPER_PROXY__ : JSON.stringify(HELPER_PROXY),
|
__HELPER_PROXY__ : JSON.stringify(HELPER_PROXY),
|
||||||
__IPFS_CORE_URL__: JSON.stringify("")
|
|
||||||
}),
|
}),
|
||||||
new webpack.BannerPlugin(BANNER_TEXT),
|
new webpack.BannerPlugin(BANNER_TEXT),
|
||||||
new CopyPlugin({
|
new CopyPlugin({
|
||||||
@@ -98,12 +91,6 @@ const electronPreloadConfig = (/*env, argv*/) => {
|
|||||||
optimization,
|
optimization,
|
||||||
plugins: [
|
plugins: [
|
||||||
new webpack.BannerPlugin(BANNER_TEXT),
|
new webpack.BannerPlugin(BANNER_TEXT),
|
||||||
|
|
||||||
// this needs to be defined, but not actually used, as electron app uses
|
|
||||||
// ipfs-core from node
|
|
||||||
new webpack.DefinePlugin({
|
|
||||||
__IPFS_CORE_URL__: JSON.stringify("")
|
|
||||||
}),
|
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -152,7 +139,6 @@ const browserConfig = (/*env, argv*/) => {
|
|||||||
new MiniCssExtractPlugin(),
|
new MiniCssExtractPlugin(),
|
||||||
new webpack.DefinePlugin({
|
new webpack.DefinePlugin({
|
||||||
__SW_NAME__: JSON.stringify("sw.js"),
|
__SW_NAME__: JSON.stringify("sw.js"),
|
||||||
__APP_FILE_SERVE_PREFIX__ : JSON.stringify(APP_FILE_SERVE_PREFIX),
|
|
||||||
__HELPER_PROXY__ : JSON.stringify(HELPER_PROXY),
|
__HELPER_PROXY__ : JSON.stringify(HELPER_PROXY),
|
||||||
__GDRIVE_CLIENT_ID__ : JSON.stringify(GDRIVE_CLIENT_ID),
|
__GDRIVE_CLIENT_ID__ : JSON.stringify(GDRIVE_CLIENT_ID),
|
||||||
__VERSION__: JSON.stringify(package_json.version),
|
__VERSION__: JSON.stringify(package_json.version),
|
||||||
|
|||||||
Reference in New Issue
Block a user