Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
glawson committed Aug 14, 2020
0 parents commit 43648c5
Show file tree
Hide file tree
Showing 16 changed files with 4,002 additions and 0 deletions.
16 changes: 16 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
version: 2.1
jobs:
build:
macos:
xcode: 11.3.0
steps:
- checkout
- run:
name: Install
command: npm install
- run:
name: Running Build
command: npm run build
- run:
name: Running Tests
command: npm run test
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
node_modules
*.log
build
bin
.nyc_output/*
.vscode/*
11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# electron-deeplink

Node module for Electron apps that sets the default handler for a given protocol (deep links) in both
development and production environments.

# Please Note

Not completely ready for Windows (yet!), you will need to include your own handler for the app ['second-instance'](https://www.electronjs.org/docs/api/app#event-second-instance) event.


this is a
28 changes: 28 additions & 0 deletions binding.gyp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"targets": [{
"target_name": "electron-deeplink",
"sources": [ ],
"conditions": [
['OS=="mac"', {
"xcode_settings": {
"MACOSX_DEPLOYMENT_TARGET": "10.10"
},
"sources": [
"./src/electron-deeplink.mm"
],
}]
],
'include_dirs': [
"<!@(node -p \"require('node-addon-api').include\")"
],
'libraries': [],
'dependencies': [
"<!(node -p \"require('node-addon-api').gyp\")"
],
'defines': [ 'NAPI_DISABLE_CPP_EXCEPTIONS' ],
"xcode_settings": {
"OTHER_CPLUSPLUSFLAGS": ["-std=c++14", "-stdlib=libc++"],
"OTHER_LDFLAGS": ["-framework CoreFoundation"]
}
}]
}
56 changes: 56 additions & 0 deletions dist/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
declare const EventEmitter: any;
interface EventHandler {
(event: Event, args: string): void;
}
interface FuncBool {
(param?: any): boolean;
}
interface FuncVoid {
(param?: any): void;
}
interface FuncString {
(param?: any): string;
}
interface On {
(event: string, callback: EventHandler): void;
}
interface App {
requestSingleInstanceLock: FuncBool;
isDefaultProtocolClient: FuncBool;
setAsDefaultProtocolClient: FuncVoid;
quit: FuncVoid;
on: On;
getAppPath: FuncString;
}
interface MainWindow {
isMinimized: FuncBool;
restore: FuncVoid;
focus: FuncVoid;
}
interface DeeplinkConfig {
protocol: string;
app: App;
mainWindow: MainWindow;
isDev?: boolean;
isYarn?: boolean;
debugLogging?: boolean;
}
declare class Deeplink extends EventEmitter {
private appPath?;
private electronPath?;
private infoPlistFile?;
private infoPlistFileBak?;
private logger?;
private app;
private mainWindow;
private config;
constructor(config: DeeplinkConfig);
private checkConfig;
private setAppProtocol;
private secondInstanceEvent;
private openEvent;
restoreInfoPlist: () => void;
getProtocol: () => string | null;
getLogfile: () => any;
}
export { Deeplink };
131 changes: 131 additions & 0 deletions dist/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.Deeplink = void 0;
var electronDeeplink = require('bindings')('electron-deeplink.node');
var path = require('path');
var fs = require('fs');
var os = require('os');
var EventEmitter = require('events');
var infoPlistTemplate = require('./templates').infoPlistTemplate;
var Deeplink = /** @class */ (function (_super) {
__extends(Deeplink, _super);
function Deeplink(config) {
var _this = _super.call(this) || this;
_this.checkConfig = function (config) {
var expectedKeys = ['app', 'mainWindow', 'protocol'];
var configKeys = Object.keys(config);
var missingKeys = expectedKeys.filter(function (expectedKey) {
return !configKeys.includes(expectedKey);
});
if (missingKeys.length > 0) {
throw new Error("electron-deeplink: missing config attributes: " + missingKeys.join(', '));
}
};
_this.setAppProtocol = function () {
var _a = _this.config, protocol = _a.protocol, debugLogging = _a.debugLogging;
var bundleURL = infoPlistTemplate.replace(/{PROTOCOL}/g, protocol);
var infoPlist;
_this.appPath = _this.app.getAppPath();
_this.electronPath = path.join(_this.appPath, '/node_modules/electron/dist/Electron.app');
_this.infoPlistFile = path.join(_this.electronPath, '/Contents/Info.plist');
_this.infoPlistFileBak = path.join(_this.electronPath, '/Contents/Info.deeplink');
if (fs.existsSync(_this.infoPlistFileBak)) {
infoPlist = fs.readFileSync(_this.infoPlistFileBak, 'utf-8');
}
else {
infoPlist = fs.readFileSync(_this.infoPlistFile, 'utf-8');
fs.writeFileSync(_this.infoPlistFileBak, infoPlist);
}
infoPlist = infoPlist.replace('com.github.Electron', "com.deeplink." + protocol);
infoPlist = infoPlist.replace(/<\/dict>\n<\/plist>/, bundleURL);
fs.writeFileSync(_this.infoPlistFile, infoPlist);
return electronDeeplink.SetRuntimeAppProtocol(_this.electronPath, protocol, debugLogging);
};
_this.secondInstanceEvent = function () {
// handle windows here
if (os.platform() === 'darwin') {
_this.logger.error("electron-deeplink: the app event 'second-instance' fired, this should not of happened, please check your packager bundleId config");
return;
}
if (_this.mainWindow.isMinimized()) {
_this.mainWindow.restore();
}
_this.mainWindow.focus();
};
_this.openEvent = function (event, url, eventName) {
event.preventDefault();
var debugLogging = _this.config.debugLogging;
if (debugLogging) {
_this.logger.debug("electron-deeplink: " + eventName + ": " + url);
}
_this.emit('received', url);
};
_this.restoreInfoPlist = function () {
var _a = _this.config, debugLogging = _a.debugLogging, isDev = _a.isDev;
if (!isDev || os.platform() !== 'darwin') {
return;
}
if (fs.existsSync(_this.infoPlistFileBak)) {
var infoPlist = fs.readFileSync(_this.infoPlistFileBak, 'utf-8');
if (debugLogging) {
_this.logger.debug("electron-deeplink: restoring Info.plist");
}
fs.writeFileSync(_this.infoPlistFile, infoPlist);
}
};
_this.getProtocol = function () { return _this.config.protocol; };
_this.getLogfile = function () {
return _this.logger ? _this.logger.transports.file.getFile().path : 'debugLogging is disabled';
};
var app = config.app, mainWindow = config.mainWindow, protocol = config.protocol, _a = config.isDev, isDev = _a === void 0 ? false : _a, _b = config.debugLogging, debugLogging = _b === void 0 ? false : _b;
_this.checkConfig(config);
_this.config = { protocol: protocol, debugLogging: debugLogging, isDev: isDev };
_this.app = app;
_this.mainWindow = mainWindow;
if (debugLogging) {
_this.logger = require('electron-log');
_this.logger.transports.file.level = 'debug';
_this.logger.debug("electron-deeplink: debugLogging is enabled");
}
var instanceLock = app.requestSingleInstanceLock();
if (!instanceLock) {
if (debugLogging) {
_this.logger.debug("electron-deeplink: unable to lock instance");
}
app.quit();
return _this;
}
if (isDev && os.platform() === 'darwin') {
var handlerDebug_1 = _this.setAppProtocol();
if (debugLogging) {
Object.keys(handlerDebug_1).forEach(function (key) {
_this.logger.debug("electron-deeplink:NAPI: " + key + ": " + (Array.isArray(handlerDebug_1[key]) ? JSON.stringify(handlerDebug_1[key]) : handlerDebug_1[key]));
});
}
}
if (!app.isDefaultProtocolClient(protocol)) {
app.setAsDefaultProtocolClient(protocol);
}
app.on('second-instance', _this.secondInstanceEvent);
app.on('will-finish-launching', function () {
app.on('open-url', function (event, url) { return _this.openEvent(event, url, 'open-url'); });
app.on('open-file', function (event, url) { return _this.openEvent(event, url, 'open-file'); });
});
return _this;
}
return Deeplink;
}(EventEmitter));
exports.Deeplink = Deeplink;
2 changes: 2 additions & 0 deletions dist/templates.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
declare const infoPlistTemplate = "\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>{PROTOCOL}</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>{PROTOCOL}</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>";
export { infoPlistTemplate };
5 changes: 5 additions & 0 deletions dist/templates.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.infoPlistTemplate = void 0;
var infoPlistTemplate = "\t<key>CFBundleURLTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>CFBundleURLName</key>\n\t\t\t<string>{PROTOCOL}</string>\n\t\t\t<key>CFBundleURLSchemes</key>\n\t\t\t<array>\n\t\t\t\t<string>{PROTOCOL}</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>";
exports.infoPlistTemplate = infoPlistTemplate;
Loading

0 comments on commit 43648c5

Please sign in to comment.