@interval/sdk
Advanced tools
Comparing version 0.33.0 to 0.34.0
@@ -0,1 +1,2 @@ | ||
import { AccessControlDefinition } from '../internalRpcSchema'; | ||
import { ExplicitIntervalActionDefinition, IntervalActionDefinition, IntervalActionHandler } from '../types'; | ||
@@ -8,3 +9,4 @@ export default class Action implements ExplicitIntervalActionDefinition { | ||
description?: string; | ||
access?: AccessControlDefinition; | ||
constructor(def: ExplicitIntervalActionDefinition | IntervalActionDefinition); | ||
} |
/// <reference types="node" /> | ||
import { AsyncLocalStorage } from 'async_hooks'; | ||
import { ActionEnvironment } from '../internalRpcSchema'; | ||
import type { IntervalActionStore, IntervalPageStore } from '../types'; | ||
import { Interval, InternalConfig } from '..'; | ||
import type { AsyncLocalStorage } from 'async_hooks'; | ||
declare let actionLocalStorage: AsyncLocalStorage<IntervalActionStore> | undefined; | ||
declare let pageLocalStorage: AsyncLocalStorage<IntervalPageStore> | undefined; | ||
export { actionLocalStorage, pageLocalStorage }; | ||
export declare const DEFAULT_WEBSOCKET_ENDPOINT = "wss://interval.com/websocket"; | ||
export declare function getHttpEndpoint(wsEndpoint: string): string; | ||
export declare const sleep: (ms: number) => Promise<unknown>; | ||
export declare const actionLocalStorage: AsyncLocalStorage<IntervalActionStore>; | ||
export declare const pageLocalStorage: AsyncLocalStorage<IntervalPageStore>; | ||
export default class IntervalClient { | ||
@@ -12,0 +13,0 @@ #private; |
@@ -39,5 +39,5 @@ "use strict"; | ||
}; | ||
var _IntervalClient_instances, _IntervalClient_interval, _IntervalClient_ghostOrgId, _IntervalClient_apiKey, _IntervalClient_endpoint, _IntervalClient_httpEndpoint, _IntervalClient_logger, _IntervalClient_retryIntervalMs, _IntervalClient_pingIntervalMs, _IntervalClient_closeUnresponsiveConnectionTimeoutMs, _IntervalClient_reinitializeBatchTimeoutMs, _IntervalClient_pingIntervalHandle, _IntervalClient_intentionallyClosed, _IntervalClient_config, _IntervalClient_actionDefinitions, _IntervalClient_pageDefinitions, _IntervalClient_actionHandlers, _IntervalClient_pageHandlers, _IntervalClient_walkRoutes, _IntervalClient_log_get, _IntervalClient_pageIOClients, _IntervalClient_ioResponseHandlers, _IntervalClient_pendingIOCalls, _IntervalClient_transactionLoadingStates, _IntervalClient_transactionCompleteCallbacks, _IntervalClient_ws, _IntervalClient_serverRpc, _IntervalClient_isConnected, _IntervalClient_isInitialized, _IntervalClient_reinitializeTimeout, _IntervalClient_resendPendingIOCalls, _IntervalClient_resendTransactionLoadingStates, _IntervalClient_findOrCreateGhostModeAccount, _IntervalClient_createSocketConnection, _IntervalClient_createRPCClient, _IntervalClient_initializeHost, _IntervalClient_send, _IntervalClient_sendLog, _IntervalClient_sendRedirect; | ||
var _IntervalClient_instances, _IntervalClient_interval, _IntervalClient_apiKey, _IntervalClient_endpoint, _IntervalClient_httpEndpoint, _IntervalClient_logger, _IntervalClient_retryIntervalMs, _IntervalClient_pingIntervalMs, _IntervalClient_closeUnresponsiveConnectionTimeoutMs, _IntervalClient_reinitializeBatchTimeoutMs, _IntervalClient_pingIntervalHandle, _IntervalClient_intentionallyClosed, _IntervalClient_config, _IntervalClient_actionDefinitions, _IntervalClient_pageDefinitions, _IntervalClient_actionHandlers, _IntervalClient_pageHandlers, _IntervalClient_walkRoutes, _IntervalClient_log_get, _IntervalClient_pageIOClients, _IntervalClient_ioResponseHandlers, _IntervalClient_pendingIOCalls, _IntervalClient_transactionLoadingStates, _IntervalClient_transactionCompleteCallbacks, _IntervalClient_ws, _IntervalClient_serverRpc, _IntervalClient_isConnected, _IntervalClient_isInitialized, _IntervalClient_reinitializeTimeout, _IntervalClient_resendPendingIOCalls, _IntervalClient_resendTransactionLoadingStates, _IntervalClient_createSocketConnection, _IntervalClient_createRPCHandlers, _IntervalClient_createRPCClient, _IntervalClient_initializeHost, _IntervalClient_send, _IntervalClient_sendLog, _IntervalClient_sendRedirect; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.pageLocalStorage = exports.actionLocalStorage = exports.sleep = exports.getHttpEndpoint = exports.DEFAULT_WEBSOCKET_ENDPOINT = void 0; | ||
exports.sleep = exports.getHttpEndpoint = exports.DEFAULT_WEBSOCKET_ENDPOINT = exports.pageLocalStorage = exports.actionLocalStorage = void 0; | ||
const zod_1 = require("zod"); | ||
@@ -47,3 +47,2 @@ const uuid_1 = require("uuid"); | ||
const node_fetch_1 = __importDefault(require("node-fetch")); | ||
const async_hooks_1 = require("async_hooks"); | ||
const superjson = __importStar(require("superjson")); | ||
@@ -60,7 +59,22 @@ const ISocket_1 = __importStar(require("./ISocket")); | ||
const TransactionLoadingState_1 = __importDefault(require("../classes/TransactionLoadingState")); | ||
const localConfig_1 = __importDefault(require("../localConfig")); | ||
const __1 = require(".."); | ||
const Page_1 = __importDefault(require("./Page")); | ||
const Layout_1 = require("./Layout"); | ||
const fileActionLoader_1 = __importDefault(require("../utils/fileActionLoader")); | ||
let actionLocalStorage; | ||
exports.actionLocalStorage = actionLocalStorage; | ||
let pageLocalStorage; | ||
exports.pageLocalStorage = pageLocalStorage; | ||
async function initAsyncLocalStorage() { | ||
try { | ||
if (typeof window === 'undefined') { | ||
const { default: { AsyncLocalStorage }, } = await Promise.resolve().then(() => __importStar(require('async_hooks'))); | ||
exports.actionLocalStorage = actionLocalStorage = new AsyncLocalStorage(); | ||
exports.pageLocalStorage = pageLocalStorage = new AsyncLocalStorage(); | ||
} | ||
} | ||
catch (err) { | ||
console.error('Failed initializing AsyncLocalStorage stores'); | ||
} | ||
} | ||
initAsyncLocalStorage(); | ||
exports.DEFAULT_WEBSOCKET_ENDPOINT = 'wss://interval.com/websocket'; | ||
@@ -77,4 +91,2 @@ function getHttpEndpoint(wsEndpoint) { | ||
exports.sleep = sleep; | ||
exports.actionLocalStorage = new async_hooks_1.AsyncLocalStorage(); | ||
exports.pageLocalStorage = new async_hooks_1.AsyncLocalStorage(); | ||
class IntervalClient { | ||
@@ -84,3 +96,2 @@ constructor(interval, config) { | ||
_IntervalClient_interval.set(this, void 0); | ||
_IntervalClient_ghostOrgId.set(this, void 0); | ||
_IntervalClient_apiKey.set(this, void 0); | ||
@@ -133,2 +144,5 @@ _IntervalClient_endpoint.set(this, exports.DEFAULT_WEBSOCKET_ENDPOINT); | ||
__classPrivateFieldSet(this, _IntervalClient_httpEndpoint, getHttpEndpoint(__classPrivateFieldGet(this, _IntervalClient_endpoint, "f")), "f"); | ||
if (config.setHostHandlers) { | ||
config.setHostHandlers(__classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_createRPCHandlers).call(this)); | ||
} | ||
} | ||
@@ -150,4 +164,20 @@ get isConnected() { | ||
async listen() { | ||
await this.initializeConnection(); | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_initializeHost).call(this); | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").setHostHandlers && __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
// in browser demo mode, we don't need to initialize the connection | ||
this.organization = { | ||
name: 'Demo Organization', | ||
slug: 'demo', | ||
}; | ||
this.environment = 'development'; | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_walkRoutes).call(this); | ||
const isInitialInitialization = !__classPrivateFieldGet(this, _IntervalClient_isInitialized, "f"); | ||
__classPrivateFieldSet(this, _IntervalClient_isInitialized, true, "f"); | ||
if (isInitialInitialization) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).prod(`🔗 Connected! Access your actions within the demo dashboard nearby.`); | ||
} | ||
} | ||
else { | ||
await this.initializeConnection(); | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_initializeHost).call(this); | ||
} | ||
} | ||
@@ -216,2 +246,7 @@ async initializeConnection() { | ||
} | ||
if (response.warnings.length) { | ||
for (const warning of response.warnings) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).warn(warning); | ||
} | ||
} | ||
if (response.invalidSlugs.length > 0) { | ||
@@ -239,3 +274,3 @@ __classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).warn('[Interval]', '⚠ Invalid slugs detected:\n'); | ||
exports.default = IntervalClient; | ||
_IntervalClient_interval = new WeakMap(), _IntervalClient_ghostOrgId = new WeakMap(), _IntervalClient_apiKey = new WeakMap(), _IntervalClient_endpoint = new WeakMap(), _IntervalClient_httpEndpoint = new WeakMap(), _IntervalClient_logger = new WeakMap(), _IntervalClient_retryIntervalMs = new WeakMap(), _IntervalClient_pingIntervalMs = new WeakMap(), _IntervalClient_closeUnresponsiveConnectionTimeoutMs = new WeakMap(), _IntervalClient_reinitializeBatchTimeoutMs = new WeakMap(), _IntervalClient_pingIntervalHandle = new WeakMap(), _IntervalClient_intentionallyClosed = new WeakMap(), _IntervalClient_config = new WeakMap(), _IntervalClient_actionDefinitions = new WeakMap(), _IntervalClient_pageDefinitions = new WeakMap(), _IntervalClient_actionHandlers = new WeakMap(), _IntervalClient_pageHandlers = new WeakMap(), _IntervalClient_pageIOClients = new WeakMap(), _IntervalClient_ioResponseHandlers = new WeakMap(), _IntervalClient_pendingIOCalls = new WeakMap(), _IntervalClient_transactionLoadingStates = new WeakMap(), _IntervalClient_transactionCompleteCallbacks = new WeakMap(), _IntervalClient_ws = new WeakMap(), _IntervalClient_serverRpc = new WeakMap(), _IntervalClient_isConnected = new WeakMap(), _IntervalClient_isInitialized = new WeakMap(), _IntervalClient_reinitializeTimeout = new WeakMap(), _IntervalClient_instances = new WeakSet(), _IntervalClient_walkRoutes = async function _IntervalClient_walkRoutes() { | ||
_IntervalClient_interval = new WeakMap(), _IntervalClient_apiKey = new WeakMap(), _IntervalClient_endpoint = new WeakMap(), _IntervalClient_httpEndpoint = new WeakMap(), _IntervalClient_logger = new WeakMap(), _IntervalClient_retryIntervalMs = new WeakMap(), _IntervalClient_pingIntervalMs = new WeakMap(), _IntervalClient_closeUnresponsiveConnectionTimeoutMs = new WeakMap(), _IntervalClient_reinitializeBatchTimeoutMs = new WeakMap(), _IntervalClient_pingIntervalHandle = new WeakMap(), _IntervalClient_intentionallyClosed = new WeakMap(), _IntervalClient_config = new WeakMap(), _IntervalClient_actionDefinitions = new WeakMap(), _IntervalClient_pageDefinitions = new WeakMap(), _IntervalClient_actionHandlers = new WeakMap(), _IntervalClient_pageHandlers = new WeakMap(), _IntervalClient_pageIOClients = new WeakMap(), _IntervalClient_ioResponseHandlers = new WeakMap(), _IntervalClient_pendingIOCalls = new WeakMap(), _IntervalClient_transactionLoadingStates = new WeakMap(), _IntervalClient_transactionCompleteCallbacks = new WeakMap(), _IntervalClient_ws = new WeakMap(), _IntervalClient_serverRpc = new WeakMap(), _IntervalClient_isConnected = new WeakMap(), _IntervalClient_isInitialized = new WeakMap(), _IntervalClient_reinitializeTimeout = new WeakMap(), _IntervalClient_instances = new WeakSet(), _IntervalClient_walkRoutes = async function _IntervalClient_walkRoutes() { | ||
const pageDefinitions = []; | ||
@@ -252,2 +287,3 @@ const actionDefinitions = []; | ||
unlisted: router.unlisted, | ||
access: router.access, | ||
}); | ||
@@ -273,5 +309,6 @@ if (router.handler) { | ||
let fileSystemRoutes; | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").routesDirectory) { | ||
if (typeof window === 'undefined' && __classPrivateFieldGet(this, _IntervalClient_config, "f").routesDirectory) { | ||
try { | ||
fileSystemRoutes = await (0, fileActionLoader_1.default)(__classPrivateFieldGet(this, _IntervalClient_config, "f").routesDirectory, __classPrivateFieldGet(this, _IntervalClient_logger, "f")); | ||
const { default: loadRoutesFromFileSystem } = await Promise.resolve().then(() => __importStar(require('../utils/fileActionLoader'))); | ||
fileSystemRoutes = await loadRoutesFromFileSystem(__classPrivateFieldGet(this, _IntervalClient_config, "f").routesDirectory, __classPrivateFieldGet(this, _IntervalClient_logger, "f")); | ||
} | ||
@@ -384,24 +421,2 @@ catch (err) { | ||
} | ||
}, _IntervalClient_findOrCreateGhostModeAccount = async function _IntervalClient_findOrCreateGhostModeAccount() { | ||
let config = await localConfig_1.default.get(); | ||
let ghostOrgId = config === null || config === void 0 ? void 0 : config.ghostOrgId; | ||
if (!ghostOrgId) { | ||
const response = await (0, node_fetch_1.default)(__classPrivateFieldGet(this, _IntervalClient_httpEndpoint, "f") + '/api/auth/ghost/create', { | ||
method: 'POST', | ||
headers: { | ||
'Content-Type': 'application/json', | ||
}, | ||
}) | ||
.then(r => r.json()) | ||
.then(r => internalRpcSchema_1.CREATE_GHOST_MODE_ACCOUNT.returns.parseAsync(r)) | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug(err); | ||
throw new __1.IntervalError('Received invalid API response.'); | ||
}); | ||
await localConfig_1.default.write({ | ||
ghostOrgId: response.ghostOrgId, | ||
}); | ||
ghostOrgId = response.ghostOrgId; | ||
} | ||
return ghostOrgId; | ||
}, _IntervalClient_createSocketConnection = | ||
@@ -418,12 +433,2 @@ /** | ||
} | ||
else if (!__classPrivateFieldGet(this, _IntervalClient_apiKey, "f")) { | ||
try { | ||
__classPrivateFieldSet(this, _IntervalClient_ghostOrgId, await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_findOrCreateGhostModeAccount).call(this), "f"); | ||
headers['x-ghost-org-id'] = __classPrivateFieldGet(this, _IntervalClient_ghostOrgId, "f"); | ||
} | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('Failed creating ghost mode account:', err); | ||
// User-facing error will be shown when trying to connect below | ||
} | ||
} | ||
const ws = new ISocket_1.default(new ws_1.WebSocket(__classPrivateFieldGet(this, _IntervalClient_endpoint, "f"), { | ||
@@ -502,78 +507,285 @@ headers, | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_initializeHost).call(this); | ||
}, _IntervalClient_createRPCClient = function _IntervalClient_createRPCClient(requestId) { | ||
if (!__classPrivateFieldGet(this, _IntervalClient_ws, "f")) { | ||
throw new Error('ISocket not initialized'); | ||
} | ||
const serverRpc = new DuplexRPCClient_1.DuplexRPCClient({ | ||
communicator: __classPrivateFieldGet(this, _IntervalClient_ws, "f"), | ||
canCall: internalRpcSchema_1.wsServerSchema, | ||
canRespondTo: internalRpcSchema_1.hostSchema, | ||
handlers: { | ||
OPEN_PAGE: async (inputs) => { | ||
if (!this.organization) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('No organization defined'); | ||
return { type: 'ERROR' }; | ||
}, _IntervalClient_createRPCHandlers = function _IntervalClient_createRPCHandlers(requestId) { | ||
const intervalClient = this; | ||
return { | ||
START_TRANSACTION: async (inputs) => { | ||
if (!intervalClient.organization) { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).error('No organization defined'); | ||
return; | ||
} | ||
const { action, transactionId } = inputs; | ||
const actionHandler = __classPrivateFieldGet(intervalClient, _IntervalClient_actionHandlers, "f").get(action.slug); | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).debug(actionHandler); | ||
if (!actionHandler) { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No actionHandler called', action.slug); | ||
return; | ||
} | ||
const client = new IOClient_1.IOClient({ | ||
logger: __classPrivateFieldGet(intervalClient, _IntervalClient_logger, "f"), | ||
send: async (ioRenderInstruction) => { | ||
var _a; | ||
const ioCall = JSON.stringify(ioRenderInstruction); | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_pendingIOCalls, "f").set(transactionId, ioCall); | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
await ((_a = __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers()) === null || _a === void 0 ? void 0 : _a.RENDER({ | ||
transactionId, | ||
toRender: ioCall, | ||
})); | ||
} | ||
else { | ||
await __classPrivateFieldGet(intervalClient, _IntervalClient_instances, "m", _IntervalClient_send).call(intervalClient, 'SEND_IO_CALL', { | ||
transactionId, | ||
ioCall, | ||
}); | ||
} | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_transactionLoadingStates, "f").delete(transactionId); | ||
}, | ||
isDemo: !!__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers, | ||
// onAddInlineAction: handler => { | ||
// const key = v4() | ||
// intervalClient.#actionHandlers.set(key, handler) | ||
// return key | ||
// }, | ||
}); | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_ioResponseHandlers, "f").set(transactionId, client.onResponse.bind(client)); | ||
// To maintain consistent ordering for logs despite network race conditions | ||
let logIndex = 0; | ||
let { params, paramsMeta } = inputs; | ||
if (params && paramsMeta) { | ||
params = superjson.deserialize({ | ||
json: params, | ||
meta: paramsMeta, | ||
}); | ||
} | ||
const ctx = { | ||
user: inputs.user, | ||
// TODO: Remove intervalClient when all active SDKs support superjson | ||
params: (0, deserialize_1.deserializeDates)(params), | ||
environment: inputs.environment, | ||
organization: intervalClient.organization, | ||
action, | ||
log: (...args) => __classPrivateFieldGet(intervalClient, _IntervalClient_instances, "m", _IntervalClient_sendLog).call(intervalClient, transactionId, logIndex++, ...args), | ||
notify: async (config) => { | ||
await __classPrivateFieldGet(intervalClient, _IntervalClient_interval, "f").notify({ | ||
...config, | ||
transactionId: inputs.transactionId, | ||
}); | ||
}, | ||
loading: new TransactionLoadingState_1.default({ | ||
logger: __classPrivateFieldGet(intervalClient, _IntervalClient_logger, "f"), | ||
send: async (loadingState) => { | ||
var _a; | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_transactionLoadingStates, "f").set(transactionId, loadingState); | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
await ((_a = __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers()) === null || _a === void 0 ? void 0 : _a.LOADING_STATE({ | ||
transactionId, | ||
...loadingState, | ||
})); | ||
} | ||
else { | ||
await __classPrivateFieldGet(intervalClient, _IntervalClient_instances, "m", _IntervalClient_send).call(intervalClient, 'SEND_LOADING_CALL', { | ||
transactionId, | ||
...loadingState, | ||
}); | ||
} | ||
}, | ||
}), | ||
redirect: (props) => __classPrivateFieldGet(intervalClient, _IntervalClient_instances, "m", _IntervalClient_sendRedirect).call(intervalClient, transactionId, props), | ||
}; | ||
const { io } = client; | ||
const handleAction = () => { | ||
actionHandler(client.io, ctx) | ||
.then(res => { | ||
// Allow actions to return data even after being canceled | ||
var _a; | ||
const { json, meta } = superjson.serialize(res); | ||
const result = { | ||
schemaVersion: internalRpcSchema_1.TRANSACTION_RESULT_SCHEMA_VERSION, | ||
status: 'SUCCESS', | ||
data: (_a = json) !== null && _a !== void 0 ? _a : null, | ||
meta, | ||
}; | ||
return result; | ||
}) | ||
.catch(err => { | ||
// Action did not catch the cancellation error | ||
if (err instanceof IOError_1.default && err.kind === 'CANCELED') | ||
throw err; | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_logger, "f").error(err); | ||
const result = { | ||
schemaVersion: internalRpcSchema_1.TRANSACTION_RESULT_SCHEMA_VERSION, | ||
status: 'FAILURE', | ||
data: err.message | ||
? { error: err.name, message: err.message } | ||
: null, | ||
}; | ||
return result; | ||
}) | ||
.then(async (res) => { | ||
var _a; | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
(_a = __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers()) === null || _a === void 0 ? void 0 : _a.TRANSACTION_COMPLETED({ | ||
transactionId, | ||
resultStatus: res.status, | ||
result: JSON.stringify(res), | ||
}); | ||
} | ||
else { | ||
await __classPrivateFieldGet(intervalClient, _IntervalClient_instances, "m", _IntervalClient_send).call(intervalClient, 'MARK_TRANSACTION_COMPLETE', { | ||
transactionId, | ||
result: JSON.stringify(res), | ||
}); | ||
} | ||
if (requestId) { | ||
const callbacks = __classPrivateFieldGet(intervalClient, _IntervalClient_transactionCompleteCallbacks, "f").get(requestId); | ||
if (callbacks) { | ||
const [resolve] = callbacks; | ||
resolve(); | ||
} | ||
else { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No transaction complete callbacks found for requestId', requestId); | ||
} | ||
} | ||
}) | ||
.catch(err => { | ||
if (err instanceof IOError_1.default) { | ||
switch (err.kind) { | ||
case 'CANCELED': | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).prod('Transaction canceled for action', action.slug); | ||
break; | ||
case 'TRANSACTION_CLOSED': | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).prod('Attempted to make IO call after transaction already closed in action', action.slug); | ||
break; | ||
} | ||
} | ||
else { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Error sending action response', err); | ||
} | ||
if (requestId) { | ||
const callbacks = __classPrivateFieldGet(intervalClient, _IntervalClient_transactionCompleteCallbacks, "f").get(requestId); | ||
if (callbacks) { | ||
const [_, reject] = callbacks; | ||
reject(err); | ||
} | ||
else { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No transaction complete callbacks found for requestId', requestId); | ||
} | ||
} | ||
}) | ||
.finally(() => { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_pendingIOCalls, "f").delete(transactionId); | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_transactionLoadingStates, "f").delete(transactionId); | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_ioResponseHandlers, "f").delete(transactionId); | ||
for (const key of client.inlineActionKeys.values()) { | ||
__classPrivateFieldGet(intervalClient, _IntervalClient_actionHandlers, "f").delete(key); | ||
} | ||
}); | ||
}; | ||
if (actionLocalStorage) { | ||
actionLocalStorage.run({ io, ctx }, () => { | ||
handleAction(); | ||
}); | ||
} | ||
else { | ||
handleAction(); | ||
} | ||
return; | ||
}, | ||
IO_RESPONSE: async (inputs) => { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('got io response', inputs); | ||
try { | ||
const ioResp = ioSchema_1.IO_RESPONSE.parse(JSON.parse(inputs.value)); | ||
const replyHandler = __classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").get(ioResp.transactionId); | ||
if (!replyHandler) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('Missing reply handler for', inputs.transactionId); | ||
return; | ||
} | ||
const { pageKey } = inputs; | ||
const pageHandler = __classPrivateFieldGet(this, _IntervalClient_pageHandlers, "f").get(inputs.page.slug); | ||
if (!pageHandler) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No app handler called', inputs.page.slug); | ||
return { type: 'ERROR' }; | ||
replyHandler(ioResp); | ||
} | ||
catch (err) { | ||
if (err instanceof zod_1.ZodError) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Received invalid IO response:', inputs); | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug(err); | ||
} | ||
let { params, paramsMeta } = inputs; | ||
if (params && paramsMeta) { | ||
params = superjson.deserialize({ | ||
json: params, | ||
meta: paramsMeta, | ||
}); | ||
else { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Failed handling IO response:', err); | ||
} | ||
const ctx = { | ||
user: inputs.user, | ||
params: (0, deserialize_1.deserializeDates)(params), | ||
environment: inputs.environment, | ||
organization: this.organization, | ||
page: inputs.page, | ||
}; | ||
let page; | ||
let menuItems = undefined; | ||
let renderInstruction = undefined; | ||
let errors = []; | ||
const MAX_PAGE_RETRIES = 5; | ||
const sendPage = async () => { | ||
if (page instanceof Layout_1.Basic) { | ||
const pageLayout = { | ||
kind: 'BASIC', | ||
title: page.title === undefined | ||
? undefined | ||
: typeof page.title === 'string' | ||
? page.title | ||
: null, | ||
description: page.description === undefined | ||
? undefined | ||
: typeof page.description === 'string' | ||
? page.description | ||
: null, | ||
menuItems, | ||
children: renderInstruction, | ||
errors, | ||
}; | ||
if (page.metadata) { | ||
const items = []; | ||
for (const pageItem of page.metadata) { | ||
let { label, value, error, ...rest } = pageItem; | ||
if (typeof value === 'function' || value instanceof Promise) { | ||
items.push({ ...rest, label }); | ||
} | ||
else { | ||
items.push({ ...rest, label, value, error }); | ||
} | ||
} | ||
}, | ||
OPEN_PAGE: async (inputs) => { | ||
if (!this.organization) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('No organization defined'); | ||
return { type: 'ERROR' }; | ||
} | ||
const { pageKey } = inputs; | ||
const pageHandler = __classPrivateFieldGet(this, _IntervalClient_pageHandlers, "f").get(inputs.page.slug); | ||
if (!pageHandler) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No app handler called', inputs.page.slug); | ||
return { type: 'ERROR' }; | ||
} | ||
let { params, paramsMeta } = inputs; | ||
if (params && paramsMeta) { | ||
params = superjson.deserialize({ | ||
json: params, | ||
meta: paramsMeta, | ||
}); | ||
} | ||
const ctx = { | ||
user: inputs.user, | ||
params: (0, deserialize_1.deserializeDates)(params), | ||
environment: inputs.environment, | ||
organization: this.organization, | ||
page: inputs.page, | ||
}; | ||
let page; | ||
let menuItems = undefined; | ||
let renderInstruction = undefined; | ||
let errors = []; | ||
const MAX_PAGE_RETRIES = 5; | ||
const sendPage = async () => { | ||
var _a; | ||
if (page instanceof Layout_1.Basic) { | ||
const pageLayout = { | ||
kind: 'BASIC', | ||
title: page.title === undefined | ||
? undefined | ||
: typeof page.title === 'string' | ||
? page.title | ||
: null, | ||
description: page.description === undefined | ||
? undefined | ||
: typeof page.description === 'string' | ||
? page.description | ||
: null, | ||
menuItems, | ||
children: renderInstruction, | ||
errors, | ||
}; | ||
if (page.metadata) { | ||
const items = []; | ||
for (const pageItem of page.metadata) { | ||
let { label, value, error } = pageItem; | ||
if (typeof value === 'function' || value instanceof Promise) { | ||
items.push({ label }); | ||
} | ||
const { json, meta } = superjson.serialize(items); | ||
if (json) { | ||
pageLayout.metadata = { | ||
json: json, | ||
meta, | ||
}; | ||
else { | ||
items.push({ label, value, error }); | ||
} | ||
} | ||
const { json, meta } = superjson.serialize(items); | ||
if (json) { | ||
pageLayout.metadata = { | ||
json: json, | ||
meta, | ||
}; | ||
} | ||
} | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
await ((_a = __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers()) === null || _a === void 0 ? void 0 : _a.RENDER_PAGE({ | ||
pageKey, | ||
page: JSON.stringify(pageLayout), | ||
hostInstanceId: 'demo', | ||
})); | ||
} | ||
else { | ||
for (let i = 0; i < MAX_PAGE_RETRIES; i++) { | ||
@@ -595,83 +807,107 @@ try { | ||
} | ||
}; | ||
// What follows is a pretty convoluted way to coalesce | ||
// `scheduleSendPage` calls into non-clobbering/overlapping | ||
// `sendPage `calls. This can probably be simplified but I | ||
// can't think of a better way at the moment. | ||
// Tracks whether a send is currently in progress | ||
let sendPagePromise = null; | ||
// Keeps track of a brief timeout to coalesce rapid send calls | ||
let pageSendTimeout = null; | ||
// Tracks whether a new send needs to happen after the current one | ||
let newPageScheduled = false; | ||
const processSendPage = () => { | ||
newPageScheduled = false; | ||
pageSendTimeout = null; | ||
sendPagePromise = sendPage() | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(`Failed sending page with key ${pageKey}`, err); | ||
}) | ||
.finally(() => { | ||
sendPagePromise = null; | ||
if (newPageScheduled) { | ||
scheduleSendPage(); | ||
} | ||
}); | ||
}; | ||
const scheduleSendPage = () => { | ||
newPageScheduled = true; | ||
if (sendPagePromise) | ||
return; | ||
if (pageSendTimeout) | ||
return; | ||
pageSendTimeout = setTimeout(processSendPage, 0); | ||
}; | ||
const client = new IOClient_1.IOClient({ | ||
logger: __classPrivateFieldGet(this, _IntervalClient_logger, "f"), | ||
send: async (instruction) => { | ||
renderInstruction = instruction; | ||
} | ||
}; | ||
// What follows is a pretty convoluted way to coalesce | ||
// `scheduleSendPage` calls into non-clobbering/overlapping | ||
// `sendPage `calls. This can probably be simplified but I | ||
// can't think of a better way at the moment. | ||
// Tracks whether a send is currently in progress | ||
let sendPagePromise = null; | ||
// Keeps track of a brief timeout to coalesce rapid send calls | ||
let pageSendTimeout = null; | ||
// Tracks whether a new send needs to happen after the current one | ||
let newPageScheduled = false; | ||
const processSendPage = () => { | ||
newPageScheduled = false; | ||
pageSendTimeout = null; | ||
sendPagePromise = sendPage() | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(`Failed sending page with key ${pageKey}`, err); | ||
}) | ||
.finally(() => { | ||
sendPagePromise = null; | ||
if (newPageScheduled) { | ||
scheduleSendPage(); | ||
}, | ||
// onAddInlineAction: () => { | ||
// const key = v4() | ||
// this.#actionHandlers.set(key, handler) | ||
// return key | ||
// }, | ||
} | ||
}); | ||
const { io: { group, display }, } = client; | ||
__classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").set(pageKey, client); | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").set(pageKey, client.onResponse.bind(client)); | ||
const pageError = (error, layoutKey) => { | ||
if (error instanceof Error) { | ||
return { | ||
layoutKey, | ||
error: error.name, | ||
message: error.message, | ||
}; | ||
}; | ||
const scheduleSendPage = () => { | ||
newPageScheduled = true; | ||
if (sendPagePromise) | ||
return; | ||
if (pageSendTimeout) | ||
return; | ||
pageSendTimeout = setTimeout(processSendPage, 0); | ||
}; | ||
const client = new IOClient_1.IOClient({ | ||
logger: __classPrivateFieldGet(this, _IntervalClient_logger, "f"), | ||
send: async (instruction) => { | ||
renderInstruction = instruction; | ||
scheduleSendPage(); | ||
}, | ||
isDemo: !!__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers, | ||
// onAddInlineAction: () => { | ||
// const key = v4() | ||
// this.#actionHandlers.set(key, handler) | ||
// return key | ||
// }, | ||
}); | ||
const { io: { group, display }, } = client; | ||
__classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").set(pageKey, client); | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").set(pageKey, client.onResponse.bind(client)); | ||
const pageError = (error, layoutKey) => { | ||
if (error instanceof Error) { | ||
return { | ||
layoutKey, | ||
error: error.name, | ||
message: error.message, | ||
}; | ||
} | ||
else { | ||
return { | ||
layoutKey, | ||
error: 'Unknown error', | ||
message: String(error), | ||
}; | ||
} | ||
}; | ||
const handlePage = () => { | ||
pageHandler(display, ctx) | ||
.then(res => { | ||
page = res; | ||
if (typeof page.title === 'function') { | ||
try { | ||
page.title = page.title(); | ||
} | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'title')); | ||
} | ||
} | ||
else { | ||
return { | ||
layoutKey, | ||
error: 'Unknown error', | ||
message: String(error), | ||
}; | ||
if (page.title instanceof Promise) { | ||
page.title | ||
.then(title => { | ||
page.title = title; | ||
scheduleSendPage(); | ||
}) | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'title')); | ||
scheduleSendPage(); | ||
}); | ||
} | ||
}; | ||
exports.pageLocalStorage.run({ display, ctx }, () => { | ||
pageHandler(display, ctx) | ||
.then(res => { | ||
page = res; | ||
if (typeof page.title === 'function') { | ||
if (page.description) { | ||
if (typeof page.description === 'function') { | ||
try { | ||
page.title = page.title(); | ||
page.description = page.description(); | ||
} | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'title')); | ||
errors.push(pageError(err, 'description')); | ||
} | ||
} | ||
if (page.title instanceof Promise) { | ||
page.title | ||
.then(title => { | ||
page.title = title; | ||
if (page.description instanceof Promise) { | ||
page.description | ||
.then(description => { | ||
page.description = description; | ||
scheduleSendPage(); | ||
@@ -681,286 +917,114 @@ }) | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'title')); | ||
errors.push(pageError(err, 'description')); | ||
scheduleSendPage(); | ||
}); | ||
} | ||
if (page.description) { | ||
if (typeof page.description === 'function') { | ||
try { | ||
page.description = page.description(); | ||
} | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'description')); | ||
} | ||
} | ||
if (page.description instanceof Promise) { | ||
page.description | ||
.then(description => { | ||
page.description = description; | ||
scheduleSendPage(); | ||
}) | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err, 'description')); | ||
scheduleSendPage(); | ||
}); | ||
} | ||
} | ||
if (page.menuItems) { | ||
menuItems = page.menuItems.map(menuItem => { | ||
// if ( | ||
// 'action' in menuItem && | ||
// typeof menuItem['action'] === 'function' | ||
// ) { | ||
// const inlineAction = client.addInlineAction(menuItem.action) | ||
// return { | ||
// ...menuItem, | ||
// inlineAction, | ||
// } | ||
// } | ||
return menuItem; | ||
}); | ||
} | ||
if (page instanceof Layout_1.Basic) { | ||
const { metadata } = page; | ||
if (metadata) { | ||
for (let i = 0; i < metadata.length; i++) { | ||
let { value } = metadata[i]; | ||
if (typeof value === 'function') { | ||
try { | ||
value = value(); | ||
metadata[i].value = value; | ||
} | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
const error = pageError(err, 'metadata'); | ||
errors.push(error); | ||
metadata[i].value = null; | ||
metadata[i].error = error.message; | ||
} | ||
} | ||
if (page.menuItems) { | ||
menuItems = page.menuItems.map(menuItem => { | ||
// if ( | ||
// 'action' in menuItem && | ||
// typeof menuItem['action'] === 'function' | ||
// ) { | ||
// const inlineAction = client.addInlineAction(menuItem.action) | ||
// return { | ||
// ...menuItem, | ||
// inlineAction, | ||
// } | ||
// } | ||
return menuItem; | ||
}); | ||
} | ||
if (page instanceof Layout_1.Basic) { | ||
const { metadata } = page; | ||
if (metadata) { | ||
for (let i = 0; i < metadata.length; i++) { | ||
let { value } = metadata[i]; | ||
if (typeof value === 'function') { | ||
try { | ||
value = value(); | ||
metadata[i].value = value; | ||
} | ||
if (value instanceof Promise) { | ||
value | ||
.then(resolved => { | ||
metadata[i].value = resolved; | ||
scheduleSendPage(); | ||
}) | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
const error = pageError(err, 'metadata'); | ||
errors.push(error); | ||
metadata[i].value = null; | ||
metadata[i].error = error.message; | ||
scheduleSendPage(); | ||
}); | ||
catch (err) { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
const error = pageError(err, 'metadata'); | ||
errors.push(error); | ||
metadata[i].value = null; | ||
metadata[i].error = error.message; | ||
} | ||
} | ||
if (value instanceof Promise) { | ||
value | ||
.then(resolved => { | ||
metadata[i].value = resolved; | ||
scheduleSendPage(); | ||
}) | ||
.catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
const error = pageError(err, 'metadata'); | ||
errors.push(error); | ||
metadata[i].value = null; | ||
metadata[i].error = error.message; | ||
scheduleSendPage(); | ||
}); | ||
} | ||
} | ||
} | ||
if (page.children) { | ||
group(page.children).then(() => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").debug('Initial children render complete for pageKey', pageKey); | ||
}); | ||
} | ||
else { | ||
scheduleSendPage(); | ||
} | ||
}) | ||
.catch(async (err) => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err)); | ||
const pageLayout = { | ||
kind: 'BASIC', | ||
errors, | ||
}; | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_PAGE', { | ||
pageKey, | ||
page: JSON.stringify(pageLayout), | ||
}); | ||
}); | ||
}); | ||
return { | ||
type: 'SUCCESS', | ||
pageKey, | ||
}; | ||
}, | ||
CLOSE_PAGE: async (inputs) => { | ||
const client = __classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").get(inputs.pageKey); | ||
if (client) { | ||
for (const key of client.inlineActionKeys.values()) { | ||
__classPrivateFieldGet(this, _IntervalClient_actionHandlers, "f").delete(key); | ||
} | ||
client.inlineActionKeys.clear(); | ||
__classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").delete(inputs.pageKey); | ||
} | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").delete(inputs.pageKey); | ||
}, | ||
START_TRANSACTION: async (inputs) => { | ||
if (!this.organization) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('No organization defined'); | ||
return; | ||
} | ||
const { action, transactionId } = inputs; | ||
const actionHandler = __classPrivateFieldGet(this, _IntervalClient_actionHandlers, "f").get(action.slug); | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug(actionHandler); | ||
if (!actionHandler) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No actionHandler called', action.slug); | ||
return; | ||
} | ||
const client = new IOClient_1.IOClient({ | ||
logger: __classPrivateFieldGet(this, _IntervalClient_logger, "f"), | ||
send: async (ioRenderInstruction) => { | ||
const ioCall = JSON.stringify(ioRenderInstruction); | ||
__classPrivateFieldGet(this, _IntervalClient_pendingIOCalls, "f").set(transactionId, ioCall); | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_IO_CALL', { | ||
transactionId, | ||
ioCall, | ||
if (page.children) { | ||
group(page.children).then(() => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").debug('Initial children render complete for pageKey', pageKey); | ||
}); | ||
__classPrivateFieldGet(this, _IntervalClient_transactionLoadingStates, "f").delete(transactionId); | ||
}, | ||
// onAddInlineAction: handler => { | ||
// const key = v4() | ||
// this.#actionHandlers.set(key, handler) | ||
// return key | ||
// }, | ||
}); | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").set(transactionId, client.onResponse.bind(client)); | ||
// To maintain consistent ordering for logs despite network race conditions | ||
let logIndex = 0; | ||
let { params, paramsMeta } = inputs; | ||
if (params && paramsMeta) { | ||
params = superjson.deserialize({ | ||
json: params, | ||
meta: paramsMeta, | ||
}); | ||
} | ||
const ctx = { | ||
user: inputs.user, | ||
// TODO: Remove this when all active SDKs support superjson | ||
params: (0, deserialize_1.deserializeDates)(params), | ||
environment: inputs.environment, | ||
organization: this.organization, | ||
action, | ||
log: (...args) => __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_sendLog).call(this, transactionId, logIndex++, ...args), | ||
notify: async (config) => { | ||
await __classPrivateFieldGet(this, _IntervalClient_interval, "f").notify({ | ||
...config, | ||
transactionId: inputs.transactionId, | ||
}); | ||
}, | ||
loading: new TransactionLoadingState_1.default({ | ||
logger: __classPrivateFieldGet(this, _IntervalClient_logger, "f"), | ||
send: async (loadingState) => { | ||
__classPrivateFieldGet(this, _IntervalClient_transactionLoadingStates, "f").set(transactionId, loadingState); | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_LOADING_CALL', { | ||
transactionId, | ||
...loadingState, | ||
}); | ||
}, | ||
}), | ||
redirect: (props) => __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_sendRedirect).call(this, transactionId, props), | ||
}; | ||
const { io } = client; | ||
exports.actionLocalStorage.run({ io, ctx }, () => { | ||
actionHandler(client.io, ctx) | ||
.then(res => { | ||
// Allow actions to return data even after being canceled | ||
var _a; | ||
const { json, meta } = superjson.serialize(res); | ||
const result = { | ||
schemaVersion: internalRpcSchema_1.TRANSACTION_RESULT_SCHEMA_VERSION, | ||
status: 'SUCCESS', | ||
data: (_a = json) !== null && _a !== void 0 ? _a : null, | ||
meta, | ||
}; | ||
return result; | ||
}) | ||
.catch(err => { | ||
// Action did not catch the cancellation error | ||
if (err instanceof IOError_1.default && err.kind === 'CANCELED') | ||
throw err; | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
const result = { | ||
schemaVersion: internalRpcSchema_1.TRANSACTION_RESULT_SCHEMA_VERSION, | ||
status: 'FAILURE', | ||
data: err.message | ||
? { error: err.name, message: err.message } | ||
: null, | ||
}; | ||
return result; | ||
}) | ||
.then(async (res) => { | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'MARK_TRANSACTION_COMPLETE', { | ||
transactionId, | ||
result: JSON.stringify(res), | ||
}); | ||
if (requestId) { | ||
const callbacks = __classPrivateFieldGet(this, _IntervalClient_transactionCompleteCallbacks, "f").get(requestId); | ||
if (callbacks) { | ||
const [resolve] = callbacks; | ||
resolve(); | ||
} | ||
else { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No transaction complete callbacks found for requestId', requestId); | ||
} | ||
} | ||
}) | ||
.catch(err => { | ||
if (err instanceof IOError_1.default) { | ||
switch (err.kind) { | ||
case 'CANCELED': | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).prod('Transaction canceled for action', action.slug); | ||
break; | ||
case 'TRANSACTION_CLOSED': | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).prod('Attempted to make IO call after transaction already closed in action', action.slug); | ||
break; | ||
} | ||
} | ||
else { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Error sending action response', err); | ||
} | ||
if (requestId) { | ||
const callbacks = __classPrivateFieldGet(this, _IntervalClient_transactionCompleteCallbacks, "f").get(requestId); | ||
if (callbacks) { | ||
const [_, reject] = callbacks; | ||
reject(err); | ||
} | ||
else { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('No transaction complete callbacks found for requestId', requestId); | ||
} | ||
} | ||
}) | ||
.finally(() => { | ||
__classPrivateFieldGet(this, _IntervalClient_pendingIOCalls, "f").delete(transactionId); | ||
__classPrivateFieldGet(this, _IntervalClient_transactionLoadingStates, "f").delete(transactionId); | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").delete(transactionId); | ||
for (const key of client.inlineActionKeys.values()) { | ||
__classPrivateFieldGet(this, _IntervalClient_actionHandlers, "f").delete(key); | ||
} | ||
}); | ||
}); | ||
return; | ||
}, | ||
IO_RESPONSE: async (inputs) => { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('got io response', inputs); | ||
try { | ||
const ioResp = ioSchema_1.IO_RESPONSE.parse(JSON.parse(inputs.value)); | ||
const replyHandler = __classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").get(ioResp.transactionId); | ||
if (!replyHandler) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug('Missing reply handler for', inputs.transactionId); | ||
return; | ||
} | ||
replyHandler(ioResp); | ||
} | ||
catch (err) { | ||
if (err instanceof zod_1.ZodError) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Received invalid IO response:', inputs); | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).debug(err); | ||
} | ||
else { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).error('Failed handling IO response:', err); | ||
scheduleSendPage(); | ||
} | ||
}) | ||
.catch(async (err) => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error(err); | ||
errors.push(pageError(err)); | ||
const pageLayout = { | ||
kind: 'BASIC', | ||
errors, | ||
}; | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_PAGE', { | ||
pageKey, | ||
page: JSON.stringify(pageLayout), | ||
}); | ||
}); | ||
}; | ||
if (pageLocalStorage) { | ||
pageLocalStorage.run({ display, ctx }, () => { | ||
handlePage(); | ||
}); | ||
} | ||
else { | ||
handlePage(); | ||
} | ||
return { | ||
type: 'SUCCESS', | ||
pageKey, | ||
}; | ||
}, | ||
CLOSE_PAGE: async (inputs) => { | ||
const client = __classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").get(inputs.pageKey); | ||
if (client) { | ||
for (const key of client.inlineActionKeys.values()) { | ||
__classPrivateFieldGet(this, _IntervalClient_actionHandlers, "f").delete(key); | ||
} | ||
}, | ||
client.inlineActionKeys.clear(); | ||
__classPrivateFieldGet(this, _IntervalClient_pageIOClients, "f").delete(inputs.pageKey); | ||
} | ||
__classPrivateFieldGet(this, _IntervalClient_ioResponseHandlers, "f").delete(inputs.pageKey); | ||
}, | ||
}; | ||
}, _IntervalClient_createRPCClient = function _IntervalClient_createRPCClient(requestId) { | ||
if (!__classPrivateFieldGet(this, _IntervalClient_ws, "f")) { | ||
throw new Error('ISocket not initialized'); | ||
} | ||
const serverRpc = new DuplexRPCClient_1.DuplexRPCClient({ | ||
communicator: __classPrivateFieldGet(this, _IntervalClient_ws, "f"), | ||
canCall: internalRpcSchema_1.wsServerSchema, | ||
canRespondTo: internalRpcSchema_1.hostSchema, | ||
handlers: __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_createRPCHandlers).call(this, requestId), | ||
}); | ||
@@ -1008,2 +1072,7 @@ __classPrivateFieldSet(this, _IntervalClient_serverRpc, serverRpc, "f"); | ||
} | ||
if (response.warnings.length) { | ||
for (const warning of response.warnings) { | ||
__classPrivateFieldGet(this, _IntervalClient_instances, "a", _IntervalClient_log_get).warn(warning); | ||
} | ||
} | ||
this.organization = response.organization; | ||
@@ -1036,2 +1105,3 @@ this.environment = response.environment; | ||
}, _IntervalClient_sendLog = async function _IntervalClient_sendLog(transactionId, index, ...args) { | ||
var _a; | ||
if (!args.length) | ||
@@ -1054,11 +1124,24 @@ return; | ||
} | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_LOG', { | ||
transactionId, | ||
data, | ||
index, | ||
timestamp: new Date().valueOf(), | ||
}).catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error('Failed sending log to Interval', err); | ||
}); | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
await ((_a = __classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers()) === null || _a === void 0 ? void 0 : _a.LOG({ | ||
transactionId, | ||
data, | ||
timestamp: new Date().valueOf(), | ||
index, | ||
})); | ||
} | ||
else { | ||
await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_LOG', { | ||
transactionId, | ||
data, | ||
index, | ||
timestamp: new Date().valueOf(), | ||
}).catch(err => { | ||
__classPrivateFieldGet(this, _IntervalClient_logger, "f").error('Failed sending log to Interval', err); | ||
}); | ||
} | ||
}, _IntervalClient_sendRedirect = async function _IntervalClient_sendRedirect(transactionId, props) { | ||
if (__classPrivateFieldGet(this, _IntervalClient_config, "f").getClientHandlers) { | ||
throw new __1.IntervalError(`The ctx.redirect method isn't supported in demo mode`); | ||
} | ||
const response = await __classPrivateFieldGet(this, _IntervalClient_instances, "m", _IntervalClient_send).call(this, 'SEND_REDIRECT', { | ||
@@ -1065,0 +1148,0 @@ transactionId, |
@@ -11,2 +11,3 @@ /// <reference types="node" /> | ||
send: IORenderSender; | ||
isDemo?: boolean; | ||
} | ||
@@ -27,2 +28,3 @@ export declare type IOClientRenderReturnValues<Components extends [AnyIOComponent, ...AnyIOComponent[]]> = { | ||
send: IORenderSender; | ||
isDemo: boolean; | ||
onResponseHandler: ResponseHandlerFn | undefined; | ||
@@ -72,4 +74,5 @@ inlineActionKeys: Set<string>; | ||
}): RequiredPropsInputIOComponentFunction<MethodName, Props, Output>; | ||
createExclusiveIOMethod<MethodName extends T_IO_INPUT_METHOD_NAMES, Props extends object = T_IO_PROPS<MethodName>, Output = T_IO_RETURNS<MethodName>>(methodName: MethodName, { componentDef, }?: { | ||
createExclusiveIOMethod<MethodName extends T_IO_INPUT_METHOD_NAMES, Props extends object = T_IO_PROPS<MethodName>, Output = T_IO_RETURNS<MethodName>>(methodName: MethodName, { componentDef, demoUnsupported, }?: { | ||
componentDef?: IOComponentDefinition<MethodName, Props, Output>; | ||
demoUnsupported?: boolean; | ||
}): ExclusiveIOComponentFunction<MethodName, Props, Output>; | ||
@@ -76,0 +79,0 @@ /** |
@@ -61,2 +61,3 @@ "use strict"; | ||
this.send = config.send; | ||
this.isDemo = !!config.isDemo; | ||
// this.onAddInlineAction = config.onAddInlineAction | ||
@@ -247,4 +248,7 @@ } | ||
} | ||
createExclusiveIOMethod(methodName, { componentDef, } = {}) { | ||
createExclusiveIOMethod(methodName, { componentDef, demoUnsupported = false, } = {}) { | ||
return (label, props) => { | ||
if (demoUnsupported && this.isDemo) { | ||
throw new __1.IntervalError(`The ${methodName} method isn't supported in demo mode`); | ||
} | ||
const promiseProps = this.getPromiseProps(methodName, props, componentDef); | ||
@@ -266,3 +270,5 @@ return new IOPromise_1.ExclusiveIOPromise({ | ||
confirm: this.createExclusiveIOMethod('CONFIRM'), | ||
confirmIdentity: this.createExclusiveIOMethod('CONFIRM_IDENTITY'), | ||
confirmIdentity: this.createExclusiveIOMethod('CONFIRM_IDENTITY', { | ||
demoUnsupported: true, | ||
}), | ||
search: this.createIOMethod('SEARCH', { | ||
@@ -269,0 +275,0 @@ propsRequired: true, |
@@ -46,7 +46,7 @@ "use strict"; | ||
// Immediately resolve any methods defined as immediate in schema | ||
setImmediate(() => { | ||
setTimeout(() => { | ||
if ((0, ioSchema_1.resolvesImmediately)(methodName) && this.resolver) { | ||
this.resolver(null); | ||
} | ||
}); | ||
}, 0); | ||
} | ||
@@ -53,0 +53,0 @@ async handleValidation(returnValue) { |
import { Evt } from 'evt'; | ||
import { AccessControlDefinition } from '../internalRpcSchema'; | ||
import { IntervalActionDefinition, IntervalPageHandler, IntervalRouteDefinitions } from '../types'; | ||
@@ -11,2 +12,3 @@ export interface PageConfig { | ||
handler?: IntervalPageHandler; | ||
access?: AccessControlDefinition; | ||
} | ||
@@ -20,2 +22,3 @@ export default class Page { | ||
handler?: IntervalPageHandler; | ||
access?: AccessControlDefinition; | ||
onChange: Evt<void>; | ||
@@ -22,0 +25,0 @@ constructor(config: PageConfig); |
@@ -21,2 +21,3 @@ "use strict"; | ||
}; | ||
this.access = config.access; | ||
this.handler = config.handler; | ||
@@ -23,0 +24,0 @@ this.onChange = new evt_1.Evt(); |
@@ -41,3 +41,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const node_fetch_1 = __importDefault(require("node-fetch")); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const superjson = __importStar(require("superjson")); | ||
@@ -77,3 +77,3 @@ const __1 = require(".."); | ||
} | ||
const response = await (0, node_fetch_1.default)(__classPrivateFieldGet(this, _Routes_instances, "m", _Routes_getAddress).call(this, 'enqueue'), { | ||
const response = await (0, cross_fetch_1.default)(__classPrivateFieldGet(this, _Routes_instances, "m", _Routes_getAddress).call(this, 'enqueue'), { | ||
method: 'POST', | ||
@@ -112,3 +112,3 @@ headers: { | ||
} | ||
const response = await (0, node_fetch_1.default)(__classPrivateFieldGet(this, _Routes_instances, "m", _Routes_getAddress).call(this, 'dequeue'), { | ||
const response = await (0, cross_fetch_1.default)(__classPrivateFieldGet(this, _Routes_instances, "m", _Routes_getAddress).call(this, 'dequeue'), { | ||
method: 'POST', | ||
@@ -115,0 +115,0 @@ headers: { |
@@ -8,3 +8,3 @@ "use strict"; | ||
const path_1 = __importDefault(require("path")); | ||
const node_fetch_1 = __importDefault(require("node-fetch")); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const __1 = require(".."); | ||
@@ -15,3 +15,3 @@ const MAX_RETRIES = 3; | ||
try { | ||
const r = await (0, node_fetch_1.default)(url); | ||
const r = await (0, cross_fetch_1.default)(url); | ||
return r; | ||
@@ -18,0 +18,0 @@ } |
@@ -43,3 +43,3 @@ "use strict"; | ||
const evt_1 = require("evt"); | ||
const node_fetch_1 = __importDefault(require("node-fetch")); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const _1 = __importStar(require(".")); | ||
@@ -220,3 +220,3 @@ Object.defineProperty(exports, "io", { enumerable: true, get: function () { return _1.io; } }); | ||
}; | ||
const response = await (0, node_fetch_1.default)(`${this.httpEndpoint}/api/hosts/declare`, { | ||
const response = await (0, cross_fetch_1.default)(`${this.httpEndpoint}/api/hosts/declare`, { | ||
method: 'POST', | ||
@@ -223,0 +223,0 @@ headers: { |
@@ -5,2 +5,4 @@ import Routes from './classes/Routes'; | ||
import Page from './classes/Page'; | ||
import { ClientSchema, HostSchema } from './internalRpcSchema'; | ||
import { DuplexRPCHandlers } from './classes/DuplexRPCClient'; | ||
import { SerializableRecord } from './ioSchema'; | ||
@@ -24,2 +26,4 @@ import type { ActionCtx, ActionLogFn, IO, IntervalActionHandler, IntervalActionStore, NotifyConfig, IntervalRouteDefinitions, IntervalPageStore, PageCtx, IntervalActionDefinition } from './types'; | ||
reinitializeBatchTimeoutMs?: number; | ||
getClientHandlers?: () => DuplexRPCHandlers<ClientSchema> | undefined; | ||
setHostHandlers?: (handlers: DuplexRPCHandlers<HostSchema>) => void; | ||
} | ||
@@ -26,0 +30,0 @@ export interface QueuedAction { |
@@ -42,3 +42,3 @@ "use strict"; | ||
exports.Action = exports.IntervalError = exports.IOError = exports.Interval = exports.ctx = exports.io = exports.getSomeStore = exports.getPageStore = exports.getActionStore = void 0; | ||
const node_fetch_1 = __importDefault(require("node-fetch")); | ||
const cross_fetch_1 = __importDefault(require("cross-fetch")); | ||
const Routes_1 = __importDefault(require("./classes/Routes")); | ||
@@ -55,5 +55,8 @@ const IOError_1 = __importDefault(require("./classes/IOError")); | ||
function getActionStore() { | ||
if (!IntervalClient_1.actionLocalStorage) { | ||
throw new IntervalError_1.default('Global io and ctx objects are only available in a Node.js context'); | ||
} | ||
const store = IntervalClient_1.actionLocalStorage.getStore(); | ||
if (!store) { | ||
throw new IntervalError_1.default('Global io and ctx objects can only be used inside an IntervalActionHandler'); | ||
throw new IntervalError_1.default('Global io and ctx objects can only be used inside an Action'); | ||
} | ||
@@ -64,5 +67,8 @@ return store; | ||
function getPageStore() { | ||
if (!IntervalClient_1.pageLocalStorage) { | ||
throw new IntervalError_1.default('Global io and ctx objects are only available in a Node.js context'); | ||
} | ||
const store = IntervalClient_1.pageLocalStorage.getStore(); | ||
if (!store) { | ||
throw new IntervalError_1.default('Global io and ctx objects can only be used inside an App'); | ||
throw new IntervalError_1.default('Global io and ctx objects can only be used inside a Page'); | ||
} | ||
@@ -157,3 +163,22 @@ return store; | ||
async notify(config) { | ||
var _a, _b, _c; | ||
var _a, _b, _c, _d, _e, _f; | ||
if (!config.transactionId && | ||
(((_a = __classPrivateFieldGet(this, _Interval_client, "f")) === null || _a === void 0 ? void 0 : _a.environment) === 'development' || | ||
(!((_b = __classPrivateFieldGet(this, _Interval_client, "f")) === null || _b === void 0 ? void 0 : _b.environment) && !((_c = __classPrivateFieldGet(this, _Interval_apiKey, "f")) === null || _c === void 0 ? void 0 : _c.startsWith('live_'))))) { | ||
__classPrivateFieldGet(this, _Interval_instances, "a", _Interval_log_get).warn('Calls to notify() outside of a transaction currently have no effect when Interval is instantiated with a development API key. Please use a live key to send notifications.'); | ||
} | ||
const clientHandlers = (_e = (_d = this.config).getClientHandlers) === null || _e === void 0 ? void 0 : _e.call(_d); | ||
if (clientHandlers) { | ||
clientHandlers.NOTIFY({ | ||
...config, | ||
transactionId: (_f = config.transactionId) !== null && _f !== void 0 ? _f : 'demo', | ||
deliveries: config.delivery || [ | ||
{ | ||
method: 'EMAIL', | ||
to: 'demo@interval.com', | ||
}, | ||
], | ||
}); | ||
return; | ||
} | ||
let body; | ||
@@ -171,8 +196,3 @@ try { | ||
} | ||
if (!config.transactionId && | ||
(((_a = __classPrivateFieldGet(this, _Interval_client, "f")) === null || _a === void 0 ? void 0 : _a.environment) === 'development' || | ||
(!((_b = __classPrivateFieldGet(this, _Interval_client, "f")) === null || _b === void 0 ? void 0 : _b.environment) && !((_c = __classPrivateFieldGet(this, _Interval_apiKey, "f")) === null || _c === void 0 ? void 0 : _c.startsWith('live_'))))) { | ||
__classPrivateFieldGet(this, _Interval_instances, "a", _Interval_log_get).warn('Calls to notify() outside of a transaction currently have no effect when Interval is instantiated with a development API key. Please use a live key to send notifications.'); | ||
} | ||
const response = await (0, node_fetch_1.default)(`${__classPrivateFieldGet(this, _Interval_httpEndpoint, "f")}/api/notify`, { | ||
const response = await (0, cross_fetch_1.default)(`${__classPrivateFieldGet(this, _Interval_httpEndpoint, "f")}/api/notify`, { | ||
method: 'POST', | ||
@@ -179,0 +199,0 @@ headers: { |
@@ -67,2 +67,10 @@ import { z } from 'zod'; | ||
export declare type LoadingState = z.input<typeof LOADING_STATE>; | ||
export declare const ACCESS_CONTROL_DEFINITION: z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>; | ||
export declare type AccessControlDefinition = z.infer<typeof ACCESS_CONTROL_DEFINITION>; | ||
export declare const ACTION_DEFINITION: z.ZodObject<{ | ||
@@ -75,2 +83,9 @@ groupSlug: z.ZodOptional<z.ZodString>; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
@@ -82,2 +97,5 @@ description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -90,2 +108,5 @@ }, { | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -101,5 +122,15 @@ }>; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -112,2 +143,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -268,2 +302,9 @@ hasIndex?: boolean | undefined; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
@@ -275,2 +316,5 @@ description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -283,2 +327,5 @@ }, { | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -293,5 +340,15 @@ }>, "many">; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -304,2 +361,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -316,2 +376,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -329,2 +392,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -338,2 +404,5 @@ }[]; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -351,2 +420,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -373,2 +445,3 @@ }[]; | ||
}>>>; | ||
warnings: z.ZodArray<z.ZodString, "many">; | ||
}, "strip", z.ZodTypeAny, { | ||
@@ -382,2 +455,3 @@ sdkAlert?: { | ||
invalidSlugs: string[]; | ||
warnings: string[]; | ||
}, { | ||
@@ -391,2 +465,3 @@ sdkAlert?: { | ||
invalidSlugs: string[]; | ||
warnings: string[]; | ||
}> | z.ZodObject<{ | ||
@@ -700,2 +775,9 @@ type: z.ZodLiteral<"error">; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
@@ -707,2 +789,5 @@ description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -715,2 +800,5 @@ }, { | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -725,5 +813,15 @@ }>, "many">; | ||
unlisted: z.ZodOptional<z.ZodBoolean>; | ||
access: z.ZodOptional<z.ZodUnion<[z.ZodLiteral<"entire-organization">, z.ZodObject<{ | ||
teams: z.ZodOptional<z.ZodArray<z.ZodString, "many">>; | ||
}, "strip", z.ZodTypeAny, { | ||
teams?: string[] | undefined; | ||
}, { | ||
teams?: string[] | undefined; | ||
}>]>>; | ||
}, "strip", z.ZodTypeAny, { | ||
description?: string | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -736,2 +834,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -746,2 +847,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -758,2 +862,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -765,2 +872,5 @@ }[]; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
hasHandler?: boolean | undefined; | ||
@@ -777,2 +887,5 @@ hasIndex?: boolean | undefined; | ||
unlisted?: boolean | undefined; | ||
access?: "entire-organization" | { | ||
teams?: string[] | undefined; | ||
} | undefined; | ||
slug: string; | ||
@@ -809,2 +922,3 @@ }[]; | ||
}>>>; | ||
warnings: z.ZodArray<z.ZodString, "many">; | ||
}, "strip", z.ZodTypeAny, { | ||
@@ -818,2 +932,3 @@ sdkAlert?: { | ||
invalidSlugs: string[]; | ||
warnings: string[]; | ||
environment: "live" | "development"; | ||
@@ -833,2 +948,3 @@ organization: { | ||
invalidSlugs: string[]; | ||
warnings: string[]; | ||
environment: "live" | "development"; | ||
@@ -891,6 +1007,9 @@ organization: { | ||
resultStatus: z.ZodEnum<["SUCCESS", "FAILURE", "CANCELED", "REDIRECTED"]>; | ||
result: z.ZodOptional<z.ZodString>; | ||
}, "strip", z.ZodTypeAny, { | ||
result?: string | undefined; | ||
transactionId: string; | ||
resultStatus: "CANCELED" | "SUCCESS" | "FAILURE" | "REDIRECTED"; | ||
}, { | ||
result?: string | undefined; | ||
transactionId: string; | ||
@@ -897,0 +1016,0 @@ resultStatus: "CANCELED" | "SUCCESS" | "FAILURE" | "REDIRECTED"; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.hostSchema = exports.clientSchema = exports.wsServerSchema = exports.DECLARE_HOST = exports.NOTIFY = exports.DEQUEUE_ACTION = exports.CREATE_GHOST_MODE_ACCOUNT = exports.ENQUEUE_ACTION = exports.PAGE_DEFINITION = exports.ACTION_DEFINITION = exports.LOADING_OPTIONS = exports.actionEnvironment = exports.TRANSACTION_RESULT_SCHEMA_VERSION = exports.DUPLEX_MESSAGE_SCHEMA = void 0; | ||
exports.hostSchema = exports.clientSchema = exports.wsServerSchema = exports.DECLARE_HOST = exports.NOTIFY = exports.DEQUEUE_ACTION = exports.CREATE_GHOST_MODE_ACCOUNT = exports.ENQUEUE_ACTION = exports.PAGE_DEFINITION = exports.ACTION_DEFINITION = exports.ACCESS_CONTROL_DEFINITION = exports.LOADING_OPTIONS = exports.actionEnvironment = exports.TRANSACTION_RESULT_SCHEMA_VERSION = exports.DUPLEX_MESSAGE_SCHEMA = void 0; | ||
const zod_1 = require("zod"); | ||
@@ -30,2 +30,8 @@ const ioSchema_1 = require("./ioSchema"); | ||
}); | ||
exports.ACCESS_CONTROL_DEFINITION = zod_1.z.union([ | ||
zod_1.z.literal('entire-organization'), | ||
zod_1.z.object({ | ||
teams: zod_1.z.array(zod_1.z.string()).optional(), | ||
}), | ||
]); | ||
exports.ACTION_DEFINITION = zod_1.z.object({ | ||
@@ -38,2 +44,3 @@ groupSlug: zod_1.z.string().optional(), | ||
unlisted: zod_1.z.boolean().optional(), | ||
access: exports.ACCESS_CONTROL_DEFINITION.optional(), | ||
}); | ||
@@ -48,2 +55,3 @@ exports.PAGE_DEFINITION = zod_1.z.object({ | ||
unlisted: zod_1.z.boolean().optional(), | ||
access: exports.ACCESS_CONTROL_DEFINITION.optional(), | ||
}); | ||
@@ -127,2 +135,3 @@ exports.ENQUEUE_ACTION = { | ||
sdkAlert: SDK_ALERT.nullish(), | ||
warnings: zod_1.z.array(zod_1.z.string()), | ||
}), | ||
@@ -270,2 +279,3 @@ zod_1.z.object({ | ||
sdkAlert: SDK_ALERT.nullish(), | ||
warnings: zod_1.z.array(zod_1.z.string()), | ||
}), | ||
@@ -292,2 +302,3 @@ zod_1.z.object({ | ||
resultStatus: zod_1.z.enum(['SUCCESS', 'FAILURE', 'CANCELED', 'REDIRECTED']), | ||
result: zod_1.z.string().optional(), | ||
}), | ||
@@ -294,0 +305,0 @@ returns: zod_1.z.void().nullable(), |
/// <reference types="node" /> | ||
import type { z } from 'zod'; | ||
import type { T_IO_RENDER_INPUT, T_IO_RESPONSE, T_IO_PROPS, T_IO_RETURNS, T_IO_STATE, T_IO_Schema, T_IO_METHOD_NAMES, IOFunctionReturnType, T_IO_DISPLAY_METHOD_NAMES, T_IO_INPUT_METHOD_NAMES, menuItem, buttonItem, ButtonTheme, serializableRecord, ImageSize, SerializableRecord, LegacyLinkProps } from './ioSchema'; | ||
import type { HostSchema } from './internalRpcSchema'; | ||
import type { AccessControlDefinition, HostSchema } from './internalRpcSchema'; | ||
import type { IOClient, IOClientRenderValidator } from './classes/IOClient'; | ||
@@ -50,2 +50,3 @@ import type IOComponent from './classes/IOComponent'; | ||
description?: string; | ||
access?: AccessControlDefinition; | ||
} | ||
@@ -52,0 +53,0 @@ export declare type IntervalActionDefinition = IntervalActionHandler | ExplicitIntervalActionDefinition | Action; |
@@ -33,3 +33,3 @@ "use strict"; | ||
const path_1 = __importDefault(require("path")); | ||
const promises_1 = __importStar(require("fs/promises")); | ||
const promises_1 = __importDefault(require("fs/promises")); | ||
const Action_1 = __importDefault(require("../classes/Action")); | ||
@@ -51,3 +51,3 @@ const Page_1 = __importDefault(require("../classes/Page")); | ||
const slug = path_1.default.basename(file, ext || undefined); | ||
if ((await (0, promises_1.stat)(fullPath)).isDirectory()) { | ||
if ((await promises_1.default.stat(fullPath)).isDirectory()) { | ||
const group = await loadFolder(path_1.default.join(currentDirectory, slug), logger); | ||
@@ -54,0 +54,0 @@ router.routes[slug] = group; |
{ | ||
"name": "@interval/sdk", | ||
"version": "0.33.0", | ||
"version": "0.34.0", | ||
"homepage": "https://interval.com", | ||
@@ -25,4 +25,4 @@ "repository": { | ||
"dependencies": { | ||
"cross-fetch": "^3.1.5", | ||
"evt": "^2.4.10", | ||
"node-fetch": "^2.0.0", | ||
"superjson": "^1.9.1", | ||
@@ -29,0 +29,0 @@ "uuid": "^9.0.0", |
<a href="https://interval.com"> | ||
<img alt="Interval" width="100" height="100" style="border-radius: 6px;" src="interval-avatar.png"> | ||
<img alt="Interval" width="100" height="100" style="border-radius: 6px;" src="https://interval.com/img/readme-assets/interval-avatar.png"> | ||
</a> | ||
@@ -53,3 +53,3 @@ | ||
<img alt="An image containing a code sample alongside a screenshot of the Interval app it generates." src="screenshot.png"> | ||
<img alt="An image containing a code sample alongside a screenshot of the Interval app it generates." src="https://interval.com/img/readme-assets/screenshot.png"> | ||
@@ -56,0 +56,0 @@ ## More about Interval |
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
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
Debug access
Supply chain riskUses debug, reflection and dynamic code execution features.
Found 1 instance in 1 package
984036
108
19299
+ Addedcross-fetch@^3.1.5
+ Addedcross-fetch@3.1.8(transitive)
- Removednode-fetch@^2.0.0