@nimiq/rpc
Advanced tools
Comparing version 0.3.0 to 0.4.0-beta.1
@@ -167,2 +167,8 @@ 'use strict'; | ||
var ResponseMethod; | ||
(function (ResponseMethod) { | ||
ResponseMethod["POST"] = "post"; | ||
ResponseMethod["URL"] = "url"; | ||
ResponseMethod["MESSAGE"] = "message"; | ||
})(ResponseMethod || (ResponseMethod = {})); | ||
(function (ResponseStatus) { | ||
@@ -172,3 +178,2 @@ ResponseStatus["OK"] = "ok"; | ||
})(exports.ResponseStatus || (exports.ResponseStatus = {})); | ||
const POSTMESSAGE_RETURN_URL = '<postMessage>'; | ||
@@ -262,2 +267,7 @@ class RequestIdStorage { | ||
fragment.delete('command'); | ||
// Ignore messages without a responseMethod | ||
if (!fragment.has('responseMethod')) | ||
return null; | ||
const responseMethod = fragment.get('responseMethod'); | ||
fragment.delete('responseMethod'); | ||
// Ignore messages without a valid return path | ||
@@ -268,3 +278,3 @@ if (!fragment.has('returnURL')) | ||
fragment.delete('returnURL'); | ||
const answerByPostMessage = returnURL === POSTMESSAGE_RETURN_URL | ||
const answerByPostMessage = responseMethod === ResponseMethod.MESSAGE | ||
&& (window.opener || window.parent); | ||
@@ -297,3 +307,4 @@ // Only allow returning to same origin | ||
returnURL, | ||
source: answerByPostMessage ? (window.opener || window.parent) : null, | ||
responseMethod: responseMethod, | ||
source: responseMethod === ResponseMethod.MESSAGE ? (window.opener || window.parent) : null, | ||
}; | ||
@@ -347,3 +358,3 @@ } | ||
} | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args) { | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args, responseMethod) { | ||
const targetUrl = new URL(targetURL); | ||
@@ -354,2 +365,3 @@ const fragment = new URLSearchParams(targetUrl.hash.substring(1)); | ||
fragment.set('command', command); | ||
fragment.set('responseMethod', responseMethod); | ||
if (Array.isArray(args)) { | ||
@@ -596,7 +608,13 @@ fragment.set('args', JSONUtils.stringify(args)); | ||
call(returnURL, command, handleHistoryBack = false, ...args) { | ||
this.callAndSaveLocalState(returnURL, null, command, handleHistoryBack, ...args); | ||
this._call(returnURL, ResponseMethod.URL, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndPOSTResponse(returnURL, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.POST, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndSaveLocalState(returnURL, state, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.URL, state, command, handleHistoryBack, ...args); | ||
} | ||
_call(returnURL, responseMethod, state, command, handleHistoryBack = false, ...args) { | ||
const id = RandomUtils.generateRandomId(); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args, responseMethod); | ||
this._waitingRequests.add(id, command, state); | ||
@@ -669,4 +687,7 @@ if (handleHistoryBack) { | ||
this._id = message.data.id; | ||
this._postMessage = 'source' in message | ||
&& !('returnURL' in message && message.returnURL !== POSTMESSAGE_RETURN_URL); | ||
this._responseMethod = 'responseMethod' in message | ||
? message.responseMethod | ||
: 'source' in message && !('returnURL' in message) | ||
? ResponseMethod.MESSAGE | ||
: ResponseMethod.URL; | ||
this._returnURL = 'returnURL' in message ? message.returnURL : null; | ||
@@ -680,4 +701,5 @@ this._data = message.data; | ||
data: this._data, | ||
responseMethod: this._responseMethod, | ||
}; | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
if (this._source === window.opener) { | ||
@@ -707,3 +729,3 @@ obj.source = 'opener'; | ||
// TODO: Clear waiting request storage? | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
// Send via postMessage (e.g., popup or url-persisted popup) | ||
@@ -734,12 +756,43 @@ let target; | ||
else if (this._returnURL) { | ||
// Send via top-level navigation | ||
window.location.href = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
if (this._responseMethod === ResponseMethod.URL) { | ||
// Send via top-level navigation | ||
const reply = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
window.location.href = reply; | ||
} | ||
else if (this._responseMethod === ResponseMethod.POST) { | ||
// send via form to server | ||
const $form = document.createElement('form'); | ||
$form.setAttribute('method', 'post'); | ||
$form.setAttribute('action', this.returnURL); | ||
$form.setAttribute('style', 'display: none;'); | ||
const $statusInput = document.createElement('input'); | ||
$statusInput.setAttribute('type', 'text'); | ||
$statusInput.setAttribute('name', 'status'); | ||
$statusInput.setAttribute('value', status); | ||
$form.appendChild($statusInput); | ||
const $resultInput = document.createElement('input'); | ||
$resultInput.setAttribute('type', 'text'); | ||
$resultInput.setAttribute('name', 'result'); | ||
$resultInput.setAttribute('value', JSONUtils.stringify(result)); | ||
$form.appendChild($resultInput); | ||
const $idInput = document.createElement('input'); | ||
$idInput.setAttribute('type', 'text'); | ||
$idInput.setAttribute('name', 'rpcId'); | ||
$idInput.setAttribute('value', this.id.toString()); | ||
$form.appendChild($idInput); | ||
document.body.appendChild($form); | ||
$form.submit(); | ||
} | ||
} | ||
} | ||
toRequestObject() { | ||
if (this._responseMethod !== ResponseMethod.MESSAGE && !this._returnURL) { | ||
throw new Error('ReturnURL is needed'); | ||
} | ||
return { | ||
origin: this._origin, | ||
data: this._data, | ||
returnURL: this._returnURL || POSTMESSAGE_RETURN_URL, | ||
returnURL: this._returnURL || 'post-message', | ||
source: typeof this._source === 'string' ? this._source : null, | ||
responseMethod: this._responseMethod, | ||
}; | ||
@@ -746,0 +799,0 @@ } |
@@ -163,2 +163,8 @@ /* tslint:disable:no-bitwise */ | ||
var ResponseMethod; | ||
(function (ResponseMethod) { | ||
ResponseMethod["POST"] = "post"; | ||
ResponseMethod["URL"] = "url"; | ||
ResponseMethod["MESSAGE"] = "message"; | ||
})(ResponseMethod || (ResponseMethod = {})); | ||
var ResponseStatus; | ||
@@ -169,3 +175,2 @@ (function (ResponseStatus) { | ||
})(ResponseStatus || (ResponseStatus = {})); | ||
const POSTMESSAGE_RETURN_URL = '<postMessage>'; | ||
@@ -259,2 +264,7 @@ class RequestIdStorage { | ||
fragment.delete('command'); | ||
// Ignore messages without a responseMethod | ||
if (!fragment.has('responseMethod')) | ||
return null; | ||
const responseMethod = fragment.get('responseMethod'); | ||
fragment.delete('responseMethod'); | ||
// Ignore messages without a valid return path | ||
@@ -265,3 +275,3 @@ if (!fragment.has('returnURL')) | ||
fragment.delete('returnURL'); | ||
const answerByPostMessage = returnURL === POSTMESSAGE_RETURN_URL | ||
const answerByPostMessage = responseMethod === ResponseMethod.MESSAGE | ||
&& (window.opener || window.parent); | ||
@@ -294,3 +304,4 @@ // Only allow returning to same origin | ||
returnURL, | ||
source: answerByPostMessage ? (window.opener || window.parent) : null, | ||
responseMethod: responseMethod, | ||
source: responseMethod === ResponseMethod.MESSAGE ? (window.opener || window.parent) : null, | ||
}; | ||
@@ -344,3 +355,3 @@ } | ||
} | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args) { | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args, responseMethod) { | ||
const targetUrl = new URL(targetURL); | ||
@@ -351,2 +362,3 @@ const fragment = new URLSearchParams(targetUrl.hash.substring(1)); | ||
fragment.set('command', command); | ||
fragment.set('responseMethod', responseMethod); | ||
if (Array.isArray(args)) { | ||
@@ -593,7 +605,13 @@ fragment.set('args', JSONUtils.stringify(args)); | ||
call(returnURL, command, handleHistoryBack = false, ...args) { | ||
this.callAndSaveLocalState(returnURL, null, command, handleHistoryBack, ...args); | ||
this._call(returnURL, ResponseMethod.URL, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndPOSTResponse(returnURL, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.POST, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndSaveLocalState(returnURL, state, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.URL, state, command, handleHistoryBack, ...args); | ||
} | ||
_call(returnURL, responseMethod, state, command, handleHistoryBack = false, ...args) { | ||
const id = RandomUtils.generateRandomId(); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args, responseMethod); | ||
this._waitingRequests.add(id, command, state); | ||
@@ -666,4 +684,7 @@ if (handleHistoryBack) { | ||
this._id = message.data.id; | ||
this._postMessage = 'source' in message | ||
&& !('returnURL' in message && message.returnURL !== POSTMESSAGE_RETURN_URL); | ||
this._responseMethod = 'responseMethod' in message | ||
? message.responseMethod | ||
: 'source' in message && !('returnURL' in message) | ||
? ResponseMethod.MESSAGE | ||
: ResponseMethod.URL; | ||
this._returnURL = 'returnURL' in message ? message.returnURL : null; | ||
@@ -677,4 +698,5 @@ this._data = message.data; | ||
data: this._data, | ||
responseMethod: this._responseMethod, | ||
}; | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
if (this._source === window.opener) { | ||
@@ -704,3 +726,3 @@ obj.source = 'opener'; | ||
// TODO: Clear waiting request storage? | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
// Send via postMessage (e.g., popup or url-persisted popup) | ||
@@ -731,12 +753,43 @@ let target; | ||
else if (this._returnURL) { | ||
// Send via top-level navigation | ||
window.location.href = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
if (this._responseMethod === ResponseMethod.URL) { | ||
// Send via top-level navigation | ||
const reply = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
window.location.href = reply; | ||
} | ||
else if (this._responseMethod === ResponseMethod.POST) { | ||
// send via form to server | ||
const $form = document.createElement('form'); | ||
$form.setAttribute('method', 'post'); | ||
$form.setAttribute('action', this.returnURL); | ||
$form.setAttribute('style', 'display: none;'); | ||
const $statusInput = document.createElement('input'); | ||
$statusInput.setAttribute('type', 'text'); | ||
$statusInput.setAttribute('name', 'status'); | ||
$statusInput.setAttribute('value', status); | ||
$form.appendChild($statusInput); | ||
const $resultInput = document.createElement('input'); | ||
$resultInput.setAttribute('type', 'text'); | ||
$resultInput.setAttribute('name', 'result'); | ||
$resultInput.setAttribute('value', JSONUtils.stringify(result)); | ||
$form.appendChild($resultInput); | ||
const $idInput = document.createElement('input'); | ||
$idInput.setAttribute('type', 'text'); | ||
$idInput.setAttribute('name', 'rpcId'); | ||
$idInput.setAttribute('value', this.id.toString()); | ||
$form.appendChild($idInput); | ||
document.body.appendChild($form); | ||
$form.submit(); | ||
} | ||
} | ||
} | ||
toRequestObject() { | ||
if (this._responseMethod !== ResponseMethod.MESSAGE && !this._returnURL) { | ||
throw new Error('ReturnURL is needed'); | ||
} | ||
return { | ||
origin: this._origin, | ||
data: this._data, | ||
returnURL: this._returnURL || POSTMESSAGE_RETURN_URL, | ||
returnURL: this._returnURL || 'post-message', | ||
source: typeof this._source === 'string' ? this._source : null, | ||
responseMethod: this._responseMethod, | ||
}; | ||
@@ -743,0 +796,0 @@ } |
@@ -169,2 +169,8 @@ (function (global, factory) { | ||
var ResponseMethod; | ||
(function (ResponseMethod) { | ||
ResponseMethod["POST"] = "post"; | ||
ResponseMethod["URL"] = "url"; | ||
ResponseMethod["MESSAGE"] = "message"; | ||
})(ResponseMethod || (ResponseMethod = {})); | ||
(function (ResponseStatus) { | ||
@@ -174,3 +180,2 @@ ResponseStatus["OK"] = "ok"; | ||
})(exports.ResponseStatus || (exports.ResponseStatus = {})); | ||
const POSTMESSAGE_RETURN_URL = '<postMessage>'; | ||
@@ -264,2 +269,7 @@ class RequestIdStorage { | ||
fragment.delete('command'); | ||
// Ignore messages without a responseMethod | ||
if (!fragment.has('responseMethod')) | ||
return null; | ||
const responseMethod = fragment.get('responseMethod'); | ||
fragment.delete('responseMethod'); | ||
// Ignore messages without a valid return path | ||
@@ -270,3 +280,3 @@ if (!fragment.has('returnURL')) | ||
fragment.delete('returnURL'); | ||
const answerByPostMessage = returnURL === POSTMESSAGE_RETURN_URL | ||
const answerByPostMessage = responseMethod === ResponseMethod.MESSAGE | ||
&& (window.opener || window.parent); | ||
@@ -299,3 +309,4 @@ // Only allow returning to same origin | ||
returnURL, | ||
source: answerByPostMessage ? (window.opener || window.parent) : null, | ||
responseMethod: responseMethod, | ||
source: responseMethod === ResponseMethod.MESSAGE ? (window.opener || window.parent) : null, | ||
}; | ||
@@ -349,3 +360,3 @@ } | ||
} | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args) { | ||
static prepareRedirectInvocation(targetURL, id, returnURL, command, args, responseMethod) { | ||
const targetUrl = new URL(targetURL); | ||
@@ -356,2 +367,3 @@ const fragment = new URLSearchParams(targetUrl.hash.substring(1)); | ||
fragment.set('command', command); | ||
fragment.set('responseMethod', responseMethod); | ||
if (Array.isArray(args)) { | ||
@@ -598,7 +610,13 @@ fragment.set('args', JSONUtils.stringify(args)); | ||
call(returnURL, command, handleHistoryBack = false, ...args) { | ||
this.callAndSaveLocalState(returnURL, null, command, handleHistoryBack, ...args); | ||
this._call(returnURL, ResponseMethod.URL, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndPOSTResponse(returnURL, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.POST, null, command, handleHistoryBack, ...args); | ||
} | ||
callAndSaveLocalState(returnURL, state, command, handleHistoryBack = false, ...args) { | ||
this._call(returnURL, ResponseMethod.URL, state, command, handleHistoryBack, ...args); | ||
} | ||
_call(returnURL, responseMethod, state, command, handleHistoryBack = false, ...args) { | ||
const id = RandomUtils.generateRandomId(); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args); | ||
const url = UrlRpcEncoder.prepareRedirectInvocation(this._target, id, returnURL, command, args, responseMethod); | ||
this._waitingRequests.add(id, command, state); | ||
@@ -671,4 +689,7 @@ if (handleHistoryBack) { | ||
this._id = message.data.id; | ||
this._postMessage = 'source' in message | ||
&& !('returnURL' in message && message.returnURL !== POSTMESSAGE_RETURN_URL); | ||
this._responseMethod = 'responseMethod' in message | ||
? message.responseMethod | ||
: 'source' in message && !('returnURL' in message) | ||
? ResponseMethod.MESSAGE | ||
: ResponseMethod.URL; | ||
this._returnURL = 'returnURL' in message ? message.returnURL : null; | ||
@@ -682,4 +703,5 @@ this._data = message.data; | ||
data: this._data, | ||
responseMethod: this._responseMethod, | ||
}; | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
if (this._source === window.opener) { | ||
@@ -709,3 +731,3 @@ obj.source = 'opener'; | ||
// TODO: Clear waiting request storage? | ||
if (this._postMessage) { | ||
if (this._responseMethod === ResponseMethod.MESSAGE) { | ||
// Send via postMessage (e.g., popup or url-persisted popup) | ||
@@ -736,12 +758,43 @@ let target; | ||
else if (this._returnURL) { | ||
// Send via top-level navigation | ||
window.location.href = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
if (this._responseMethod === ResponseMethod.URL) { | ||
// Send via top-level navigation | ||
const reply = UrlRpcEncoder.prepareRedirectReply(this, status, result); | ||
window.location.href = reply; | ||
} | ||
else if (this._responseMethod === ResponseMethod.POST) { | ||
// send via form to server | ||
const $form = document.createElement('form'); | ||
$form.setAttribute('method', 'post'); | ||
$form.setAttribute('action', this.returnURL); | ||
$form.setAttribute('style', 'display: none;'); | ||
const $statusInput = document.createElement('input'); | ||
$statusInput.setAttribute('type', 'text'); | ||
$statusInput.setAttribute('name', 'status'); | ||
$statusInput.setAttribute('value', status); | ||
$form.appendChild($statusInput); | ||
const $resultInput = document.createElement('input'); | ||
$resultInput.setAttribute('type', 'text'); | ||
$resultInput.setAttribute('name', 'result'); | ||
$resultInput.setAttribute('value', JSONUtils.stringify(result)); | ||
$form.appendChild($resultInput); | ||
const $idInput = document.createElement('input'); | ||
$idInput.setAttribute('type', 'text'); | ||
$idInput.setAttribute('name', 'rpcId'); | ||
$idInput.setAttribute('value', this.id.toString()); | ||
$form.appendChild($idInput); | ||
document.body.appendChild($form); | ||
$form.submit(); | ||
} | ||
} | ||
} | ||
toRequestObject() { | ||
if (this._responseMethod !== ResponseMethod.MESSAGE && !this._returnURL) { | ||
throw new Error('ReturnURL is needed'); | ||
} | ||
return { | ||
origin: this._origin, | ||
data: this._data, | ||
returnURL: this._returnURL || POSTMESSAGE_RETURN_URL, | ||
returnURL: this._returnURL || 'post-message', | ||
source: typeof this._source === 'string' ? this._source : null, | ||
responseMethod: this._responseMethod, | ||
}; | ||
@@ -748,0 +801,0 @@ } |
@@ -23,4 +23,10 @@ interface Message { | ||
returnURL: string; | ||
responseMethod: ResponseMethod; | ||
source: MessagePort | Window | ServiceWorker | string | null; | ||
} | ||
export declare enum ResponseMethod { | ||
POST = "post", | ||
URL = "url", | ||
MESSAGE = "message" | ||
} | ||
export declare enum ResponseStatus { | ||
@@ -30,3 +36,2 @@ OK = "ok", | ||
} | ||
export declare const POSTMESSAGE_RETURN_URL = "<postMessage>"; | ||
export {}; |
@@ -49,5 +49,7 @@ import { ResponseMessage } from './Messages'; | ||
call(returnURL: string, command: string, handleHistoryBack?: boolean, ...args: any[]): void; | ||
callAndPOSTResponse(returnURL: string, command: string, handleHistoryBack?: boolean, ...args: any[]): void; | ||
callAndSaveLocalState(returnURL: string, state: ObjectType | null, command: string, handleHistoryBack?: boolean, ...args: any[]): void; | ||
private _call; | ||
protected _receive(response: ResponseMessage, persistMessage?: boolean): boolean; | ||
private _rejectOnBack; | ||
} |
@@ -16,3 +16,3 @@ import { PostMessage, RedirectRequest, ResponseStatus } from './Messages'; | ||
private readonly _id; | ||
private readonly _postMessage; | ||
private readonly _responseMethod; | ||
private readonly _returnURL; | ||
@@ -19,0 +19,0 @@ private readonly _data; |
@@ -1,2 +0,2 @@ | ||
import { RedirectRequest, ResponseMessage, ResponseStatus } from './Messages'; | ||
import { RedirectRequest, ResponseMessage, ResponseStatus, ResponseMethod } from './Messages'; | ||
import { State } from './State'; | ||
@@ -8,4 +8,4 @@ export declare class UrlRpcEncoder { | ||
static prepareRedirectReply(state: State, status: ResponseStatus, result: any): string; | ||
static prepareRedirectInvocation(targetURL: string, id: number, returnURL: string, command: string, args: any[]): string; | ||
static prepareRedirectInvocation(targetURL: string, id: number, returnURL: string, command: string, args: any[], responseMethod: ResponseMethod): string; | ||
private static _setUrlFragment; | ||
} |
{ | ||
"name": "@nimiq/rpc", | ||
"version": "0.3.0", | ||
"version": "0.4.0-beta.1", | ||
"description": "RPC Client/Server", | ||
@@ -5,0 +5,0 @@ "repository": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
130151
2856