diff --git a/dist/autofill-debug.js b/dist/autofill-debug.js index 9ccabd40e..f97dbde2f 100644 --- a/dist/autofill-debug.js +++ b/dist/autofill-debug.js @@ -58,954 +58,598 @@ function processConfig(data, userList, preferences) { Object.defineProperty(exports, "__esModule", { value: true }); +exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; -var _messaging = require("./messaging.js"); +const parseUtil_1 = require("./helpers/parseUtil"); -Object.keys(_messaging).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - if (key in exports && exports[key] === _messaging[key]) return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _messaging[key]; - } - }); -}); +const util_1 = require("./helpers/util"); -},{"./messaging.js":3}],3:[function(require,module,exports){ -"use strict"; +exports.ZodIssueCode = util_1.util.arrayToEnum(["invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of"]); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; -Object.defineProperty(exports, "WebkitMessagingConfig", { - enumerable: true, - get: function () { - return _webkit.WebkitMessagingConfig; - } -}); -Object.defineProperty(exports, "WindowsMessagingConfig", { - enumerable: true, - get: function () { - return _windows.WindowsMessagingConfig; - } -}); +const quotelessJson = obj => { + const json = JSON.stringify(obj, null, 2); + return json.replace(/"([^"]+)":/g, "$1:"); +}; -var _windows = require("./messaging/windows.js"); +exports.quotelessJson = quotelessJson; -var _webkit = require("./messaging/webkit.js"); +class ZodError extends Error { + constructor(issues) { + var _this; -/** - * @module Messaging - * - * @description - * - * An abstraction for communications between JavaScript and host platforms. - * - * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) - * 2) Then use that to get an instance of the Messaging utility which allows - * you to send and receive data in a unified way - * 3) Each platform implements {@link MessagingTransport} along with its own Configuration - * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} - * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} - * - * @example Webkit Messaging - * - * ```js - * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // This config would be injected into the UserScript - * const injectedConfig = { - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }; - * - * // Then use that config to construct platform-specific configuration - * const config = new WebkitMessagingConfig(injectedConfig); - * - * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 - * const messaging = new Messaging(config); - * messaging.notify("hello world!", {foo: "bar"}) - * - * ``` - * - * @example Windows Messaging - * - * ```js - * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // Messaging on Windows is namespaced, so you can create multiple messaging instances - * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); - * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); - * - * const autofillMessaging = new Messaging(autofillConfig); - * const debugMessaging = new Messaging(debugConfig); - * - * // Now send messages to both features as needed 🚀 - * autofillMessaging.notify("storeFormData", { "username": "dax" }) - * debugMessaging.notify("pageLoad", { time: window.performance.now() }) - * ``` - */ + super(); + _this = this; + this.issues = []; -/** - * @implements {MessagingTransport} - */ -class Messaging { - /** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - */ - constructor(config) { - this.transport = getTransport(config); - } - /** - * Send a 'fire-and-forget' message. - * @throws - * {@link MissingHandler} - * - * @example - * - * ``` - * const messaging = new Messaging(config) - * messaging.notify("foo", {bar: "baz"}) - * ``` - * @param {string} name - * @param {Record} [data] - */ + this.addIssue = sub => { + this.issues = [...this.issues, sub]; + }; + this.addIssues = function () { + let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + _this.issues = [..._this.issues, ...subs]; + }; - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.transport.notify(name, data); - } - /** - * Send a request, and wait for a response - * @throws - * {@link MissingHandler} - * - * @example - * ``` - * const messaging = new Messaging(config) - * const response = await messaging.request("foo", {bar: "baz"}) - * ``` - * - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + // eslint-disable-next-line ban/ban + Object.setPrototypeOf(this, actualProto); + } else { + this.__proto__ = actualProto; + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.transport.request(name, data); + this.name = "ZodError"; + this.issues = issues; } -} -/** - * @interface - */ + get errors() { + return this.issues; + } + format(_mapper) { + const mapper = _mapper || function (issue) { + return issue.message; + }; -exports.Messaging = Messaging; + const fieldErrors = { + _errors: [] + }; -class MessagingTransport { - /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error("must implement 'notify'"); + const processError = error => { + for (const issue of error.issues) { + if (issue.code === "invalid_union") { + issue.unionErrors.map(processError); + } else if (issue.code === "invalid_return_type") { + processError(issue.returnTypeError); + } else if (issue.code === "invalid_arguments") { + processError(issue.argumentsError); + } else if (issue.path.length === 0) { + fieldErrors._errors.push(mapper(issue)); + } else { + let curr = fieldErrors; + let i = 0; + + while (i < issue.path.length) { + const el = issue.path[i]; + const terminal = i === issue.path.length - 1; + + if (!terminal) { + curr[el] = curr[el] || { + _errors: [] + }; // if (typeof el === "string") { + // curr[el] = curr[el] || { _errors: [] }; + // } else if (typeof el === "number") { + // const errorArray: any = []; + // errorArray._errors = []; + // curr[el] = curr[el] || errorArray; + // } + } else { + curr[el] = curr[el] || { + _errors: [] + }; + + curr[el]._errors.push(mapper(issue)); + } + + curr = curr[el]; + i++; + } + } + } + }; + + processError(this); + return fieldErrors; } - /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + toString() { + return this.message; + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); + get message() { + return JSON.stringify(this.issues, null, 2); } -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + get isEmpty() { + return this.issues.length === 0; + } + flatten() { + let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; + const fieldErrors = {}; + const formErrors = []; -exports.MessagingTransport = MessagingTransport; + for (const sub of this.issues) { + if (sub.path.length > 0) { + fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; + fieldErrors[sub.path[0]].push(mapper(sub)); + } else { + formErrors.push(mapper(sub)); + } + } -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); + return { + formErrors, + fieldErrors + }; } - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + get formErrors() { + return this.flatten(); } - throw new Error('unreachable'); } -/** - * Thrown when a handler cannot be found - */ +exports.ZodError = ZodError; -class MissingHandler extends Error { - /** - * @param {string} message - * @param {string} handlerName - */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; - } +ZodError.create = issues => { + const error = new ZodError(issues); + return error; +}; -} -/** - * Some re-exports for convenience - */ +const defaultErrorMap = (issue, _ctx) => { + let message; + switch (issue.code) { + case exports.ZodIssueCode.invalid_type: + if (issue.received === parseUtil_1.ZodParsedType.undefined) { + message = "Required"; + } else { + message = "Expected ".concat(issue.expected, ", received ").concat(issue.received); + } -exports.MissingHandler = MissingHandler; + break; -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + case exports.ZodIssueCode.invalid_literal: + message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); + break; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + case exports.ZodIssueCode.unrecognized_keys: + message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); + break; -var _messaging = require("../messaging.js"); + case exports.ZodIssueCode.invalid_union: + message = "Invalid input"; + break; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + case exports.ZodIssueCode.invalid_union_discriminator: + message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); + break; -/** - * @example - * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` - * - * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following - * would occur: - * - * ```js - * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); - * const response = JSON.parse(json) - * ``` - * - * @example - * On macOS 10 however, the process is a little more involved. A method will be appended to `window` - * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow - * as being something along the lines of: - * - * ```js - * // add the window method - * window["_0123456"] = (response) => { - * // decrypt `response` and deliver the result to the caller here - * // then remove the temporary method - * delete window["_0123456"] - * }; - * - * // send the data + `messageHanding` values - * window.webkit.messageHandlers.foo.postMessage({ - * bar: "baz", - * messagingHandling: { - * methodName: "_0123456", - * secret: "super-secret", - * key: [1, 2, 45, 2], - * iv: [34, 4, 43], - * } - * }); - * - * // later in swift, the following JavaScript snippet will be executed - * (() => { - * window["_0123456"]({ - * ciphertext: [12, 13, 4], - * tag: [3, 5, 67, 56] - * }) - * })() - * ``` - * @implements {MessagingTransport} - */ -class WebkitMessagingTransport { - /** @type {WebkitMessagingConfig} */ + case exports.ZodIssueCode.invalid_enum_value: + message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); + break; - /** - * @param {WebkitMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); + case exports.ZodIssueCode.invalid_arguments: + message = "Invalid function arguments"; + break; - _defineProperty(this, "globals", void 0); + case exports.ZodIssueCode.invalid_return_type: + message = "Invalid function return type"; + break; - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); + case exports.ZodIssueCode.invalid_date: + message = "Invalid date"; + break; - this.config = config; - this.globals = captureGlobals(); + case exports.ZodIssueCode.invalid_string: + if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; + break; - if (!this.config.hasModernWebkitAPI) { - this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); - } - } - /** - * Sends message to the webkit layer (fire and forget) - * @param {String} handler - * @param {*} data - * @internal - */ + case exports.ZodIssueCode.too_small: + if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at least" : "more than", " ").concat(issue.minimum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at least" : "over", " ").concat(issue.minimum, " character(s)");else if (issue.type === "number") message = "Number must be greater than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.minimum);else message = "Invalid input"; + break; + case exports.ZodIssueCode.too_big: + if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at most" : "less than", " ").concat(issue.maximum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at most" : "under", " ").concat(issue.maximum, " character(s)");else if (issue.type === "number") message = "Number must be less than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.maximum);else message = "Invalid input"; + break; - wkSend(handler) { - var _this$globals$window$, _this$globals$window$2; + case exports.ZodIssueCode.custom: + message = "Invalid input"; + break; - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + case exports.ZodIssueCode.invalid_intersection_types: + message = "Intersection results could not be merged"; + break; - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } + case exports.ZodIssueCode.not_multiple_of: + message = "Number must be a multiple of ".concat(issue.multipleOf); + break; - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret - } - }; + default: + message = _ctx.defaultError; + util_1.util.assertNever(issue); + } - if (!this.config.hasModernWebkitAPI) { - if (!(handler in this.globals.capturedWebkitHandlers)) { - throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); - } else { - return this.globals.capturedWebkitHandlers[handler](outgoing); - } - } + return { + message + }; +}; - return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); - } - /** - * Sends message to the webkit layer and waits for the specified response - * @param {String} handler - * @param {*} data - * @returns {Promise<*>} - * @internal - */ +exports.defaultErrorMap = defaultErrorMap; +exports.overrideErrorMap = exports.defaultErrorMap; +const setErrorMap = map => { + exports.overrideErrorMap = map; +}; - async wkSendAndWait(handler) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; +exports.setErrorMap = setErrorMap; - if (this.config.hasModernWebkitAPI) { - const response = await this.wkSend(handler, data); - return this.globals.JSONparse(response || '{}'); - } +},{"./helpers/parseUtil":5,"./helpers/util":7}],3:[function(require,module,exports){ +"use strict"; - try { - const randMethodName = this.createRandMethodName(); - const key = await this.createRandKey(); - const iv = this.createRandIv(); - const { - ciphertext, - tag - } = await new this.globals.Promise(( - /** @type {any} */ - resolve) => { - this.generateRandomMethod(randMethodName, resolve); - data.messageHandling = new SecureMessagingParams({ - methodName: randMethodName, - secret: this.config.secret, - key: this.globals.Arrayfrom(key), - iv: this.globals.Arrayfrom(iv) - }); - this.wkSend(handler, data); - }); - const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); - const decrypted = await this.decrypt(cipher, key, iv); - return this.globals.JSONparse(decrypted || '{}'); - } catch (e) { - // re-throw when the error is just a 'MissingHandler' - if (e instanceof _messaging.MissingHandler) { - throw e; - } else { - console.error('decryption failed', e); - console.error(e); - return { - error: e - }; +var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; } - } + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); - } - /** - * @param {string} name - * @param {Record} [data] - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); +var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.wkSendAndWait(name, data); - } - /** - * Generate a random method name and adds it to the global scope - * The native layer will use this method to send the response - * @param {string | number} randomMethodName - * @param {Function} callback - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +__exportStar(require("./helpers/parseUtil"), exports); - generateRandomMethod(randomMethodName, callback) { - var _this = this; +__exportStar(require("./helpers/typeAliases"), exports); - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, +__exportStar(require("./types"), exports); - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. +__exportStar(require("./ZodError"), exports); - delete _this.globals.window[randomMethodName]; - } - }); - } +},{"./ZodError":2,"./helpers/parseUtil":5,"./helpers/typeAliases":6,"./types":9}],4:[function(require,module,exports){ +"use strict"; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.errorUtil = void 0; +var errorUtil; - createRandMethodName() { - return '_' + this.randomString(); - } - /** - * @type {{name: string, length: number}} - */ +(function (errorUtil) { + errorUtil.errToObj = message => typeof message === "string" ? { + message + } : message || {}; + errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; +})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); - /** - * @returns {Promise} - */ - async createRandKey() { - const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); - const exportedKey = await this.globals.exportKey('raw', key); - return new this.globals.Uint8Array(exportedKey); - } - /** - * @returns {Uint8Array} - */ +},{}],5:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isAsync = exports.isValid = exports.isDirty = exports.isAborted = exports.OK = exports.DIRTY = exports.INVALID = exports.ParseStatus = exports.addIssueToContext = exports.EMPTY_PATH = exports.makeIssue = exports.getParsedType = exports.ZodParsedType = void 0; - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ +const ZodError_1 = require("../ZodError"); +const util_1 = require("./util"); - async decrypt(ciphertext, key, iv) { - const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); - const algo = { - name: 'AES-GCM', - iv - }; - let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); - let dec = new this.globals.TextDecoder(); - return dec.decode(decrypted); - } - /** - * When required (such as on macos 10.x), capture the `postMessage` method on - * each webkit messageHandler - * - * @param {string[]} handlerNames - */ +exports.ZodParsedType = util_1.util.arrayToEnum(["string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set"]); +const getParsedType = data => { + const t = typeof data; - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); + switch (t) { + case "undefined": + return exports.ZodParsedType.undefined; - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case "string": + return exports.ZodParsedType.string; - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + case "number": + return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; - /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ - const original = handlers[webkitMessageHandlerName]; - const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); - this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; - delete handlers[webkitMessageHandlerName].postMessage; - } - } - } + case "boolean": + return exports.ZodParsedType.boolean; -} -/** - * Use this configuration to create an instance of {@link Messaging} for WebKit - * - * ```js - * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * const config = new WebkitMessagingConfig({ - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }); - * - * const messaging = new Messaging(config) - * const resp = await messaging.request("debugConfig") - * ``` - */ + case "function": + return exports.ZodParsedType.function; + case "bigint": + return exports.ZodParsedType.bigint; -exports.WebkitMessagingTransport = WebkitMessagingTransport; + case "object": + if (Array.isArray(data)) { + return exports.ZodParsedType.array; + } -class WebkitMessagingConfig { - /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ - constructor(params) { - /** - * Whether or not the current WebKit Platform supports secure messaging - * by default (eg: macOS 11+) - */ - this.hasModernWebkitAPI = params.hasModernWebkitAPI; - /** - * A list of WebKit message handler names that a user script can send - */ + if (data === null) { + return exports.ZodParsedType.null; + } - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return exports.ZodParsedType.promise; + } - this.secret = params.secret; - } + if (typeof Map !== "undefined" && data instanceof Map) { + return exports.ZodParsedType.map; + } -} -/** - * This is the additional payload that gets appended to outgoing messages. - * It's used in the Swift side to encrypt the response that comes back - */ + if (typeof Set !== "undefined" && data instanceof Set) { + return exports.ZodParsedType.set; + } + if (typeof Date !== "undefined" && data instanceof Date) { + return exports.ZodParsedType.date; + } -exports.WebkitMessagingConfig = WebkitMessagingConfig; + return exports.ZodParsedType.object; -class SecureMessagingParams { - /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ - constructor(params) { - /** - * The method that's been appended to `window` to be called later - */ - this.methodName = params.methodName; - /** - * The secret used to ensure message sender validity - */ + default: + return exports.ZodParsedType.unknown; + } +}; - this.secret = params.secret; - /** - * The CipherKey as number[] - */ +exports.getParsedType = getParsedType; - this.key = params.key; - /** - * The Initial Vector as number[] - */ +const makeIssue = params => { + const { + data, + path, + errorMaps, + issueData + } = params; + const fullPath = [...path, ...(issueData.path || [])]; + const fullIssue = { ...issueData, + path: fullPath + }; + let errorMessage = ""; + const maps = errorMaps.filter(m => !!m).slice().reverse(); - this.iv = params.iv; + for (const map of maps) { + errorMessage = map(fullIssue, { + data, + defaultError: errorMessage + }).message; } -} -/** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this - */ + return { ...issueData, + path: fullPath, + message: issueData.message || errorMessage + }; +}; +exports.makeIssue = makeIssue; +exports.EMPTY_PATH = []; -exports.SecureMessagingParams = SecureMessagingParams; +function addIssueToContext(ctx, issueData) { + const issue = (0, exports.makeIssue)({ + issueData: issueData, + data: ctx.data, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap // then global default map + ].filter(x => !!x) + }); + ctx.common.issues.push(issue); +} -function captureGlobals() { - // Creat base with null prototype - return { - window, - // Methods must be bound to their interface, otherwise they throw Illegal invocation - encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), - decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), - generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), - exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), - importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), - getRandomValues: window.crypto.getRandomValues.bind(window.crypto), - TextEncoder, - TextDecoder, - Uint8Array, - Uint16Array, - Uint32Array, - JSONstringify: window.JSON.stringify, - JSONparse: window.JSON.parse, - Arrayfrom: window.Array.from, - Promise: window.Promise, - ObjectDefineProperty: window.Object.defineProperty, - addEventListener: window.addEventListener.bind(window), - - /** @type {Record} */ - capturedWebkitHandlers: {} - }; -} +exports.addIssueToContext = addIssueToContext; -},{"../messaging.js":3}],5:[function(require,module,exports){ -"use strict"; +class ParseStatus { + constructor() { + this.value = "valid"; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; + dirty() { + if (this.value === "valid") this.value = "dirty"; + } -var _messaging = require("../messaging.js"); + abort() { + if (this.value !== "aborted") this.value = "aborted"; + } -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + static mergeArray(status, results) { + const arrayValue = []; -/** - * @implements {MessagingTransport} - */ -class WindowsMessagingTransport { - /** - * @param {WindowsMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); + for (const s of results) { + if (s.status === "aborted") return exports.INVALID; + if (s.status === "dirty") status.dirty(); + arrayValue.push(s.value); + } - this.config = config; + return { + status: status.value, + value: arrayValue + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + static async mergeObjectAsync(status, pairs) { + const syncPairs = []; - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); - } - /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars - + for (const pair of pairs) { + syncPairs.push({ + key: await pair.key, + value: await pair.value + }); + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - throw new Error('todo: implement request for windows'); + return ParseStatus.mergeObjectSync(status, syncPairs); } -} + static mergeObjectSync(status, pairs) { + const finalObject = {}; + + for (const pair of pairs) { + const { + key, + value + } = pair; + if (key.status === "aborted") return exports.INVALID; + if (value.status === "aborted") return exports.INVALID; + if (key.status === "dirty") status.dirty(); + if (value.status === "dirty") status.dirty(); -exports.WindowsMessagingTransport = WindowsMessagingTransport; + if (typeof value.value !== "undefined" || pair.alwaysSet) { + finalObject[key.value] = value.value; + } + } -class WindowsMessagingConfig { - /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; + return { + status: status.value, + value: finalObject + }; } } -exports.WindowsMessagingConfig = WindowsMessagingConfig; - -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; +exports.ParseStatus = ParseStatus; +exports.INVALID = Object.freeze({ + status: "aborted" +}); -Object.defineProperty(exports, "__esModule", { - value: true +const DIRTY = value => ({ + status: "dirty", + value }); -exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; -const parseUtil_1 = require("./helpers/parseUtil"); +exports.DIRTY = DIRTY; -const util_1 = require("./helpers/util"); +const OK = value => ({ + status: "valid", + value +}); -exports.ZodIssueCode = util_1.util.arrayToEnum(["invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of"]); +exports.OK = OK; -const quotelessJson = obj => { - const json = JSON.stringify(obj, null, 2); - return json.replace(/"([^"]+)":/g, "$1:"); -}; +const isAborted = x => x.status === "aborted"; -exports.quotelessJson = quotelessJson; +exports.isAborted = isAborted; -class ZodError extends Error { - constructor(issues) { - var _this; +const isDirty = x => x.status === "dirty"; - super(); - _this = this; - this.issues = []; +exports.isDirty = isDirty; - this.addIssue = sub => { - this.issues = [...this.issues, sub]; - }; +const isValid = x => x.status === "valid"; - this.addIssues = function () { - let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - _this.issues = [..._this.issues, ...subs]; - }; +exports.isValid = isValid; - const actualProto = new.target.prototype; +const isAsync = x => typeof Promise !== undefined && x instanceof Promise; - if (Object.setPrototypeOf) { - // eslint-disable-next-line ban/ban - Object.setPrototypeOf(this, actualProto); - } else { - this.__proto__ = actualProto; - } +exports.isAsync = isAsync; - this.name = "ZodError"; - this.issues = issues; - } +},{"../ZodError":2,"./util":7}],6:[function(require,module,exports){ +"use strict"; - get errors() { - return this.issues; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); - format(_mapper) { - const mapper = _mapper || function (issue) { - return issue.message; - }; +},{}],7:[function(require,module,exports){ +"use strict"; - const fieldErrors = { - _errors: [] - }; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.util = void 0; +var util; - const processError = error => { - for (const issue of error.issues) { - if (issue.code === "invalid_union") { - issue.unionErrors.map(processError); - } else if (issue.code === "invalid_return_type") { - processError(issue.returnTypeError); - } else if (issue.code === "invalid_arguments") { - processError(issue.argumentsError); - } else if (issue.path.length === 0) { - fieldErrors._errors.push(mapper(issue)); - } else { - let curr = fieldErrors; - let i = 0; +(function (util) { + function assertNever(_x) { + throw new Error(); + } - while (i < issue.path.length) { - const el = issue.path[i]; - const terminal = i === issue.path.length - 1; + util.assertNever = assertNever; - if (!terminal) { - curr[el] = curr[el] || { - _errors: [] - }; // if (typeof el === "string") { - // curr[el] = curr[el] || { _errors: [] }; - // } else if (typeof el === "number") { - // const errorArray: any = []; - // errorArray._errors = []; - // curr[el] = curr[el] || errorArray; - // } - } else { - curr[el] = curr[el] || { - _errors: [] - }; + util.arrayToEnum = items => { + const obj = {}; - curr[el]._errors.push(mapper(issue)); - } + for (const item of items) { + obj[item] = item; + } - curr = curr[el]; - i++; - } - } - } - }; + return obj; + }; - processError(this); - return fieldErrors; - } + util.getValidEnumValues = obj => { + const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); + const filtered = {}; - toString() { - return this.message; - } + for (const k of validKeys) { + filtered[k] = obj[k]; + } - get message() { - return JSON.stringify(this.issues, null, 2); - } + return util.objectValues(filtered); + }; - get isEmpty() { - return this.issues.length === 0; - } + util.objectValues = obj => { + return util.objectKeys(obj).map(function (e) { + return obj[e]; + }); + }; - flatten() { - let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; - const fieldErrors = {}; - const formErrors = []; + util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban + ? obj => Object.keys(obj) // eslint-disable-line ban/ban + : object => { + const keys = []; - for (const sub of this.issues) { - if (sub.path.length > 0) { - fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; - fieldErrors[sub.path[0]].push(mapper(sub)); - } else { - formErrors.push(mapper(sub)); + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); } } - return { - formErrors, - fieldErrors - }; - } - - get formErrors() { - return this.flatten(); - } - -} - -exports.ZodError = ZodError; - -ZodError.create = issues => { - const error = new ZodError(issues); - return error; -}; - -const defaultErrorMap = (issue, _ctx) => { - let message; - - switch (issue.code) { - case exports.ZodIssueCode.invalid_type: - if (issue.received === parseUtil_1.ZodParsedType.undefined) { - message = "Required"; - } else { - message = "Expected ".concat(issue.expected, ", received ").concat(issue.received); - } - - break; - - case exports.ZodIssueCode.invalid_literal: - message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); - break; - - case exports.ZodIssueCode.unrecognized_keys: - message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); - break; - - case exports.ZodIssueCode.invalid_union: - message = "Invalid input"; - break; - - case exports.ZodIssueCode.invalid_union_discriminator: - message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); - break; - - case exports.ZodIssueCode.invalid_enum_value: - message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); - break; - - case exports.ZodIssueCode.invalid_arguments: - message = "Invalid function arguments"; - break; - - case exports.ZodIssueCode.invalid_return_type: - message = "Invalid function return type"; - break; - - case exports.ZodIssueCode.invalid_date: - message = "Invalid date"; - break; - - case exports.ZodIssueCode.invalid_string: - if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; - break; - - case exports.ZodIssueCode.too_small: - if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at least" : "more than", " ").concat(issue.minimum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at least" : "over", " ").concat(issue.minimum, " character(s)");else if (issue.type === "number") message = "Number must be greater than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.minimum);else message = "Invalid input"; - break; - - case exports.ZodIssueCode.too_big: - if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at most" : "less than", " ").concat(issue.maximum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at most" : "under", " ").concat(issue.maximum, " character(s)");else if (issue.type === "number") message = "Number must be less than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.maximum);else message = "Invalid input"; - break; - - case exports.ZodIssueCode.custom: - message = "Invalid input"; - break; - - case exports.ZodIssueCode.invalid_intersection_types: - message = "Intersection results could not be merged"; - break; - - case exports.ZodIssueCode.not_multiple_of: - message = "Number must be a multiple of ".concat(issue.multipleOf); - break; + return keys; + }; - default: - message = _ctx.defaultError; - util_1.util.assertNever(issue); - } + util.find = (arr, checker) => { + for (const item of arr) { + if (checker(item)) return item; + } - return { - message + return undefined; }; -}; -exports.defaultErrorMap = defaultErrorMap; -exports.overrideErrorMap = exports.defaultErrorMap; + util.isInteger = typeof Number.isInteger === "function" ? val => Number.isInteger(val) // eslint-disable-line ban/ban + : val => typeof val === "number" && isFinite(val) && Math.floor(val) === val; -const setErrorMap = map => { - exports.overrideErrorMap = map; -}; + function joinValues(array) { + let separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : " | "; + return array.map(val => typeof val === "string" ? "'".concat(val, "'") : val).join(separator); + } -exports.setErrorMap = setErrorMap; + util.joinValues = joinValues; +})(util = exports.util || (exports.util = {})); -},{"./helpers/parseUtil":9,"./helpers/util":11}],7:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ "use strict"; var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { @@ -1027,6 +671,25 @@ var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? fun o[k2] = m[k]; }); +var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) { + Object.defineProperty(o, "default", { + enumerable: true, + value: v + }); +} : function (o, v) { + o["default"] = v; +}); + +var __importStar = void 0 && (void 0).__importStar || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + + __setModuleDefault(result, mod); + + return result; +}; + var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; @@ -1034,1031 +697,659 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { Object.defineProperty(exports, "__esModule", { value: true }); +exports.z = void 0; -__exportStar(require("./helpers/parseUtil"), exports); +const mod = __importStar(require("./external")); -__exportStar(require("./helpers/typeAliases"), exports); +exports.z = mod; -__exportStar(require("./types"), exports); +__exportStar(require("./external"), exports); -__exportStar(require("./ZodError"), exports); +exports.default = mod; -},{"./ZodError":6,"./helpers/parseUtil":9,"./helpers/typeAliases":10,"./types":13}],8:[function(require,module,exports){ +},{"./external":3}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.errorUtil = void 0; -var errorUtil; - -(function (errorUtil) { - errorUtil.errToObj = message => typeof message === "string" ? { - message - } : message || {}; - - errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; -})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); - -},{}],9:[function(require,module,exports){ -"use strict"; +exports.intersection = exports.instanceof = exports.function = exports.enum = exports.effect = exports.discriminatedUnion = exports.date = exports.boolean = exports.bigint = exports.array = exports.any = exports.ZodFirstPartyTypeKind = exports.late = exports.ZodSchema = exports.Schema = exports.custom = exports.ZodNaN = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransformer = exports.ZodEffects = exports.ZodPromise = exports.ZodNativeEnum = exports.ZodEnum = exports.ZodLiteral = exports.ZodLazy = exports.ZodFunction = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodUnion = exports.ZodObject = exports.objectUtil = exports.ZodArray = exports.ZodVoid = exports.ZodNever = exports.ZodUnknown = exports.ZodAny = exports.ZodNull = exports.ZodUndefined = exports.ZodDate = exports.ZodBoolean = exports.ZodBigInt = exports.ZodNumber = exports.ZodString = exports.ZodType = void 0; +exports.void = exports.unknown = exports.union = exports.undefined = exports.tuple = exports.transformer = exports.string = exports.strictObject = exports.set = exports.record = exports.promise = exports.preprocess = exports.ostring = exports.optional = exports.onumber = exports.oboolean = exports.object = exports.number = exports.nullable = exports.null = exports.never = exports.nativeEnum = exports.nan = exports.map = exports.literal = exports.lazy = void 0; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isAsync = exports.isValid = exports.isDirty = exports.isAborted = exports.OK = exports.DIRTY = exports.INVALID = exports.ParseStatus = exports.addIssueToContext = exports.EMPTY_PATH = exports.makeIssue = exports.getParsedType = exports.ZodParsedType = void 0; +const errorUtil_1 = require("./helpers/errorUtil"); -const ZodError_1 = require("../ZodError"); +const parseUtil_1 = require("./helpers/parseUtil"); -const util_1 = require("./util"); +const util_1 = require("./helpers/util"); -exports.ZodParsedType = util_1.util.arrayToEnum(["string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set"]); +const ZodError_1 = require("./ZodError"); -const getParsedType = data => { - const t = typeof data; +class ParseInputLazyPath { + constructor(parent, value, path, key) { + this.parent = parent; + this.data = value; + this._path = path; + this._key = key; + } - switch (t) { - case "undefined": - return exports.ZodParsedType.undefined; + get path() { + return this._path.concat(this._key); + } - case "string": - return exports.ZodParsedType.string; +} - case "number": - return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; +const handleResult = (ctx, result) => { + if ((0, parseUtil_1.isValid)(result)) { + return { + success: true, + data: result.value + }; + } else { + if (!ctx.common.issues.length) { + throw new Error("Validation failed but no issues detected."); + } - case "boolean": - return exports.ZodParsedType.boolean; + const error = new ZodError_1.ZodError(ctx.common.issues); + return { + success: false, + error + }; + } +}; - case "function": - return exports.ZodParsedType.function; +function processCreateParams(params) { + if (!params) return {}; + const { + errorMap, + invalid_type_error, + required_error, + description + } = params; - case "bigint": - return exports.ZodParsedType.bigint; + if (errorMap && (invalid_type_error || required_error)) { + throw new Error("Can't use \"invalid\" or \"required\" in conjunction with custom error map."); + } - case "object": - if (Array.isArray(data)) { - return exports.ZodParsedType.array; - } + if (errorMap) return { + errorMap: errorMap, + description + }; - if (data === null) { - return exports.ZodParsedType.null; - } - - if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { - return exports.ZodParsedType.promise; - } - - if (typeof Map !== "undefined" && data instanceof Map) { - return exports.ZodParsedType.map; - } - - if (typeof Set !== "undefined" && data instanceof Set) { - return exports.ZodParsedType.set; - } - - if (typeof Date !== "undefined" && data instanceof Date) { - return exports.ZodParsedType.date; - } - - return exports.ZodParsedType.object; - - default: - return exports.ZodParsedType.unknown; - } -}; - -exports.getParsedType = getParsedType; - -const makeIssue = params => { - const { - data, - path, - errorMaps, - issueData - } = params; - const fullPath = [...path, ...(issueData.path || [])]; - const fullIssue = { ...issueData, - path: fullPath + const customMap = (iss, ctx) => { + if (iss.code !== "invalid_type") return { + message: ctx.defaultError + }; + if (typeof ctx.data === "undefined" && required_error) return { + message: required_error + }; + if (params.invalid_type_error) return { + message: params.invalid_type_error + }; + return { + message: ctx.defaultError + }; }; - let errorMessage = ""; - const maps = errorMaps.filter(m => !!m).slice().reverse(); - - for (const map of maps) { - errorMessage = map(fullIssue, { - data, - defaultError: errorMessage - }).message; - } - return { ...issueData, - path: fullPath, - message: issueData.message || errorMessage + return { + errorMap: customMap, + description }; -}; - -exports.makeIssue = makeIssue; -exports.EMPTY_PATH = []; - -function addIssueToContext(ctx, issueData) { - const issue = (0, exports.makeIssue)({ - issueData: issueData, - data: ctx.data, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap // then global default map - ].filter(x => !!x) - }); - ctx.common.issues.push(issue); } -exports.addIssueToContext = addIssueToContext; - -class ParseStatus { - constructor() { - this.value = "valid"; +class ZodType { + constructor(def) { + /** Alias of safeParseAsync */ + this.spa = this.safeParseAsync; + this.superRefine = this._refinement; + this._def = def; + this.parse = this.parse.bind(this); + this.safeParse = this.safeParse.bind(this); + this.parseAsync = this.parseAsync.bind(this); + this.safeParseAsync = this.safeParseAsync.bind(this); + this.spa = this.spa.bind(this); + this.refine = this.refine.bind(this); + this.refinement = this.refinement.bind(this); + this.superRefine = this.superRefine.bind(this); + this.optional = this.optional.bind(this); + this.nullable = this.nullable.bind(this); + this.nullish = this.nullish.bind(this); + this.array = this.array.bind(this); + this.promise = this.promise.bind(this); + this.or = this.or.bind(this); + this.and = this.and.bind(this); + this.transform = this.transform.bind(this); + this.default = this.default.bind(this); + this.describe = this.describe.bind(this); + this.isNullable = this.isNullable.bind(this); + this.isOptional = this.isOptional.bind(this); } - dirty() { - if (this.value === "valid") this.value = "dirty"; + get description() { + return this._def.description; } - abort() { - if (this.value !== "aborted") this.value = "aborted"; + _getType(input) { + return (0, parseUtil_1.getParsedType)(input.data); } - static mergeArray(status, results) { - const arrayValue = []; - - for (const s of results) { - if (s.status === "aborted") return exports.INVALID; - if (s.status === "dirty") status.dirty(); - arrayValue.push(s.value); - } + _getOrReturnCtx(input, ctx) { + return ctx || { + common: input.parent.common, + data: input.data, + parsedType: (0, parseUtil_1.getParsedType)(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + }; + } + _processInputParams(input) { return { - status: status.value, - value: arrayValue + status: new parseUtil_1.ParseStatus(), + ctx: { + common: input.parent.common, + data: input.data, + parsedType: (0, parseUtil_1.getParsedType)(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + } }; } - static async mergeObjectAsync(status, pairs) { - const syncPairs = []; + _parseSync(input) { + const result = this._parse(input); - for (const pair of pairs) { - syncPairs.push({ - key: await pair.key, - value: await pair.value - }); + if ((0, parseUtil_1.isAsync)(result)) { + throw new Error("Synchronous parse encountered promise."); } - return ParseStatus.mergeObjectSync(status, syncPairs); + return result; } - static mergeObjectSync(status, pairs) { - const finalObject = {}; - - for (const pair of pairs) { - const { - key, - value - } = pair; - if (key.status === "aborted") return exports.INVALID; - if (value.status === "aborted") return exports.INVALID; - if (key.status === "dirty") status.dirty(); - if (value.status === "dirty") status.dirty(); - - if (typeof value.value !== "undefined" || pair.alwaysSet) { - finalObject[key.value] = value.value; - } - } + _parseAsync(input) { + const result = this._parse(input); - return { - status: status.value, - value: finalObject - }; + return Promise.resolve(result); } -} - -exports.ParseStatus = ParseStatus; -exports.INVALID = Object.freeze({ - status: "aborted" -}); + parse(data, params) { + const result = this.safeParse(data, params); + if (result.success) return result.data; + throw result.error; + } -const DIRTY = value => ({ - status: "dirty", - value -}); + safeParse(data, params) { + var _a; -exports.DIRTY = DIRTY; + const ctx = { + common: { + issues: [], + async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false, + contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap + }, + path: (params === null || params === void 0 ? void 0 : params.path) || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: (0, parseUtil_1.getParsedType)(data) + }; -const OK = value => ({ - status: "valid", - value -}); + const result = this._parseSync({ + data, + path: ctx.path, + parent: ctx + }); -exports.OK = OK; + return handleResult(ctx, result); + } -const isAborted = x => x.status === "aborted"; + async parseAsync(data, params) { + const result = await this.safeParseAsync(data, params); + if (result.success) return result.data; + throw result.error; + } -exports.isAborted = isAborted; + async safeParseAsync(data, params) { + const ctx = { + common: { + issues: [], + contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, + async: true + }, + path: (params === null || params === void 0 ? void 0 : params.path) || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: (0, parseUtil_1.getParsedType)(data) + }; -const isDirty = x => x.status === "dirty"; + const maybeAsyncResult = this._parse({ + data, + path: [], + parent: ctx + }); -exports.isDirty = isDirty; + const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } -const isValid = x => x.status === "valid"; - -exports.isValid = isValid; - -const isAsync = x => typeof Promise !== undefined && x instanceof Promise; - -exports.isAsync = isAsync; - -},{"../ZodError":6,"./util":11}],10:[function(require,module,exports){ -"use strict"; + refine(check, message) { + const getIssueProperties = val => { + if (typeof message === "string" || typeof message === "undefined") { + return { + message + }; + } else if (typeof message === "function") { + return message(val); + } else { + return message; + } + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); + return this._refinement((val, ctx) => { + const result = check(val); -},{}],11:[function(require,module,exports){ -"use strict"; + const setError = () => ctx.addIssue({ + code: ZodError_1.ZodIssueCode.custom, + ...getIssueProperties(val) + }); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.util = void 0; -var util; + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then(data => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); + } -(function (util) { - function assertNever(_x) { - throw new Error(); + if (!result) { + setError(); + return false; + } else { + return true; + } + }); } - util.assertNever = assertNever; - - util.arrayToEnum = items => { - const obj = {}; - - for (const item of items) { - obj[item] = item; - } - - return obj; - }; - - util.getValidEnumValues = obj => { - const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); - const filtered = {}; - - for (const k of validKeys) { - filtered[k] = obj[k]; - } - - return util.objectValues(filtered); - }; - - util.objectValues = obj => { - return util.objectKeys(obj).map(function (e) { - return obj[e]; + refinement(check, refinementData) { + return this._refinement((val, ctx) => { + if (!check(val)) { + ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); + return false; + } else { + return true; + } }); - }; - - util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban - ? obj => Object.keys(obj) // eslint-disable-line ban/ban - : object => { - const keys = []; + } - for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key)) { - keys.push(key); + _refinement(refinement) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "refinement", + refinement } - } - - return keys; - }; + }); + } - util.find = (arr, checker) => { - for (const item of arr) { - if (checker(item)) return item; - } + optional() { + return ZodOptional.create(this); + } - return undefined; - }; + nullable() { + return ZodNullable.create(this); + } - util.isInteger = typeof Number.isInteger === "function" ? val => Number.isInteger(val) // eslint-disable-line ban/ban - : val => typeof val === "number" && isFinite(val) && Math.floor(val) === val; + nullish() { + return this.optional().nullable(); + } - function joinValues(array) { - let separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : " | "; - return array.map(val => typeof val === "string" ? "'".concat(val, "'") : val).join(separator); + array() { + return ZodArray.create(this); } - util.joinValues = joinValues; -})(util = exports.util || (exports.util = {})); + promise() { + return ZodPromise.create(this); + } -},{}],12:[function(require,module,exports){ -"use strict"; + or(option) { + return ZodUnion.create([this, option]); + } -var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); + and(incoming) { + return ZodIntersection.create(this, incoming); + } - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; + transform(transform) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "transform", + transform } - }; + }); } - Object.defineProperty(o, k2, desc); -} : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -}); - -var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) { - Object.defineProperty(o, "default", { - enumerable: true, - value: v - }); -} : function (o, v) { - o["default"] = v; -}); - -var __importStar = void 0 && (void 0).__importStar || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - - __setModuleDefault(result, mod); + default(def) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + return new ZodDefault({ + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault + }); + } - return result; -}; + describe(description) { + const This = this.constructor; + return new This({ ...this._def, + description + }); + } -var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; + isOptional() { + return this.safeParse(undefined).success; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.z = void 0; + isNullable() { + return this.safeParse(null).success; + } -const mod = __importStar(require("./external")); +} -exports.z = mod; +exports.ZodType = ZodType; +exports.Schema = ZodType; +exports.ZodSchema = ZodType; +const cuidRegex = /^c[^\s-]{8,}$/i; +const uuidRegex = /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; // from https://stackoverflow.com/a/46181/1550155 +// old version: too slow, didn't support unicode +// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; +// eslint-disable-next-line -__exportStar(require("./external"), exports); +const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; -exports.default = mod; +class ZodString extends ZodType { + constructor() { + super(...arguments); -},{"./external":7}],13:[function(require,module,exports){ -"use strict"; + this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { + validation, + code: ZodError_1.ZodIssueCode.invalid_string, + ...errorUtil_1.errorUtil.errToObj(message) + }); + /** + * Deprecated. + * Use z.string().min(1) instead. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.intersection = exports.instanceof = exports.function = exports.enum = exports.effect = exports.discriminatedUnion = exports.date = exports.boolean = exports.bigint = exports.array = exports.any = exports.ZodFirstPartyTypeKind = exports.late = exports.ZodSchema = exports.Schema = exports.custom = exports.ZodNaN = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransformer = exports.ZodEffects = exports.ZodPromise = exports.ZodNativeEnum = exports.ZodEnum = exports.ZodLiteral = exports.ZodLazy = exports.ZodFunction = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodUnion = exports.ZodObject = exports.objectUtil = exports.ZodArray = exports.ZodVoid = exports.ZodNever = exports.ZodUnknown = exports.ZodAny = exports.ZodNull = exports.ZodUndefined = exports.ZodDate = exports.ZodBoolean = exports.ZodBigInt = exports.ZodNumber = exports.ZodString = exports.ZodType = void 0; -exports.void = exports.unknown = exports.union = exports.undefined = exports.tuple = exports.transformer = exports.string = exports.strictObject = exports.set = exports.record = exports.promise = exports.preprocess = exports.ostring = exports.optional = exports.onumber = exports.oboolean = exports.object = exports.number = exports.nullable = exports.null = exports.never = exports.nativeEnum = exports.nan = exports.map = exports.literal = exports.lazy = void 0; -const errorUtil_1 = require("./helpers/errorUtil"); + this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); + } -const parseUtil_1 = require("./helpers/parseUtil"); + _parse(input) { + const parsedType = this._getType(input); -const util_1 = require("./helpers/util"); + if (parsedType !== parseUtil_1.ZodParsedType.string) { + const ctx = this._getOrReturnCtx(input); -const ZodError_1 = require("./ZodError"); - -class ParseInputLazyPath { - constructor(parent, value, path, key) { - this.parent = parent; - this.data = value; - this._path = path; - this._key = key; - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.string, + received: ctx.parsedType + } // + ); + return parseUtil_1.INVALID; + } - get path() { - return this._path.concat(this._key); - } + const status = new parseUtil_1.ParseStatus(); + let ctx = undefined; -} + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.length < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.length > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "email") { + if (!emailRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "email", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "uuid") { + if (!uuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "uuid", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "cuid") { + if (!cuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "cuid", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "url") { + try { + new URL(input.data); + } catch (_a) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "url", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "regex") { + check.regex.lastIndex = 0; + const testResult = check.regex.test(input.data); -const handleResult = (ctx, result) => { - if ((0, parseUtil_1.isValid)(result)) { - return { - success: true, - data: result.value - }; - } else { - if (!ctx.common.issues.length) { - throw new Error("Validation failed but no issues detected."); + if (!testResult) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "regex", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } } - const error = new ZodError_1.ZodError(ctx.common.issues); return { - success: false, - error + status: status.value, + value: input.data }; } -}; - -function processCreateParams(params) { - if (!params) return {}; - const { - errorMap, - invalid_type_error, - required_error, - description - } = params; - if (errorMap && (invalid_type_error || required_error)) { - throw new Error("Can't use \"invalid\" or \"required\" in conjunction with custom error map."); + _addCheck(check) { + return new ZodString({ ...this._def, + checks: [...this._def.checks, check] + }); } - if (errorMap) return { - errorMap: errorMap, - description - }; + email(message) { + return this._addCheck({ + kind: "email", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } - const customMap = (iss, ctx) => { - if (iss.code !== "invalid_type") return { - message: ctx.defaultError - }; - if (typeof ctx.data === "undefined" && required_error) return { - message: required_error - }; - if (params.invalid_type_error) return { - message: params.invalid_type_error - }; - return { - message: ctx.defaultError - }; - }; + url(message) { + return this._addCheck({ + kind: "url", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } - return { - errorMap: customMap, - description - }; -} + uuid(message) { + return this._addCheck({ + kind: "uuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -class ZodType { - constructor(def) { - /** Alias of safeParseAsync */ - this.spa = this.safeParseAsync; - this.superRefine = this._refinement; - this._def = def; - this.parse = this.parse.bind(this); - this.safeParse = this.safeParse.bind(this); - this.parseAsync = this.parseAsync.bind(this); - this.safeParseAsync = this.safeParseAsync.bind(this); - this.spa = this.spa.bind(this); - this.refine = this.refine.bind(this); - this.refinement = this.refinement.bind(this); - this.superRefine = this.superRefine.bind(this); - this.optional = this.optional.bind(this); - this.nullable = this.nullable.bind(this); - this.nullish = this.nullish.bind(this); - this.array = this.array.bind(this); - this.promise = this.promise.bind(this); - this.or = this.or.bind(this); - this.and = this.and.bind(this); - this.transform = this.transform.bind(this); - this.default = this.default.bind(this); - this.describe = this.describe.bind(this); - this.isNullable = this.isNullable.bind(this); - this.isOptional = this.isOptional.bind(this); + cuid(message) { + return this._addCheck({ + kind: "cuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); } - get description() { - return this._def.description; + regex(regex, message) { + return this._addCheck({ + kind: "regex", + regex: regex, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _getType(input) { - return (0, parseUtil_1.getParsedType)(input.data); + min(minLength, message) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _getOrReturnCtx(input, ctx) { - return ctx || { - common: input.parent.common, - data: input.data, - parsedType: (0, parseUtil_1.getParsedType)(input.data), - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent - }; + max(maxLength, message) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _processInputParams(input) { - return { - status: new parseUtil_1.ParseStatus(), - ctx: { - common: input.parent.common, - data: input.data, - parsedType: (0, parseUtil_1.getParsedType)(input.data), - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent - } - }; + length(len, message) { + return this.min(len, message).max(len, message); } - _parseSync(input) { - const result = this._parse(input); + get isEmail() { + return !!this._def.checks.find(ch => ch.kind === "email"); + } - if ((0, parseUtil_1.isAsync)(result)) { - throw new Error("Synchronous parse encountered promise."); - } - - return result; - } - - _parseAsync(input) { - const result = this._parse(input); - - return Promise.resolve(result); - } - - parse(data, params) { - const result = this.safeParse(data, params); - if (result.success) return result.data; - throw result.error; - } - - safeParse(data, params) { - var _a; - - const ctx = { - common: { - issues: [], - async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false, - contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap - }, - path: (params === null || params === void 0 ? void 0 : params.path) || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: (0, parseUtil_1.getParsedType)(data) - }; - - const result = this._parseSync({ - data, - path: ctx.path, - parent: ctx - }); - - return handleResult(ctx, result); - } - - async parseAsync(data, params) { - const result = await this.safeParseAsync(data, params); - if (result.success) return result.data; - throw result.error; + get isURL() { + return !!this._def.checks.find(ch => ch.kind === "url"); } - async safeParseAsync(data, params) { - const ctx = { - common: { - issues: [], - contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, - async: true - }, - path: (params === null || params === void 0 ? void 0 : params.path) || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: (0, parseUtil_1.getParsedType)(data) - }; - - const maybeAsyncResult = this._parse({ - data, - path: [], - parent: ctx - }); - - const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); - return handleResult(ctx, result); + get isUUID() { + return !!this._def.checks.find(ch => ch.kind === "uuid"); } - refine(check, message) { - const getIssueProperties = val => { - if (typeof message === "string" || typeof message === "undefined") { - return { - message - }; - } else if (typeof message === "function") { - return message(val); - } else { - return message; - } - }; - - return this._refinement((val, ctx) => { - const result = check(val); - - const setError = () => ctx.addIssue({ - code: ZodError_1.ZodIssueCode.custom, - ...getIssueProperties(val) - }); - - if (typeof Promise !== "undefined" && result instanceof Promise) { - return result.then(data => { - if (!data) { - setError(); - return false; - } else { - return true; - } - }); - } - - if (!result) { - setError(); - return false; - } else { - return true; - } - }); + get isCUID() { + return !!this._def.checks.find(ch => ch.kind === "cuid"); } - refinement(check, refinementData) { - return this._refinement((val, ctx) => { - if (!check(val)) { - ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); - return false; - } else { - return true; - } - }); - } + get minLength() { + let min = -Infinity; - _refinement(refinement) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "refinement", - refinement + this._def.checks.map(ch => { + if (ch.kind === "min") { + if (min === null || ch.value > min) { + min = ch.value; + } } }); - } - - optional() { - return ZodOptional.create(this); - } - - nullable() { - return ZodNullable.create(this); - } - - nullish() { - return this.optional().nullable(); - } - - array() { - return ZodArray.create(this); - } - - promise() { - return ZodPromise.create(this); - } - or(option) { - return ZodUnion.create([this, option]); + return min; } - and(incoming) { - return ZodIntersection.create(this, incoming); - } + get maxLength() { + let max = null; - transform(transform) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "transform", - transform + this._def.checks.map(ch => { + if (ch.kind === "max") { + if (max === null || ch.value < max) { + max = ch.value; + } } }); - } - - default(def) { - const defaultValueFunc = typeof def === "function" ? def : () => def; - return new ZodDefault({ - innerType: this, - defaultValue: defaultValueFunc, - typeName: ZodFirstPartyTypeKind.ZodDefault - }); - } - describe(description) { - const This = this.constructor; - return new This({ ...this._def, - description - }); + return max; } - isOptional() { - return this.safeParse(undefined).success; - } +} - isNullable() { - return this.safeParse(null).success; - } +exports.ZodString = ZodString; -} +ZodString.create = params => { + return new ZodString({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodString, + ...processCreateParams(params) + }); +}; // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 -exports.ZodType = ZodType; -exports.Schema = ZodType; -exports.ZodSchema = ZodType; -const cuidRegex = /^c[^\s-]{8,}$/i; -const uuidRegex = /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; // from https://stackoverflow.com/a/46181/1550155 -// old version: too slow, didn't support unicode -// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; -// eslint-disable-next-line -const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; +function floatSafeRemainder(val, step) { + const valDecCount = (val.toString().split(".")[1] || "").length; + const stepDecCount = (step.toString().split(".")[1] || "").length; + const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; + const valInt = parseInt(val.toFixed(decCount).replace(".", "")); + const stepInt = parseInt(step.toFixed(decCount).replace(".", "")); + return valInt % stepInt / Math.pow(10, decCount); +} -class ZodString extends ZodType { +class ZodNumber extends ZodType { constructor() { super(...arguments); - - this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { - validation, - code: ZodError_1.ZodIssueCode.invalid_string, - ...errorUtil_1.errorUtil.errToObj(message) - }); - /** - * Deprecated. - * Use z.string().min(1) instead. - */ - - - this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); + this.min = this.gte; + this.max = this.lte; + this.step = this.multipleOf; } _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.string) { + if (parsedType !== parseUtil_1.ZodParsedType.number) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.string, + expected: parseUtil_1.ZodParsedType.number, received: ctx.parsedType - } // - ); + }); return parseUtil_1.INVALID; } - const status = new parseUtil_1.ParseStatus(); let ctx = undefined; - - for (const check of this._def.checks) { - if (check.kind === "min") { - if (input.data.length < check.value) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: check.value, - type: "string", - inclusive: true, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "max") { - if (input.data.length > check.value) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: check.value, - type: "string", - inclusive: true, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "email") { - if (!emailRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "email", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "uuid") { - if (!uuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "uuid", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "cuid") { - if (!cuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "cuid", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "url") { - try { - new URL(input.data); - } catch (_a) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "url", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "regex") { - check.regex.lastIndex = 0; - const testResult = check.regex.test(input.data); - - if (!testResult) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "regex", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } - } - - return { - status: status.value, - value: input.data - }; - } - - _addCheck(check) { - return new ZodString({ ...this._def, - checks: [...this._def.checks, check] - }); - } - - email(message) { - return this._addCheck({ - kind: "email", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - url(message) { - return this._addCheck({ - kind: "url", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - uuid(message) { - return this._addCheck({ - kind: "uuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - cuid(message) { - return this._addCheck({ - kind: "cuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - regex(regex, message) { - return this._addCheck({ - kind: "regex", - regex: regex, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - min(minLength, message) { - return this._addCheck({ - kind: "min", - value: minLength, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - max(maxLength, message) { - return this._addCheck({ - kind: "max", - value: maxLength, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - length(len, message) { - return this.min(len, message).max(len, message); - } - - get isEmail() { - return !!this._def.checks.find(ch => ch.kind === "email"); - } - - get isURL() { - return !!this._def.checks.find(ch => ch.kind === "url"); - } - - get isUUID() { - return !!this._def.checks.find(ch => ch.kind === "uuid"); - } - - get isCUID() { - return !!this._def.checks.find(ch => ch.kind === "cuid"); - } - - get minLength() { - let min = -Infinity; - - this._def.checks.map(ch => { - if (ch.kind === "min") { - if (min === null || ch.value > min) { - min = ch.value; - } - } - }); - - return min; - } - - get maxLength() { - let max = null; - - this._def.checks.map(ch => { - if (ch.kind === "max") { - if (max === null || ch.value < max) { - max = ch.value; - } - } - }); - - return max; - } - -} - -exports.ZodString = ZodString; - -ZodString.create = params => { - return new ZodString({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodString, - ...processCreateParams(params) - }); -}; // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 - - -function floatSafeRemainder(val, step) { - const valDecCount = (val.toString().split(".")[1] || "").length; - const stepDecCount = (step.toString().split(".")[1] || "").length; - const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; - const valInt = parseInt(val.toFixed(decCount).replace(".", "")); - const stepInt = parseInt(step.toFixed(decCount).replace(".", "")); - return valInt % stepInt / Math.pow(10, decCount); -} - -class ZodNumber extends ZodType { - constructor() { - super(...arguments); - this.min = this.gte; - this.max = this.lte; - this.step = this.multipleOf; - } - - _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.number) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.number, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } - - let ctx = undefined; - const status = new parseUtil_1.ParseStatus(); + const status = new parseUtil_1.ParseStatus(); for (const check of this._def.checks) { if (check.kind === "int") { @@ -4429,464 +3720,1073 @@ const ostring = () => stringType().optional(); exports.ostring = ostring; -const onumber = () => numberType().optional(); +const onumber = () => numberType().optional(); + +exports.onumber = onumber; + +const oboolean = () => booleanType().optional(); + +exports.oboolean = oboolean; + +},{"./ZodError":2,"./helpers/errorUtil":4,"./helpers/parseUtil":5,"./helpers/util":7}],10:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "DeviceApi", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApi; + } +}); +Object.defineProperty(exports, "DeviceApiCall", { + enumerable: true, + get: function () { + return _deviceApiCall.DeviceApiCall; + } +}); +Object.defineProperty(exports, "DeviceApiTransport", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApiTransport; + } +}); +Object.defineProperty(exports, "createNotification", { + enumerable: true, + get: function () { + return _deviceApiCall.createNotification; + } +}); +Object.defineProperty(exports, "createRequest", { + enumerable: true, + get: function () { + return _deviceApiCall.createRequest; + } +}); +Object.defineProperty(exports, "validate", { + enumerable: true, + get: function () { + return _deviceApiCall.validate; + } +}); + +var _deviceApiCall = require("./lib/device-api-call.js"); + +var _deviceApi = require("./lib/device-api.js"); + +},{"./lib/device-api-call.js":11,"./lib/device-api.js":12}],11:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; +exports.createDeviceApiCall = createDeviceApiCall; +exports.createNotification = void 0; +exports.createRequest = createRequest; +exports.validate = validate; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * This roughly follows https://www.jsonrpc.org/specification + * @template {import("zod").ZodType} Params=import("zod").ZodType + * @template {import("zod").ZodType} Result=import("zod").ZodType + */ +class DeviceApiCall { + /** @type {string} */ + + /** + * An optional 'id' - used to indicate if a request requires a response. + * @type {string|null} + */ + + /** @type {Params | null | undefined} */ + + /** @type {Result | null | undefined} */ + + /** @type {import("zod").infer} */ + + /** + * This is a carve-out for legacy messages that are not typed yet. + * If you set this to 'true', then the response will not be checked to conform + * to any shape + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ + + /** + * New messages should be in a particular format, eg: { success: T }, + * but you can set this to false if you want to access the result as-is, + * without any unwrapping logic + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ + + /** + * @param {import("zod").infer} data + */ + constructor(data) { + _defineProperty(this, "method", 'unknown'); + + _defineProperty(this, "id", null); + + _defineProperty(this, "paramsValidator", null); + + _defineProperty(this, "resultValidator", null); + + _defineProperty(this, "params", void 0); + + _defineProperty(this, "throwOnResultKeysMissing", true); + + _defineProperty(this, "unwrapResult", true); + + this.params = data; + } + /** + * @returns {import("zod").infer|undefined} + */ + + + validateParams() { + if (this.params === undefined) { + return undefined; + } + + this._validate(this.params, this.paramsValidator); + + return this.params; + } + /** + * @param {any|null} incoming + * @returns {import("zod").infer} + */ + + + validateResult(incoming) { + this._validate(incoming, this.resultValidator); + + if (!incoming) { + return incoming; + } + + if (!this.unwrapResult) { + return incoming; + } + + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } + + if ('success' in incoming) { + return incoming.success; + } + + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + } + } + + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); + } + + return incoming; + } + /** + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private + */ + + + _validate(data, validator) { + if (!validator) return data; + + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + + if (!result) { + throw new Error('unreachable, data failure', data); + } + + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } + } + } + } + /** + * @param {import('zod').ZodIssue[]} errors + */ + + + throwError(errors) { + const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); + throw error; + } + /** + * Use this helper for creating stand-in response messages that are typed correctly. + * + * @examples + * + * ```js + * const msg = new Message(); + * const response = msg.response({}) // <-- This argument will be typed correctly + * ``` + * + * @param {import("zod").infer} response + * @returns {import("zod").infer} + */ + + + result(response) { + return response; + } + /** + * @returns {import("zod").infer} + */ + + + preResultValidation(response) { + return response; + } + +} + +exports.DeviceApiCall = DeviceApiCall; + +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ + + +exports.DeviceApiCallError = DeviceApiCallError; + +class SchemaValidationError extends Error { + constructor() { + super(...arguments); + + _defineProperty(this, "validationErrors", []); + } + + /** + * @param {import("zod").ZodIssue[]} errors + * @param {string} name + * @returns {SchemaValidationError} + */ + static fromZodErrors(errors, name) { + const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; + + function log(issue) { + switch (issue.code) { + case 'invalid_literal': + case 'invalid_type': + { + console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); + break; + } + + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } + + break; + } + + default: + { + console.log(name, 'other issue:', issue); + } + } + } + + for (let error of errors) { + log(error); + } + + const message = [heading, 'please see the details above'].join('\n '); + const error = new SchemaValidationError(message); + error.validationErrors = errors; + return error; + } + +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ + + +exports.SchemaValidationError = SchemaValidationError; + +function createDeviceApiCall(method, params) { + let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + /** @type {DeviceApiCall} */ + const deviceApiCall = new DeviceApiCall(params); + deviceApiCall.paramsValidator = paramsValidator; + deviceApiCall.resultValidator = resultValidator; + deviceApiCall.method = method; + deviceApiCall.throwOnResultKeysMissing = false; + deviceApiCall.unwrapResult = false; + return deviceApiCall; +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string + * so that transports know that it expects a response. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {string} [id] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ + + +function createRequest(method, params) { + let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; + let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); + call.id = id; + return call; +} + +const createNotification = createDeviceApiCall; +/** + * Validate any arbitrary data with any Zod validator + * + * @template {import("zod").ZodType} Validator + * @param {any} data + * @param {Validator | null} [validator] + * @returns {import("zod").infer} + */ + +exports.createNotification = createNotification; + +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (validator) { + return validator.parse(data); + } + + return data; +} + +},{}],12:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Platforms should only need to implement this `send` method + */ +class DeviceApiTransport { + /** + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} + */ + async send(_deviceApiCall, _options) { + return undefined; + } + +} +/** + * This is the base Sender class that platforms can will implement. + * + * Note: The 'handle' method must be implemented, unless you also implement 'send' + * + * @typedef CallOptions + * @property {AbortSignal} [signal] + */ + + +exports.DeviceApiTransport = DeviceApiTransport; + +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ + + + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); + } + /** + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} + */ + -exports.onumber = onumber; + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); + } -const oboolean = () => booleanType().optional(); +} -exports.oboolean = oboolean; +exports.DeviceApi = DeviceApi; -},{"./ZodError":6,"./helpers/errorUtil":8,"./helpers/parseUtil":9,"./helpers/util":11}],14:[function(require,module,exports){ +},{}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -Object.defineProperty(exports, "DeviceApi", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApi; - } -}); -Object.defineProperty(exports, "DeviceApiCall", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.DeviceApiCall; + return _webkit.WebkitMessagingConfig; } }); -Object.defineProperty(exports, "DeviceApiTransport", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApiTransport; + +var _webkit = require("./webkit.js"); + +/** + * @module Messaging + * + * @description + * + * An abstraction for communications between JavaScript and host platforms. + * + * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) + * 2) Then use that to get an instance of the Messaging utility which allows + * you to send and receive data in a unified way + * 3) Each platform implements {@link MessagingTransport} along with its own Configuration + * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} + * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} + * + * @example Webkit Messaging + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + * + * @example Windows Messaging + * + * ```js + * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // Messaging on Windows is namespaced, so you can create multiple messaging instances + * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); + * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); + * + * const autofillMessaging = new Messaging(autofillConfig); + * const debugMessaging = new Messaging(debugConfig); + * + * // Now send messages to both features as needed 🚀 + * autofillMessaging.notify("storeFormData", { "username": "dax" }) + * debugMessaging.notify("pageLoad", { time: window.performance.now() }) + * ``` + */ + +/** + * @implements {MessagingTransport} + */ +class Messaging { + /** + * @param {WebkitMessagingConfig} config + */ + constructor(config) { + this.transport = getTransport(config); } -}); -Object.defineProperty(exports, "createNotification", { - enumerable: true, - get: function () { - return _deviceApiCall.createNotification; + /** + * Send a 'fire-and-forget' message. + * @throws {Error} + * {@link MissingHandler} + * + * @example + * + * ``` + * const messaging = new Messaging(config) + * messaging.notify("foo", {bar: "baz"}) + * ``` + * @param {string} name + * @param {Record} [data] + */ + + + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.transport.notify(name, data); } -}); -Object.defineProperty(exports, "createRequest", { - enumerable: true, - get: function () { - return _deviceApiCall.createRequest; + /** + * Send a request, and wait for a response + * @throws {Error} + * {@link MissingHandler} + * + * @example + * ``` + * const messaging = new Messaging(config) + * const response = await messaging.request("foo", {bar: "baz"}) + * ``` + * + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + + + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); } -}); -Object.defineProperty(exports, "validate", { - enumerable: true, - get: function () { - return _deviceApiCall.validate; + +} +/** + * @interface + */ + + +exports.Messaging = Messaging; + +class MessagingTransport { + /** + * @param {string} name + * @param {Record} [data] + * @returns {void} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error("must implement 'notify'"); } -}); + /** + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. -var _deviceApiCall = require("./lib/device-api-call.js"); -var _deviceApi = require("./lib/device-api.js"); + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); + } -},{"./lib/device-api-call.js":15,"./lib/device-api.js":16}],15:[function(require,module,exports){ -"use strict"; +} +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; -exports.createDeviceApiCall = createDeviceApiCall; -exports.createNotification = void 0; -exports.createRequest = createRequest; -exports.validate = validate; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +exports.MessagingTransport = MessagingTransport; + +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); + } + throw new Error('unreachable'); +} /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * Thrown when a handler cannot be found */ -class DeviceApiCall { - /** @type {string} */ + +class MissingHandler extends Error { /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} - */ + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } - /** @type {Params | null | undefined} */ +} +/** + * Some re-exports for convenience + */ - /** @type {Result | null | undefined} */ - /** @type {import("zod").infer} */ +exports.MissingHandler = MissingHandler; - /** - * This is a carve-out for legacy messages that are not typed yet. - * If you set this to 'true', then the response will not be checked to conform - * to any shape - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +},{"./webkit.js":14}],14:[function(require,module,exports){ +"use strict"; - /** - * New messages should be in a particular format, eg: { success: T }, - * but you can set this to false if you want to access the result as-is, - * without any unwrapping logic - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + +var _messaging = require("./messaging.js"); + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @typedef {import("./messaging").MessagingTransport} MessagingTransport + */ + +/** + * @example + * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` + * + * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following + * would occur: + * + * ```js + * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); + * const response = JSON.parse(json) + * ``` + * + * @example + * On macOS 10 however, the process is a little more involved. A method will be appended to `window` + * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow + * as being something along the lines of: + * + * ```js + * // add the window method + * window["_0123456"] = (response) => { + * // decrypt `response` and deliver the result to the caller here + * // then remove the temporary method + * delete window["_0123456"] + * }; + * + * // send the data + `messageHanding` values + * window.webkit.messageHandlers.foo.postMessage({ + * bar: "baz", + * messagingHandling: { + * methodName: "_0123456", + * secret: "super-secret", + * key: [1, 2, 45, 2], + * iv: [34, 4, 43], + * } + * }); + * + * // later in swift, the following JavaScript snippet will be executed + * (() => { + * window["_0123456"]({ + * ciphertext: [12, 13, 4], + * tag: [3, 5, 67, 56] + * }) + * })() + * ``` + * @implements {MessagingTransport} + */ +class WebkitMessagingTransport { + /** @type {WebkitMessagingConfig} */ /** - * @param {import("zod").infer} data + * @param {WebkitMessagingConfig} config */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - - _defineProperty(this, "resultValidator", null); - - _defineProperty(this, "params", void 0); - - _defineProperty(this, "throwOnResultKeysMissing", true); + constructor(config) { + _defineProperty(this, "config", void 0); - _defineProperty(this, "unwrapResult", true); + _defineProperty(this, "globals", void 0); - this.params = data; - } - /** - * @returns {import("zod").infer|undefined} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - validateParams() { - if (this.params === undefined) { - return undefined; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - this._validate(this.params, this.paramsValidator); - - return this.params; } /** - * @param {any|null} incoming - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - validateResult(incoming) { - this._validate(incoming, this.resultValidator); - - if (!incoming) { - return incoming; - } - - if (!this.unwrapResult) { - return incoming; - } + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if ('success' in incoming) { - return incoming.success; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); } - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } - } + }; - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + if (!(handler in this.globals.capturedWebkitHandlers)) { + throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); + } else { + return this.globals.capturedWebkitHandlers[handler](outgoing); + } } - return incoming; + return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - _validate(data, validator) { - if (!validator) return data; - - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + try { + const randMethodName = this.createRandMethodName(); + const key = await this.createRandKey(); + const iv = this.createRandIv(); + const { + ciphertext, + tag + } = await new this.globals.Promise(( + /** @type {any} */ + resolve) => { + this.generateRandomMethod(randMethodName, resolve); + data.messageHandling = new SecureMessagingParams({ + methodName: randMethodName, + secret: this.config.secret, + key: this.globals.Arrayfrom(key), + iv: this.globals.Arrayfrom(iv) + }); + this.wkSend(handler, data); + }); + const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); + const decrypted = await this.decrypt(cipher, key, iv); + return this.globals.JSONparse(decrypted || '{}'); + } catch (e) { + // re-throw when the error is just a 'MissingHandler' + if (e instanceof _messaging.MissingHandler) { + throw e; + } else { + console.error('decryption failed', e); + console.error(e); + return { + error: e + }; } } } /** - * @param {import('zod').ZodIssue[]} errors + * @param {string} name + * @param {Record} [data] */ - throwError(errors) { - const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); - throw error; + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } /** - * Use this helper for creating stand-in response messages that are typed correctly. - * - * @examples - * - * ```js - * const msg = new Message(); - * const response = msg.response({}) // <-- This argument will be typed correctly - * ``` - * - * @param {import("zod").infer} response - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - result(response) { - return response; + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.wkSendAndWait(name, data); } /** - * @returns {import("zod").infer} + * Generate a random method name and adds it to the global scope + * The native layer will use this method to send the response + * @param {string | number} randomMethodName + * @param {Function} callback */ - preResultValidation(response) { - return response; - } + generateRandomMethod(randomMethodName, callback) { + var _this = this; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -exports.DeviceApiCall = DeviceApiCall; + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + delete _this.globals.window[randomMethodName]; + } + }); + } + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.DeviceApiCallError = DeviceApiCallError; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -class SchemaValidationError extends Error { - constructor() { - super(...arguments); - _defineProperty(this, "validationErrors", []); + /** + * @returns {Promise} + */ + async createRandKey() { + const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); + const exportedKey = await this.globals.exportKey('raw', key); + return new this.globals.Uint8Array(exportedKey); } + /** + * @returns {Uint8Array} + */ + + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } /** - * @param {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ + + + async decrypt(ciphertext, key, iv) { + const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); + const algo = { + name: 'AES-GCM', + iv + }; + let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); + let dec = new this.globals.TextDecoder(); + return dec.decode(decrypted); + } + /** + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - static fromZodErrors(errors, name) { - const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; - function log(issue) { - switch (issue.code) { - case 'invalid_literal': - case 'invalid_type': - { - console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); - break; - } - case 'invalid_union': - { - for (let unionError of issue.unionErrors) { - for (let issue1 of unionError.issues) { - log(issue1); - } - } + captureWebkitHandlers(handlerNames) { + const handlers = window.webkit.messageHandlers; + if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - break; - } + for (let webkitMessageHandlerName of handlerNames) { + var _handlers$webkitMessa; - default: - { - console.log(name, 'other issue:', issue); - } - } - } + if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { + var _handlers$webkitMessa2; - for (let error of errors) { - log(error); + /** + * `bind` is used here to ensure future calls to the captured + * `postMessage` have the correct `this` context + */ + const original = handlers[webkitMessageHandlerName]; + const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); + this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; + delete handlers[webkitMessageHandlerName].postMessage; + } } - - const message = [heading, 'please see the details above'].join('\n '); - const error = new SchemaValidationError(message); - error.validationErrors = errors; - return error; } } /** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} - */ - - -exports.SchemaValidationError = SchemaValidationError; - -function createDeviceApiCall(method, params) { - let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - /** @type {DeviceApiCall} */ - const deviceApiCall = new DeviceApiCall(params); - deviceApiCall.paramsValidator = paramsValidator; - deviceApiCall.resultValidator = resultValidator; - deviceApiCall.method = method; - deviceApiCall.throwOnResultKeysMissing = false; - deviceApiCall.unwrapResult = false; - return deviceApiCall; -} -/** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string - * so that transports know that it expects a response. + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {string} [id] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -function createRequest(method, params) { - let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; - let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); - call.id = id; - return call; -} - -const createNotification = createDeviceApiCall; -/** - * Validate any arbitrary data with any Zod validator - * - * @template {import("zod").ZodType} Validator - * @param {any} data - * @param {Validator | null} [validator] - * @returns {import("zod").infer} - */ +exports.WebkitMessagingTransport = WebkitMessagingTransport; -exports.createNotification = createNotification; +class WebkitMessagingConfig { + /** + * @param {object} params + * @param {boolean} params.hasModernWebkitAPI + * @param {string[]} params.webkitMessageHandlerNames + * @param {string} params.secret + */ + constructor(params) { + /** + * Whether or not the current WebKit Platform supports secure messaging + * by default (eg: macOS 11+) + */ + this.hasModernWebkitAPI = params.hasModernWebkitAPI; + /** + * A list of WebKit message handler names that a user script can send + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; + /** + * A string provided by native platforms to be sent with future outgoing + * messages + */ - if (validator) { - return validator.parse(data); + this.secret = params.secret; } - return data; } - -},{}],16:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - /** - * Platforms should only need to implement this `send` method + * This is the additional payload that gets appended to outgoing messages. + * It's used in the Swift side to encrypt the response that comes back */ -class DeviceApiTransport { - /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} - */ - async send(_deviceApiCall, _options) { - return undefined; - } -} -/** - * This is the base Sender class that platforms can will implement. - * - * Note: The 'handle' method must be implemented, unless you also implement 'send' - * - * @typedef CallOptions - * @property {AbortSignal} [signal] - */ +exports.WebkitMessagingConfig = WebkitMessagingConfig; -exports.DeviceApiTransport = DeviceApiTransport; +class SecureMessagingParams { + /** + * @param {object} params + * @param {string} params.methodName + * @param {string} params.secret + * @param {number[]} params.key + * @param {number[]} params.iv + */ + constructor(params) { + /** + * The method that's been appended to `window` to be called later + */ + this.methodName = params.methodName; + /** + * The secret used to ensure message sender validity + */ -class DeviceApi { - /** @type {DeviceApiTransport} */ + this.secret = params.secret; + /** + * The CipherKey as number[] + */ - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); + this.key = params.key; + /** + * The Initial Vector as number[] + */ - this.transport = transport; + this.iv = params.iv; } - /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} - */ +} +/** + * Capture some globals used for messaging handling to prevent page + * scripts from tampering with this + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); - } - /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} - */ +exports.SecureMessagingParams = SecureMessagingParams; - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); - } +function captureGlobals() { + // Creat base with null prototype + return { + window, + // Methods must be bound to their interface, otherwise they throw Illegal invocation + encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), + decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), + generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), + exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), + importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), + getRandomValues: window.crypto.getRandomValues.bind(window.crypto), + TextEncoder, + TextDecoder, + Uint8Array, + Uint16Array, + Uint32Array, + JSONstringify: window.JSON.stringify, + JSONparse: window.JSON.parse, + Arrayfrom: window.Array.from, + Promise: window.Promise, + ObjectDefineProperty: window.Object.defineProperty, + addEventListener: window.addEventListener.bind(window), + /** @type {Record} */ + capturedWebkitHandlers: {} + }; } -exports.DeviceApi = DeviceApi; - -},{}],17:[function(require,module,exports){ +},{"./messaging.js":13}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5035,7 +4935,7 @@ function _safeHostname(inputHostname) { } } -},{"./lib/apple.password.js":18,"./lib/constants.js":19,"./lib/rules-parser.js":20}],18:[function(require,module,exports){ +},{"./lib/apple.password.js":16,"./lib/constants.js":17,"./lib/rules-parser.js":18}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5659,7 +5559,7 @@ exports.Password = Password; _defineProperty(Password, "defaults", defaults); -},{"./constants.js":19,"./rules-parser.js":20}],19:[function(require,module,exports){ +},{"./constants.js":17,"./rules-parser.js":18}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5680,7 +5580,7 @@ const constants = { }; exports.constants = constants; -},{}],20:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6413,7 +6313,7 @@ function parsePasswordRules(input, formatRulesForMinifiedVersion) { return newPasswordRules; } -},{}],21:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ module.exports={ "163.com": { "password-rules": "minlength: 6; maxlength: 16;" @@ -7244,7 +7144,7 @@ module.exports={ "password-rules": "minlength: 8; maxlength: 32; max-consecutive: 6; required: lower; required: upper; required: digit;" } } -},{}],22:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7317,7 +7217,7 @@ function createDevice() { return new _ExtensionInterface.ExtensionInterface(globalConfig, deviceApi, settings); } -},{"../packages/device-api/index.js":14,"./DeviceInterface/AndroidInterface.js":23,"./DeviceInterface/AppleDeviceInterface.js":24,"./DeviceInterface/AppleOverlayDeviceInterface.js":25,"./DeviceInterface/ExtensionInterface.js":26,"./DeviceInterface/WindowsInterface.js":28,"./DeviceInterface/WindowsOverlayDeviceInterface.js":29,"./Settings.js":50,"./config.js":63,"./deviceApiCalls/transports/transports.js":71}],23:[function(require,module,exports){ +},{"../packages/device-api/index.js":10,"./DeviceInterface/AndroidInterface.js":21,"./DeviceInterface/AppleDeviceInterface.js":22,"./DeviceInterface/AppleOverlayDeviceInterface.js":23,"./DeviceInterface/ExtensionInterface.js":24,"./DeviceInterface/WindowsInterface.js":26,"./DeviceInterface/WindowsOverlayDeviceInterface.js":27,"./Settings.js":48,"./config.js":61,"./deviceApiCalls/transports/transports.js":69}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7467,7 +7367,7 @@ class AndroidInterface extends _InterfacePrototype.default { exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ +},{"../UI/controllers/NativeUIController.js":54,"../autofill-utils.js":59,"./InterfacePrototype.js":25,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7919,7 +7819,7 @@ class AppleDeviceInterface extends _InterfacePrototype.default { exports.AppleDeviceInterface = AppleDeviceInterface; -},{"../../packages/device-api/index.js":14,"../Form/matching.js":43,"../InContextSignup.js":44,"../UI/HTMLTooltip.js":54,"../UI/controllers/HTMLTooltipUIController.js":55,"../UI/controllers/NativeUIController.js":56,"../UI/controllers/OverlayUIController.js":57,"../autofill-utils.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/additionalDeviceApiCalls.js":67,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],25:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../Form/matching.js":41,"../InContextSignup.js":42,"../UI/HTMLTooltip.js":52,"../UI/controllers/HTMLTooltipUIController.js":53,"../UI/controllers/NativeUIController.js":54,"../UI/controllers/OverlayUIController.js":55,"../autofill-utils.js":59,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/additionalDeviceApiCalls.js":65,"./InterfacePrototype.js":25,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8074,7 +7974,7 @@ class AppleOverlayDeviceInterface extends _AppleDeviceInterface.AppleDeviceInter exports.AppleOverlayDeviceInterface = AppleOverlayDeviceInterface; -},{"../../packages/device-api/index.js":14,"../UI/controllers/HTMLTooltipUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/__generated__/validators.zod.js":66,"./AppleDeviceInterface.js":24,"./overlayApi.js":31}],26:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../UI/controllers/HTMLTooltipUIController.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/__generated__/validators.zod.js":64,"./AppleDeviceInterface.js":22,"./overlayApi.js":29}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8352,7 +8252,7 @@ class ExtensionInterface extends _InterfacePrototype.default { exports.ExtensionInterface = ExtensionInterface; -},{"../Form/matching.js":43,"../InContextSignup.js":44,"../UI/HTMLTooltip.js":54,"../UI/controllers/HTMLTooltipUIController.js":55,"../autofill-utils.js":61,"./InterfacePrototype.js":27}],27:[function(require,module,exports){ +},{"../Form/matching.js":41,"../InContextSignup.js":42,"../UI/HTMLTooltip.js":52,"../UI/controllers/HTMLTooltipUIController.js":53,"../autofill-utils.js":59,"./InterfacePrototype.js":25}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9421,7 +9321,7 @@ class InterfacePrototype { var _default = InterfacePrototype; exports.default = _default; -},{"../../packages/device-api/index.js":14,"../EmailProtection.js":32,"../Form/formatters.js":36,"../Form/matching.js":43,"../InputTypes/Credentials.js":45,"../PasswordGenerator.js":48,"../Scanner.js":49,"../Settings.js":50,"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"../config.js":63,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/__generated__/validators.zod.js":66,"../deviceApiCalls/transports/transports.js":71,"./initFormSubmissionsApi.js":30}],28:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../EmailProtection.js":30,"../Form/formatters.js":34,"../Form/matching.js":41,"../InputTypes/Credentials.js":43,"../PasswordGenerator.js":46,"../Scanner.js":47,"../Settings.js":48,"../UI/controllers/NativeUIController.js":54,"../autofill-utils.js":59,"../config.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/__generated__/validators.zod.js":64,"../deviceApiCalls/transports/transports.js":69,"./initFormSubmissionsApi.js":28}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9637,7 +9537,7 @@ class WindowsInterface extends _InterfacePrototype.default { exports.WindowsInterface = WindowsInterface; -},{"../UI/controllers/OverlayUIController.js":57,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27}],29:[function(require,module,exports){ +},{"../UI/controllers/OverlayUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"./InterfacePrototype.js":25}],27:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9846,7 +9746,7 @@ class WindowsOverlayDeviceInterface extends _InterfacePrototype.default { exports.WindowsOverlayDeviceInterface = WindowsOverlayDeviceInterface; -},{"../UI/controllers/HTMLTooltipUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27,"./overlayApi.js":31}],30:[function(require,module,exports){ +},{"../UI/controllers/HTMLTooltipUIController.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"./InterfacePrototype.js":25,"./overlayApi.js":29}],28:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9952,7 +9852,7 @@ function initFormSubmissionsApi(forms, matching) { }); } -},{"../Form/label-util.js":39,"../autofill-utils.js":61}],31:[function(require,module,exports){ +},{"../Form/label-util.js":37,"../autofill-utils.js":59}],29:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -10019,7 +9919,7 @@ function overlayApi(device) { }; } -},{"../deviceApiCalls/__generated__/deviceApiCalls.js":65}],32:[function(require,module,exports){ +},{"../deviceApiCalls/__generated__/deviceApiCalls.js":63}],30:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -10080,7 +9980,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],33:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11000,7 +10900,7 @@ class Form { exports.Form = Form; -},{"../autofill-utils.js":61,"../constants.js":64,"./FormAnalyzer.js":34,"./formatters.js":36,"./inputStyles.js":37,"./inputTypeConfig.js":38,"./matching.js":43}],34:[function(require,module,exports){ +},{"../autofill-utils.js":59,"../constants.js":62,"./FormAnalyzer.js":32,"./formatters.js":34,"./inputStyles.js":35,"./inputTypeConfig.js":36,"./matching.js":41}],32:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11394,7 +11294,7 @@ class FormAnalyzer { var _default = FormAnalyzer; exports.default = _default; -},{"../autofill-utils.js":61,"../constants.js":64,"./matching-config/__generated__/compiled-matching-config.js":41,"./matching.js":43}],35:[function(require,module,exports){ +},{"../autofill-utils.js":59,"../constants.js":62,"./matching-config/__generated__/compiled-matching-config.js":39,"./matching.js":41}],33:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11962,7 +11862,7 @@ const COUNTRY_NAMES_TO_CODES = { }; exports.COUNTRY_NAMES_TO_CODES = COUNTRY_NAMES_TO_CODES; -},{}],36:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12319,7 +12219,7 @@ const prepareFormValuesForStorage = formValues => { exports.prepareFormValuesForStorage = prepareFormValuesForStorage; -},{"./countryNames.js":35,"./matching.js":43}],37:[function(require,module,exports){ +},{"./countryNames.js":33,"./matching.js":41}],35:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12421,7 +12321,7 @@ const getIconStylesAutofilled = (input, form) => { exports.getIconStylesAutofilled = getIconStylesAutofilled; -},{"./inputTypeConfig.js":38}],38:[function(require,module,exports){ +},{"./inputTypeConfig.js":36}],36:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12701,7 +12601,7 @@ const isFieldDecorated = input => { exports.isFieldDecorated = isFieldDecorated; -},{"../InputTypes/Credentials.js":45,"../InputTypes/CreditCard.js":46,"../InputTypes/Identity.js":47,"../UI/img/ddgPasswordIcon.js":59,"../constants.js":64,"./logo-svg.js":40,"./matching.js":43}],39:[function(require,module,exports){ +},{"../InputTypes/Credentials.js":43,"../InputTypes/CreditCard.js":44,"../InputTypes/Identity.js":45,"../UI/img/ddgPasswordIcon.js":57,"../constants.js":62,"./logo-svg.js":38,"./matching.js":41}],37:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12762,7 +12662,7 @@ const extractElementStrings = element => { exports.extractElementStrings = extractElementStrings; -},{"./matching.js":43}],40:[function(require,module,exports){ +},{"./matching.js":41}],38:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12776,7 +12676,7 @@ const daxGrayscaleSvg = "\n * {\n border-radius: 8px;\n border: 0;\n cursor: pointer;\n display: inline-block;\n font-family: inherit;\n font-style: normal;\n font-weight: bold;\n padding: 8px 12px;\n text-decoration: none;\n}\n\n.notice-controls .ghost {\n margin-left: 1rem;\n}\n\n.tooltip--email-signup a.primary {\n background: #3969EF;\n color: #fff;\n}\n\n.tooltip--email-signup a.primary:hover,\n.tooltip--email-signup a.primary:focus {\n background: #2b55ca;\n}\n\n.tooltip--email-signup a.primary:active {\n background: #1e42a4;\n}\n\n.tooltip--email-signup button.ghost {\n background: transparent;\n color: #3969EF;\n}\n\n.tooltip--email-signup button.ghost:hover,\n.tooltip--email-signup button.ghost:focus {\n background-color: rgba(0, 0, 0, 0.06);\n color: #2b55ca;\n}\n\n.tooltip--email-signup button.ghost:active {\n background-color: rgba(0, 0, 0, 0.12);\n color: #1e42a4;\n}\n\n.tooltip--email-signup button.close-tooltip {\n background-color: transparent;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMiAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjI5Mjg5NCAwLjY1NjkwN0MwLjY4MzQxOCAwLjI2NjM4MyAxLjMxNjU4IDAuMjY2MzgzIDEuNzA3MTEgMC42NTY5MDdMNiA0Ljk0OThMMTAuMjkyOSAwLjY1NjkwN0MxMC42ODM0IDAuMjY2MzgzIDExLjMxNjYgMC4yNjYzODMgMTEuNzA3MSAwLjY1NjkwN0MxMi4wOTc2IDEuMDQ3NDMgMTIuMDk3NiAxLjY4MDYgMTEuNzA3MSAyLjA3MTEyTDcuNDE0MjEgNi4zNjQwMUwxMS43MDcxIDEwLjY1NjlDMTIuMDk3NiAxMS4wNDc0IDEyLjA5NzYgMTEuNjgwNiAxMS43MDcxIDEyLjA3MTFDMTEuMzE2NiAxMi40NjE2IDEwLjY4MzQgMTIuNDYxNiAxMC4yOTI5IDEyLjA3MTFMNiA3Ljc3ODIzTDEuNzA3MTEgMTIuMDcxMUMxLjMxNjU4IDEyLjQ2MTYgMC42ODM0MTcgMTIuNDYxNiAwLjI5Mjg5MyAxMi4wNzExQy0wLjA5NzYzMTEgMTEuNjgwNiAtMC4wOTc2MzExIDExLjA0NzQgMC4yOTI4OTMgMTAuNjU2OUw0LjU4NTc5IDYuMzY0MDFMMC4yOTI4OTQgMi4wNzExMkMtMC4wOTc2MzA2IDEuNjgwNiAtMC4wOTc2MzA2IDEuMDQ3NDMgMC4yOTI4OTQgMC42NTY5MDdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjg0Ii8+Cjwvc3ZnPgo=);\n background-position: center center;\n background-repeat: no-repeat;\n border: 0;\n cursor: pointer;\n padding: 16px;\n position: absolute;\n right: 12px;\n top: 12px;\n}\n"; exports.CSS_STYLES = CSS_STYLES; -},{}],61:[function(require,module,exports){ +},{}],59:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18148,7 +18048,7 @@ function isFormLikelyToBeUsedAsPageWrapper(form) { return formChildrenPercentage > 50; } -},{"./Form/matching.js":43}],62:[function(require,module,exports){ +},{"./Form/matching.js":41}],60:[function(require,module,exports){ "use strict"; require("./requestIdleCallback.js"); @@ -18183,7 +18083,7 @@ var _autofillUtils = require("./autofill-utils.js"); } })(); -},{"./DeviceInterface.js":22,"./autofill-utils.js":61,"./requestIdleCallback.js":73}],63:[function(require,module,exports){ +},{"./DeviceInterface.js":20,"./autofill-utils.js":59,"./requestIdleCallback.js":71}],61:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18271,7 +18171,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],64:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18289,7 +18189,7 @@ const constants = { }; exports.constants = constants; -},{}],65:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18779,7 +18679,7 @@ class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; -},{"../../../packages/device-api":14,"./validators.zod.js":66}],66:[function(require,module,exports){ +},{"../../../packages/device-api":10,"./validators.zod.js":64}],64:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19285,7 +19185,7 @@ const apiSchema = _zod.z.object({ exports.apiSchema = apiSchema; -},{"zod":12}],67:[function(require,module,exports){ +},{"zod":8}],65:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19326,7 +19226,7 @@ class GetAlias extends _index.DeviceApiCall { exports.GetAlias = GetAlias; -},{"../../packages/device-api/index.js":14,"./__generated__/validators.zod.js":66}],68:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"./__generated__/validators.zod.js":64}],66:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19484,7 +19384,7 @@ function androidSpecificAvailableInputTypes(globalConfig) { }; } -},{"../../../packages/device-api/index.js":14,"../__generated__/deviceApiCalls.js":65}],69:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../__generated__/deviceApiCalls.js":63}],67:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19492,7 +19392,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.AppleTransport = void 0; -var _contentScopeUtils = require("@duckduckgo/content-scope-utils"); +var _messaging = require("../../../packages/messaging/messaging.js"); var _index = require("../../../packages/device-api/index.js"); @@ -19503,12 +19403,12 @@ class AppleTransport extends _index.DeviceApiTransport { constructor(globalConfig) { super(); this.config = globalConfig; - const webkitConfig = new _contentScopeUtils.WebkitMessagingConfig({ + const webkitConfig = new _messaging.WebkitMessagingConfig({ hasModernWebkitAPI: this.config.hasModernWebkitAPI, webkitMessageHandlerNames: this.config.webkitMessageHandlerNames, secret: this.config.secret }); - this.messaging = new _contentScopeUtils.Messaging(webkitConfig); + this.messaging = new _messaging.Messaging(webkitConfig); } async send(deviceApiCall) { @@ -19520,7 +19420,7 @@ class AppleTransport extends _index.DeviceApiTransport { return this.messaging.notify(deviceApiCall.method, deviceApiCall.params || undefined); } } catch (e) { - if (e instanceof _contentScopeUtils.MissingHandler) { + if (e instanceof _messaging.MissingHandler) { if (this.config.isDDGTestMode) { console.log('MissingWebkitHandler error for:', deviceApiCall.method); } @@ -19560,7 +19460,7 @@ function appleSpecificRuntimeConfiguration(globalConfig) { }; } -},{"../../../packages/device-api/index.js":14,"../__generated__/deviceApiCalls.js":65,"@duckduckgo/content-scope-utils":2}],70:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../../../packages/messaging/messaging.js":13,"../__generated__/deviceApiCalls.js":63}],68:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19732,7 +19632,7 @@ async function extensionSpecificSetIncontextSignupPermanentlyDismissedAtCall(par }); } -},{"../../../packages/device-api/index.js":14,"../../Settings.js":50,"../../autofill-utils.js":61,"../__generated__/deviceApiCalls.js":65}],71:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../../Settings.js":48,"../../autofill-utils.js":59,"../__generated__/deviceApiCalls.js":63}],69:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19786,7 +19686,7 @@ function createTransport(globalConfig) { return new _extensionTransport.ExtensionTransport(globalConfig); } -},{"./android.transport.js":68,"./apple.transport.js":69,"./extension.transport.js":70,"./windows.transport.js":72}],72:[function(require,module,exports){ +},{"./android.transport.js":66,"./apple.transport.js":67,"./extension.transport.js":68,"./windows.transport.js":70}],70:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19886,7 +19786,7 @@ function waitForWindowsResponse(responseId, options) { }); } -},{"../../../packages/device-api/index.js":14}],73:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10}],71:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19934,4 +19834,4 @@ window.cancelIdleCallback = window.cancelIdleCallback || function (id) { var _default = {}; exports.default = _default; -},{}]},{},[62]); +},{}]},{},[60]); diff --git a/dist/autofill.js b/dist/autofill.js index 36465880d..24c9967c9 100644 --- a/dist/autofill.js +++ b/dist/autofill.js @@ -58,1159 +58,1059 @@ function processConfig(data, userList, preferences) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _messaging = require("./messaging.js"); - -Object.keys(_messaging).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - if (key in exports && exports[key] === _messaging[key]) return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _messaging[key]; - } - }); +Object.defineProperty(exports, "DeviceApi", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApi; + } }); - -},{"./messaging.js":3}],3:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true +Object.defineProperty(exports, "DeviceApiCall", { + enumerable: true, + get: function () { + return _deviceApiCall.DeviceApiCall; + } }); -exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; -Object.defineProperty(exports, "WebkitMessagingConfig", { +Object.defineProperty(exports, "DeviceApiTransport", { enumerable: true, get: function () { - return _webkit.WebkitMessagingConfig; + return _deviceApi.DeviceApiTransport; + } +}); +Object.defineProperty(exports, "createNotification", { + enumerable: true, + get: function () { + return _deviceApiCall.createNotification; + } +}); +Object.defineProperty(exports, "createRequest", { + enumerable: true, + get: function () { + return _deviceApiCall.createRequest; } }); -Object.defineProperty(exports, "WindowsMessagingConfig", { +Object.defineProperty(exports, "validate", { enumerable: true, get: function () { - return _windows.WindowsMessagingConfig; + return _deviceApiCall.validate; } }); -var _windows = require("./messaging/windows.js"); +var _deviceApiCall = require("./lib/device-api-call.js"); -var _webkit = require("./messaging/webkit.js"); +var _deviceApi = require("./lib/device-api.js"); -/** - * @module Messaging - * - * @description - * - * An abstraction for communications between JavaScript and host platforms. - * - * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) - * 2) Then use that to get an instance of the Messaging utility which allows - * you to send and receive data in a unified way - * 3) Each platform implements {@link MessagingTransport} along with its own Configuration - * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} - * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} - * - * @example Webkit Messaging - * - * ```js - * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // This config would be injected into the UserScript - * const injectedConfig = { - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }; - * - * // Then use that config to construct platform-specific configuration - * const config = new WebkitMessagingConfig(injectedConfig); - * - * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 - * const messaging = new Messaging(config); - * messaging.notify("hello world!", {foo: "bar"}) - * - * ``` - * - * @example Windows Messaging - * - * ```js - * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // Messaging on Windows is namespaced, so you can create multiple messaging instances - * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); - * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); - * - * const autofillMessaging = new Messaging(autofillConfig); - * const debugMessaging = new Messaging(debugConfig); - * - * // Now send messages to both features as needed 🚀 - * autofillMessaging.notify("storeFormData", { "username": "dax" }) - * debugMessaging.notify("pageLoad", { time: window.performance.now() }) - * ``` - */ +},{"./lib/device-api-call.js":3,"./lib/device-api.js":4}],3:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; +exports.createDeviceApiCall = createDeviceApiCall; +exports.createNotification = void 0; +exports.createRequest = createRequest; +exports.validate = validate; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** - * @implements {MessagingTransport} + * This roughly follows https://www.jsonrpc.org/specification + * @template {import("zod").ZodType} Params=import("zod").ZodType + * @template {import("zod").ZodType} Result=import("zod").ZodType */ -class Messaging { - /** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - */ - constructor(config) { - this.transport = getTransport(config); - } - /** - * Send a 'fire-and-forget' message. - * @throws - * {@link MissingHandler} - * - * @example - * - * ``` - * const messaging = new Messaging(config) - * messaging.notify("foo", {bar: "baz"}) - * ``` - * @param {string} name - * @param {Record} [data] - */ - +class DeviceApiCall { + /** @type {string} */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.transport.notify(name, data); - } /** - * Send a request, and wait for a response - * @throws - * {@link MissingHandler} - * - * @example - * ``` - * const messaging = new Messaging(config) - * const response = await messaging.request("foo", {bar: "baz"}) - * ``` - * - * @param {string} name - * @param {Record} [data] - * @return {Promise} + * An optional 'id' - used to indicate if a request requires a response. + * @type {string|null} */ + /** @type {Params | null | undefined} */ - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.transport.request(name, data); - } - -} -/** - * @interface - */ + /** @type {Result | null | undefined} */ + /** @type {import("zod").infer} */ -exports.Messaging = Messaging; + /** + * This is a carve-out for legacy messages that are not typed yet. + * If you set this to 'true', then the response will not be checked to conform + * to any shape + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ -class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} + * New messages should be in a particular format, eg: { success: T }, + * but you can set this to false if you want to access the result as-is, + * without any unwrapping logic + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error("must implement 'notify'"); - } + /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} + * @param {import("zod").infer} data */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + constructor(data) { + _defineProperty(this, "method", 'unknown'); + _defineProperty(this, "id", null); - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); - } + _defineProperty(this, "paramsValidator", null); -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + _defineProperty(this, "resultValidator", null); + _defineProperty(this, "params", void 0); -exports.MessagingTransport = MessagingTransport; + _defineProperty(this, "throwOnResultKeysMissing", true); -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); - } + _defineProperty(this, "unwrapResult", true); - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + this.params = data; } + /** + * @returns {import("zod").infer|undefined} + */ - throw new Error('unreachable'); -} -/** - * Thrown when a handler cannot be found - */ + validateParams() { + if (this.params === undefined) { + return undefined; + } -class MissingHandler extends Error { + this._validate(this.params, this.paramsValidator); + + return this.params; + } /** - * @param {string} message - * @param {string} handlerName + * @param {any|null} incoming + * @returns {import("zod").infer} */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; - } - -} -/** - * Some re-exports for convenience - */ -exports.MissingHandler = MissingHandler; + validateResult(incoming) { + this._validate(incoming, this.resultValidator); -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + if (!incoming) { + return incoming; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + if (!this.unwrapResult) { + return incoming; + } -var _messaging = require("../messaging.js"); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + if ('success' in incoming) { + return incoming.success; + } -/** - * @example - * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` - * - * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following - * would occur: - * - * ```js - * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); - * const response = JSON.parse(json) - * ``` - * - * @example - * On macOS 10 however, the process is a little more involved. A method will be appended to `window` - * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow - * as being something along the lines of: - * - * ```js - * // add the window method - * window["_0123456"] = (response) => { - * // decrypt `response` and deliver the result to the caller here - * // then remove the temporary method - * delete window["_0123456"] - * }; - * - * // send the data + `messageHanding` values - * window.webkit.messageHandlers.foo.postMessage({ - * bar: "baz", - * messagingHandling: { - * methodName: "_0123456", - * secret: "super-secret", - * key: [1, 2, 45, 2], - * iv: [34, 4, 43], - * } - * }); - * - * // later in swift, the following JavaScript snippet will be executed - * (() => { - * window["_0123456"]({ - * ciphertext: [12, 13, 4], - * tag: [3, 5, 67, 56] - * }) - * })() - * ``` - * @implements {MessagingTransport} - */ -class WebkitMessagingTransport { - /** @type {WebkitMessagingConfig} */ - - /** - * @param {WebkitMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); - - _defineProperty(this, "globals", void 0); - - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); - - this.config = config; - this.globals = captureGlobals(); + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + } + } - if (!this.config.hasModernWebkitAPI) { - this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); } + + return incoming; } /** - * Sends message to the webkit layer (fire and forget) - * @param {String} handler - * @param {*} data - * @internal + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private */ - wkSend(handler) { - var _this$globals$window$, _this$globals$window$2; - - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _validate(data, validator) { + if (!validator) return data; - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret + if (!result) { + throw new Error('unreachable, data failure', data); } - }; - if (!this.config.hasModernWebkitAPI) { - if (!(handler in this.globals.capturedWebkitHandlers)) { - throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); - } else { - return this.globals.capturedWebkitHandlers[handler](outgoing); + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } } } - - return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * Sends message to the webkit layer and waits for the specified response - * @param {String} handler - * @param {*} data - * @returns {Promise<*>} - * @internal + * @param {import('zod').ZodIssue[]} errors */ - async wkSendAndWait(handler) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (this.config.hasModernWebkitAPI) { - const response = await this.wkSend(handler, data); - return this.globals.JSONparse(response || '{}'); - } - - try { - const randMethodName = this.createRandMethodName(); - const key = await this.createRandKey(); - const iv = this.createRandIv(); - const { - ciphertext, - tag - } = await new this.globals.Promise(( - /** @type {any} */ - resolve) => { - this.generateRandomMethod(randMethodName, resolve); - data.messageHandling = new SecureMessagingParams({ - methodName: randMethodName, - secret: this.config.secret, - key: this.globals.Arrayfrom(key), - iv: this.globals.Arrayfrom(iv) - }); - this.wkSend(handler, data); - }); - const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); - const decrypted = await this.decrypt(cipher, key, iv); - return this.globals.JSONparse(decrypted || '{}'); - } catch (e) { - // re-throw when the error is just a 'MissingHandler' - if (e instanceof _messaging.MissingHandler) { - throw e; - } else { - console.error('decryption failed', e); - console.error(e); - return { - error: e - }; - } - } + throwError(errors) { + const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); + throw error; } /** - * @param {string} name - * @param {Record} [data] + * Use this helper for creating stand-in response messages that are typed correctly. + * + * @examples + * + * ```js + * const msg = new Message(); + * const response = msg.response({}) // <-- This argument will be typed correctly + * ``` + * + * @param {import("zod").infer} response + * @returns {import("zod").infer} */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); + result(response) { + return response; } /** - * @param {string} name - * @param {Record} [data] + * @returns {import("zod").infer} */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.wkSendAndWait(name, data); + preResultValidation(response) { + return response; } - /** - * Generate a random method name and adds it to the global scope - * The native layer will use this method to send the response - * @param {string | number} randomMethodName - * @param {Function} callback - */ +} - generateRandomMethod(randomMethodName, callback) { - var _this = this; +exports.DeviceApiCall = DeviceApiCall; - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. - delete _this.globals.window[randomMethodName]; - } - }); - } +exports.DeviceApiCallError = DeviceApiCallError; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } +class SchemaValidationError extends Error { + constructor() { + super(...arguments); - createRandMethodName() { - return '_' + this.randomString(); + _defineProperty(this, "validationErrors", []); } + /** - * @type {{name: string, length: number}} + * @param {import("zod").ZodIssue[]} errors + * @param {string} name + * @returns {SchemaValidationError} */ + static fromZodErrors(errors, name) { + const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; + function log(issue) { + switch (issue.code) { + case 'invalid_literal': + case 'invalid_type': + { + console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); + break; + } - /** - * @returns {Promise} - */ - async createRandKey() { - const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); - const exportedKey = await this.globals.exportKey('raw', key); - return new this.globals.Uint8Array(exportedKey); - } - /** - * @returns {Uint8Array} - */ + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } + break; + } - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ + default: + { + console.log(name, 'other issue:', issue); + } + } + } + for (let error of errors) { + log(error); + } - async decrypt(ciphertext, key, iv) { - const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); - const algo = { - name: 'AES-GCM', - iv - }; - let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); - let dec = new this.globals.TextDecoder(); - return dec.decode(decrypted); + const message = [heading, 'please see the details above'].join('\n '); + const error = new SchemaValidationError(message); + error.validationErrors = errors; + return error; } - /** - * When required (such as on macos 10.x), capture the `postMessage` method on - * each webkit messageHandler - * - * @param {string[]} handlerNames - */ +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; - - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; +exports.SchemaValidationError = SchemaValidationError; - /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ - const original = handlers[webkitMessageHandlerName]; - const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); - this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; - delete handlers[webkitMessageHandlerName].postMessage; - } - } - } +function createDeviceApiCall(method, params) { + let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + /** @type {DeviceApiCall} */ + const deviceApiCall = new DeviceApiCall(params); + deviceApiCall.paramsValidator = paramsValidator; + deviceApiCall.resultValidator = resultValidator; + deviceApiCall.method = method; + deviceApiCall.throwOnResultKeysMissing = false; + deviceApiCall.unwrapResult = false; + return deviceApiCall; } /** - * Use this configuration to create an instance of {@link Messaging} for WebKit - * - * ```js - * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. * - * const config = new WebkitMessagingConfig({ - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }); + * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string + * so that transports know that it expects a response. * - * const messaging = new Messaging(config) - * const resp = await messaging.request("debugConfig") - * ``` + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {string} [id] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} */ -exports.WebkitMessagingTransport = WebkitMessagingTransport; +function createRequest(method, params) { + let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; + let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); + call.id = id; + return call; +} -class WebkitMessagingConfig { - /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ - constructor(params) { - /** - * Whether or not the current WebKit Platform supports secure messaging - * by default (eg: macOS 11+) - */ - this.hasModernWebkitAPI = params.hasModernWebkitAPI; - /** - * A list of WebKit message handler names that a user script can send - */ +const createNotification = createDeviceApiCall; +/** + * Validate any arbitrary data with any Zod validator + * + * @template {import("zod").ZodType} Validator + * @param {any} data + * @param {Validator | null} [validator] + * @returns {import("zod").infer} + */ - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ +exports.createNotification = createNotification; - this.secret = params.secret; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (validator) { + return validator.parse(data); } + return data; } -/** - * This is the additional payload that gets appended to outgoing messages. - * It's used in the Swift side to encrypt the response that comes back - */ +},{}],4:[function(require,module,exports){ +"use strict"; -exports.WebkitMessagingConfig = WebkitMessagingConfig; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; -class SecureMessagingParams { +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Platforms should only need to implement this `send` method + */ +class DeviceApiTransport { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} */ - constructor(params) { - /** - * The method that's been appended to `window` to be called later - */ - this.methodName = params.methodName; - /** - * The secret used to ensure message sender validity - */ - - this.secret = params.secret; - /** - * The CipherKey as number[] - */ - - this.key = params.key; - /** - * The Initial Vector as number[] - */ - - this.iv = params.iv; + async send(_deviceApiCall, _options) { + return undefined; } } /** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this + * This is the base Sender class that platforms can will implement. + * + * Note: The 'handle' method must be implemented, unless you also implement 'send' + * + * @typedef CallOptions + * @property {AbortSignal} [signal] */ -exports.SecureMessagingParams = SecureMessagingParams; +exports.DeviceApiTransport = DeviceApiTransport; -function captureGlobals() { - // Creat base with null prototype - return { - window, - // Methods must be bound to their interface, otherwise they throw Illegal invocation - encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), - decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), - generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), - exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), - importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), - getRandomValues: window.crypto.getRandomValues.bind(window.crypto), - TextEncoder, - TextDecoder, - Uint8Array, - Uint16Array, - Uint32Array, - JSONstringify: window.JSON.stringify, - JSONparse: window.JSON.parse, - Arrayfrom: window.Array.from, - Promise: window.Promise, - ObjectDefineProperty: window.Object.defineProperty, - addEventListener: window.addEventListener.bind(window), +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ + + + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); + } + /** + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} + */ + + + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); + } - /** @type {Record} */ - capturedWebkitHandlers: {} - }; } -},{"../messaging.js":3}],5:[function(require,module,exports){ +exports.DeviceApi = DeviceApi; + +},{}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { + enumerable: true, + get: function () { + return _webkit.WebkitMessagingConfig; + } +}); -var _messaging = require("../messaging.js"); +var _webkit = require("./webkit.js"); -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/** + * @module Messaging + * + * @description + * + * An abstraction for communications between JavaScript and host platforms. + * + * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) + * 2) Then use that to get an instance of the Messaging utility which allows + * you to send and receive data in a unified way + * 3) Each platform implements {@link MessagingTransport} along with its own Configuration + * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} + * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} + * + * @example Webkit Messaging + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + * + * @example Windows Messaging + * + * ```js + * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // Messaging on Windows is namespaced, so you can create multiple messaging instances + * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); + * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); + * + * const autofillMessaging = new Messaging(autofillConfig); + * const debugMessaging = new Messaging(debugConfig); + * + * // Now send messages to both features as needed 🚀 + * autofillMessaging.notify("storeFormData", { "username": "dax" }) + * debugMessaging.notify("pageLoad", { time: window.performance.now() }) + * ``` + */ /** * @implements {MessagingTransport} */ -class WindowsMessagingTransport { +class Messaging { /** - * @param {WindowsMessagingConfig} config - */ + * @param {WebkitMessagingConfig} config + */ constructor(config) { - _defineProperty(this, "config", void 0); - - this.config = config; + this.transport = getTransport(config); } /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + * Send a 'fire-and-forget' message. + * @throws {Error} + * {@link MissingHandler} + * + * @example + * + * ``` + * const messaging = new Messaging(config) + * messaging.notify("foo", {bar: "baz"}) + * ``` + * @param {string} name + * @param {Record} [data] + */ notify(name) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); + this.transport.notify(name, data); } /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + * Send a request, and wait for a response + * @throws {Error} + * {@link MissingHandler} + * + * @example + * ``` + * const messaging = new Messaging(config) + * const response = await messaging.request("foo", {bar: "baz"}) + * ``` + * + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ request(name) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - throw new Error('todo: implement request for windows'); + return this.transport.request(name, data); } } +/** + * @interface + */ -exports.WindowsMessagingTransport = WindowsMessagingTransport; -class WindowsMessagingConfig { +exports.Messaging = Messaging; + +class MessagingTransport { /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; + * @param {string} name + * @param {Record} [data] + * @returns {void} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error("must implement 'notify'"); + } + /** + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + + + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); } } +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ -exports.WindowsMessagingConfig = WindowsMessagingConfig; -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; +exports.MessagingTransport = MessagingTransport; -Object.defineProperty(exports, "__esModule", { - value: true -}); -Object.defineProperty(exports, "DeviceApi", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApi; - } -}); -Object.defineProperty(exports, "DeviceApiCall", { - enumerable: true, - get: function () { - return _deviceApiCall.DeviceApiCall; - } -}); -Object.defineProperty(exports, "DeviceApiTransport", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApiTransport; - } -}); -Object.defineProperty(exports, "createNotification", { - enumerable: true, - get: function () { - return _deviceApiCall.createNotification; - } -}); -Object.defineProperty(exports, "createRequest", { - enumerable: true, - get: function () { - return _deviceApiCall.createRequest; +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); } -}); -Object.defineProperty(exports, "validate", { - enumerable: true, - get: function () { - return _deviceApiCall.validate; + + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ + + +class MissingHandler extends Error { + /** + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; } -}); -var _deviceApiCall = require("./lib/device-api-call.js"); +} +/** + * Some re-exports for convenience + */ -var _deviceApi = require("./lib/device-api.js"); -},{"./lib/device-api-call.js":7,"./lib/device-api.js":8}],7:[function(require,module,exports){ +exports.MissingHandler = MissingHandler; + +},{"./webkit.js":6}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; -exports.createDeviceApiCall = createDeviceApiCall; -exports.createNotification = void 0; -exports.createRequest = createRequest; -exports.validate = validate; +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + +var _messaging = require("./messaging.js"); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @typedef {import("./messaging").MessagingTransport} MessagingTransport */ -class DeviceApiCall { - /** @type {string} */ - - /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} - */ - - /** @type {Params | null | undefined} */ - - /** @type {Result | null | undefined} */ - - /** @type {import("zod").infer} */ - - /** - * This is a carve-out for legacy messages that are not typed yet. - * If you set this to 'true', then the response will not be checked to conform - * to any shape - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ - /** - * New messages should be in a particular format, eg: { success: T }, - * but you can set this to false if you want to access the result as-is, - * without any unwrapping logic - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +/** + * @example + * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` + * + * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following + * would occur: + * + * ```js + * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); + * const response = JSON.parse(json) + * ``` + * + * @example + * On macOS 10 however, the process is a little more involved. A method will be appended to `window` + * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow + * as being something along the lines of: + * + * ```js + * // add the window method + * window["_0123456"] = (response) => { + * // decrypt `response` and deliver the result to the caller here + * // then remove the temporary method + * delete window["_0123456"] + * }; + * + * // send the data + `messageHanding` values + * window.webkit.messageHandlers.foo.postMessage({ + * bar: "baz", + * messagingHandling: { + * methodName: "_0123456", + * secret: "super-secret", + * key: [1, 2, 45, 2], + * iv: [34, 4, 43], + * } + * }); + * + * // later in swift, the following JavaScript snippet will be executed + * (() => { + * window["_0123456"]({ + * ciphertext: [12, 13, 4], + * tag: [3, 5, 67, 56] + * }) + * })() + * ``` + * @implements {MessagingTransport} + */ +class WebkitMessagingTransport { + /** @type {WebkitMessagingConfig} */ /** - * @param {import("zod").infer} data + * @param {WebkitMessagingConfig} config */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - - _defineProperty(this, "resultValidator", null); - - _defineProperty(this, "params", void 0); - - _defineProperty(this, "throwOnResultKeysMissing", true); + constructor(config) { + _defineProperty(this, "config", void 0); - _defineProperty(this, "unwrapResult", true); + _defineProperty(this, "globals", void 0); - this.params = data; - } - /** - * @returns {import("zod").infer|undefined} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - validateParams() { - if (this.params === undefined) { - return undefined; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - this._validate(this.params, this.paramsValidator); - - return this.params; } /** - * @param {any|null} incoming - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - validateResult(incoming) { - this._validate(incoming, this.resultValidator); - - if (!incoming) { - return incoming; - } - - if (!this.unwrapResult) { - return incoming; - } + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if ('success' in incoming) { - return incoming.success; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); } - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } - } + }; - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + if (!(handler in this.globals.capturedWebkitHandlers)) { + throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); + } else { + return this.globals.capturedWebkitHandlers[handler](outgoing); + } } - return incoming; + return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - _validate(data, validator) { - if (!validator) return data; - - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + try { + const randMethodName = this.createRandMethodName(); + const key = await this.createRandKey(); + const iv = this.createRandIv(); + const { + ciphertext, + tag + } = await new this.globals.Promise(( + /** @type {any} */ + resolve) => { + this.generateRandomMethod(randMethodName, resolve); + data.messageHandling = new SecureMessagingParams({ + methodName: randMethodName, + secret: this.config.secret, + key: this.globals.Arrayfrom(key), + iv: this.globals.Arrayfrom(iv) + }); + this.wkSend(handler, data); + }); + const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); + const decrypted = await this.decrypt(cipher, key, iv); + return this.globals.JSONparse(decrypted || '{}'); + } catch (e) { + // re-throw when the error is just a 'MissingHandler' + if (e instanceof _messaging.MissingHandler) { + throw e; + } else { + console.error('decryption failed', e); + console.error(e); + return { + error: e + }; } } } /** - * @param {import('zod').ZodIssue[]} errors + * @param {string} name + * @param {Record} [data] */ - throwError(errors) { - const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); - throw error; + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } /** - * Use this helper for creating stand-in response messages that are typed correctly. - * - * @examples - * - * ```js - * const msg = new Message(); - * const response = msg.response({}) // <-- This argument will be typed correctly - * ``` - * - * @param {import("zod").infer} response - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - result(response) { - return response; + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.wkSendAndWait(name, data); } /** - * @returns {import("zod").infer} + * Generate a random method name and adds it to the global scope + * The native layer will use this method to send the response + * @param {string | number} randomMethodName + * @param {Function} callback */ - preResultValidation(response) { - return response; - } + generateRandomMethod(randomMethodName, callback) { + var _this = this; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -exports.DeviceApiCall = DeviceApiCall; + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + delete _this.globals.window[randomMethodName]; + } + }); + } + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.DeviceApiCallError = DeviceApiCallError; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -class SchemaValidationError extends Error { - constructor() { - super(...arguments); - _defineProperty(this, "validationErrors", []); + /** + * @returns {Promise} + */ + async createRandKey() { + const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); + const exportedKey = await this.globals.exportKey('raw', key); + return new this.globals.Uint8Array(exportedKey); } + /** + * @returns {Uint8Array} + */ + + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } /** - * @param {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ + + + async decrypt(ciphertext, key, iv) { + const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); + const algo = { + name: 'AES-GCM', + iv + }; + let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); + let dec = new this.globals.TextDecoder(); + return dec.decode(decrypted); + } + /** + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - static fromZodErrors(errors, name) { - const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; - function log(issue) { - switch (issue.code) { - case 'invalid_literal': - case 'invalid_type': - { - console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); - break; - } - case 'invalid_union': - { - for (let unionError of issue.unionErrors) { - for (let issue1 of unionError.issues) { - log(issue1); - } - } + captureWebkitHandlers(handlerNames) { + const handlers = window.webkit.messageHandlers; + if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - break; - } + for (let webkitMessageHandlerName of handlerNames) { + var _handlers$webkitMessa; - default: - { - console.log(name, 'other issue:', issue); - } - } - } + if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { + var _handlers$webkitMessa2; - for (let error of errors) { - log(error); + /** + * `bind` is used here to ensure future calls to the captured + * `postMessage` have the correct `this` context + */ + const original = handlers[webkitMessageHandlerName]; + const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); + this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; + delete handlers[webkitMessageHandlerName].postMessage; + } } - - const message = [heading, 'please see the details above'].join('\n '); - const error = new SchemaValidationError(message); - error.validationErrors = errors; - return error; } } /** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} - */ - - -exports.SchemaValidationError = SchemaValidationError; - -function createDeviceApiCall(method, params) { - let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - /** @type {DeviceApiCall} */ - const deviceApiCall = new DeviceApiCall(params); - deviceApiCall.paramsValidator = paramsValidator; - deviceApiCall.resultValidator = resultValidator; - deviceApiCall.method = method; - deviceApiCall.throwOnResultKeysMissing = false; - deviceApiCall.unwrapResult = false; - return deviceApiCall; -} -/** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string - * so that transports know that it expects a response. + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {string} [id] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -function createRequest(method, params) { - let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; - let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); - call.id = id; - return call; -} - -const createNotification = createDeviceApiCall; -/** - * Validate any arbitrary data with any Zod validator - * - * @template {import("zod").ZodType} Validator - * @param {any} data - * @param {Validator | null} [validator] - * @returns {import("zod").infer} - */ +exports.WebkitMessagingTransport = WebkitMessagingTransport; -exports.createNotification = createNotification; +class WebkitMessagingConfig { + /** + * @param {object} params + * @param {boolean} params.hasModernWebkitAPI + * @param {string[]} params.webkitMessageHandlerNames + * @param {string} params.secret + */ + constructor(params) { + /** + * Whether or not the current WebKit Platform supports secure messaging + * by default (eg: macOS 11+) + */ + this.hasModernWebkitAPI = params.hasModernWebkitAPI; + /** + * A list of WebKit message handler names that a user script can send + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; + /** + * A string provided by native platforms to be sent with future outgoing + * messages + */ - if (validator) { - return validator.parse(data); + this.secret = params.secret; } - return data; } - -},{}],8:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - /** - * Platforms should only need to implement this `send` method + * This is the additional payload that gets appended to outgoing messages. + * It's used in the Swift side to encrypt the response that comes back */ -class DeviceApiTransport { - /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} - */ - async send(_deviceApiCall, _options) { - return undefined; - } -} -/** - * This is the base Sender class that platforms can will implement. - * - * Note: The 'handle' method must be implemented, unless you also implement 'send' - * - * @typedef CallOptions - * @property {AbortSignal} [signal] - */ +exports.WebkitMessagingConfig = WebkitMessagingConfig; -exports.DeviceApiTransport = DeviceApiTransport; +class SecureMessagingParams { + /** + * @param {object} params + * @param {string} params.methodName + * @param {string} params.secret + * @param {number[]} params.key + * @param {number[]} params.iv + */ + constructor(params) { + /** + * The method that's been appended to `window` to be called later + */ + this.methodName = params.methodName; + /** + * The secret used to ensure message sender validity + */ -class DeviceApi { - /** @type {DeviceApiTransport} */ + this.secret = params.secret; + /** + * The CipherKey as number[] + */ - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); + this.key = params.key; + /** + * The Initial Vector as number[] + */ - this.transport = transport; + this.iv = params.iv; } - /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} - */ +} +/** + * Capture some globals used for messaging handling to prevent page + * scripts from tampering with this + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); - } - /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} - */ +exports.SecureMessagingParams = SecureMessagingParams; - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); - } +function captureGlobals() { + // Creat base with null prototype + return { + window, + // Methods must be bound to their interface, otherwise they throw Illegal invocation + encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), + decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), + generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), + exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), + importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), + getRandomValues: window.crypto.getRandomValues.bind(window.crypto), + TextEncoder, + TextDecoder, + Uint8Array, + Uint16Array, + Uint32Array, + JSONstringify: window.JSON.stringify, + JSONparse: window.JSON.parse, + Arrayfrom: window.Array.from, + Promise: window.Promise, + ObjectDefineProperty: window.Object.defineProperty, + addEventListener: window.addEventListener.bind(window), + /** @type {Record} */ + capturedWebkitHandlers: {} + }; } -exports.DeviceApi = DeviceApi; - -},{}],9:[function(require,module,exports){ +},{"./messaging.js":5}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1359,7 +1259,7 @@ function _safeHostname(inputHostname) { } } -},{"./lib/apple.password.js":10,"./lib/constants.js":11,"./lib/rules-parser.js":12}],10:[function(require,module,exports){ +},{"./lib/apple.password.js":8,"./lib/constants.js":9,"./lib/rules-parser.js":10}],8:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1983,7 +1883,7 @@ exports.Password = Password; _defineProperty(Password, "defaults", defaults); -},{"./constants.js":11,"./rules-parser.js":12}],11:[function(require,module,exports){ +},{"./constants.js":9,"./rules-parser.js":10}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2004,7 +1904,7 @@ const constants = { }; exports.constants = constants; -},{}],12:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2737,7 +2637,7 @@ function parsePasswordRules(input, formatRulesForMinifiedVersion) { return newPasswordRules; } -},{}],13:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ module.exports={ "163.com": { "password-rules": "minlength: 6; maxlength: 16;" @@ -3568,7 +3468,7 @@ module.exports={ "password-rules": "minlength: 8; maxlength: 32; max-consecutive: 6; required: lower; required: upper; required: digit;" } } -},{}],14:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -3641,7 +3541,7 @@ function createDevice() { return new _ExtensionInterface.ExtensionInterface(globalConfig, deviceApi, settings); } -},{"../packages/device-api/index.js":6,"./DeviceInterface/AndroidInterface.js":15,"./DeviceInterface/AppleDeviceInterface.js":16,"./DeviceInterface/AppleOverlayDeviceInterface.js":17,"./DeviceInterface/ExtensionInterface.js":18,"./DeviceInterface/WindowsInterface.js":20,"./DeviceInterface/WindowsOverlayDeviceInterface.js":21,"./Settings.js":42,"./config.js":55,"./deviceApiCalls/transports/transports.js":63}],15:[function(require,module,exports){ +},{"../packages/device-api/index.js":2,"./DeviceInterface/AndroidInterface.js":13,"./DeviceInterface/AppleDeviceInterface.js":14,"./DeviceInterface/AppleOverlayDeviceInterface.js":15,"./DeviceInterface/ExtensionInterface.js":16,"./DeviceInterface/WindowsInterface.js":18,"./DeviceInterface/WindowsOverlayDeviceInterface.js":19,"./Settings.js":40,"./config.js":53,"./deviceApiCalls/transports/transports.js":61}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -3791,7 +3691,7 @@ class AndroidInterface extends _InterfacePrototype.default { exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":48,"../autofill-utils.js":53,"./InterfacePrototype.js":19,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],16:[function(require,module,exports){ +},{"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4243,7 +4143,7 @@ class AppleDeviceInterface extends _InterfacePrototype.default { exports.AppleDeviceInterface = AppleDeviceInterface; -},{"../../packages/device-api/index.js":6,"../Form/matching.js":35,"../InContextSignup.js":36,"../UI/HTMLTooltip.js":46,"../UI/controllers/HTMLTooltipUIController.js":47,"../UI/controllers/NativeUIController.js":48,"../UI/controllers/OverlayUIController.js":49,"../autofill-utils.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/additionalDeviceApiCalls.js":59,"./InterfacePrototype.js":19,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],17:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../Form/matching.js":33,"../InContextSignup.js":34,"../UI/HTMLTooltip.js":44,"../UI/controllers/HTMLTooltipUIController.js":45,"../UI/controllers/NativeUIController.js":46,"../UI/controllers/OverlayUIController.js":47,"../autofill-utils.js":51,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/additionalDeviceApiCalls.js":57,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4398,7 +4298,7 @@ class AppleOverlayDeviceInterface extends _AppleDeviceInterface.AppleDeviceInter exports.AppleOverlayDeviceInterface = AppleOverlayDeviceInterface; -},{"../../packages/device-api/index.js":6,"../UI/controllers/HTMLTooltipUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/__generated__/validators.zod.js":58,"./AppleDeviceInterface.js":16,"./overlayApi.js":23}],18:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../UI/controllers/HTMLTooltipUIController.js":45,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/__generated__/validators.zod.js":56,"./AppleDeviceInterface.js":14,"./overlayApi.js":21}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4676,7 +4576,7 @@ class ExtensionInterface extends _InterfacePrototype.default { exports.ExtensionInterface = ExtensionInterface; -},{"../Form/matching.js":35,"../InContextSignup.js":36,"../UI/HTMLTooltip.js":46,"../UI/controllers/HTMLTooltipUIController.js":47,"../autofill-utils.js":53,"./InterfacePrototype.js":19}],19:[function(require,module,exports){ +},{"../Form/matching.js":33,"../InContextSignup.js":34,"../UI/HTMLTooltip.js":44,"../UI/controllers/HTMLTooltipUIController.js":45,"../autofill-utils.js":51,"./InterfacePrototype.js":17}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5745,7 +5645,7 @@ class InterfacePrototype { var _default = InterfacePrototype; exports.default = _default; -},{"../../packages/device-api/index.js":6,"../EmailProtection.js":24,"../Form/formatters.js":28,"../Form/matching.js":35,"../InputTypes/Credentials.js":37,"../PasswordGenerator.js":40,"../Scanner.js":41,"../Settings.js":42,"../UI/controllers/NativeUIController.js":48,"../autofill-utils.js":53,"../config.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/__generated__/validators.zod.js":58,"../deviceApiCalls/transports/transports.js":63,"./initFormSubmissionsApi.js":22}],20:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../EmailProtection.js":22,"../Form/formatters.js":26,"../Form/matching.js":33,"../InputTypes/Credentials.js":35,"../PasswordGenerator.js":38,"../Scanner.js":39,"../Settings.js":40,"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"../config.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/__generated__/validators.zod.js":56,"../deviceApiCalls/transports/transports.js":61,"./initFormSubmissionsApi.js":20}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5961,7 +5861,7 @@ class WindowsInterface extends _InterfacePrototype.default { exports.WindowsInterface = WindowsInterface; -},{"../UI/controllers/OverlayUIController.js":49,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"./InterfacePrototype.js":19}],21:[function(require,module,exports){ +},{"../UI/controllers/OverlayUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17}],19:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6170,7 +6070,7 @@ class WindowsOverlayDeviceInterface extends _InterfacePrototype.default { exports.WindowsOverlayDeviceInterface = WindowsOverlayDeviceInterface; -},{"../UI/controllers/HTMLTooltipUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"./InterfacePrototype.js":19,"./overlayApi.js":23}],22:[function(require,module,exports){ +},{"../UI/controllers/HTMLTooltipUIController.js":45,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17,"./overlayApi.js":21}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6276,7 +6176,7 @@ function initFormSubmissionsApi(forms, matching) { }); } -},{"../Form/label-util.js":31,"../autofill-utils.js":53}],23:[function(require,module,exports){ +},{"../Form/label-util.js":29,"../autofill-utils.js":51}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6343,7 +6243,7 @@ function overlayApi(device) { }; } -},{"../deviceApiCalls/__generated__/deviceApiCalls.js":57}],24:[function(require,module,exports){ +},{"../deviceApiCalls/__generated__/deviceApiCalls.js":55}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6404,7 +6304,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],25:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7324,7 +7224,7 @@ class Form { exports.Form = Form; -},{"../autofill-utils.js":53,"../constants.js":56,"./FormAnalyzer.js":26,"./formatters.js":28,"./inputStyles.js":29,"./inputTypeConfig.js":30,"./matching.js":35}],26:[function(require,module,exports){ +},{"../autofill-utils.js":51,"../constants.js":54,"./FormAnalyzer.js":24,"./formatters.js":26,"./inputStyles.js":27,"./inputTypeConfig.js":28,"./matching.js":33}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7718,7 +7618,7 @@ class FormAnalyzer { var _default = FormAnalyzer; exports.default = _default; -},{"../autofill-utils.js":53,"../constants.js":56,"./matching-config/__generated__/compiled-matching-config.js":33,"./matching.js":35}],27:[function(require,module,exports){ +},{"../autofill-utils.js":51,"../constants.js":54,"./matching-config/__generated__/compiled-matching-config.js":31,"./matching.js":33}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8286,7 +8186,7 @@ const COUNTRY_NAMES_TO_CODES = { }; exports.COUNTRY_NAMES_TO_CODES = COUNTRY_NAMES_TO_CODES; -},{}],28:[function(require,module,exports){ +},{}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8643,7 +8543,7 @@ const prepareFormValuesForStorage = formValues => { exports.prepareFormValuesForStorage = prepareFormValuesForStorage; -},{"./countryNames.js":27,"./matching.js":35}],29:[function(require,module,exports){ +},{"./countryNames.js":25,"./matching.js":33}],27:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8745,7 +8645,7 @@ const getIconStylesAutofilled = (input, form) => { exports.getIconStylesAutofilled = getIconStylesAutofilled; -},{"./inputTypeConfig.js":30}],30:[function(require,module,exports){ +},{"./inputTypeConfig.js":28}],28:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9025,7 +8925,7 @@ const isFieldDecorated = input => { exports.isFieldDecorated = isFieldDecorated; -},{"../InputTypes/Credentials.js":37,"../InputTypes/CreditCard.js":38,"../InputTypes/Identity.js":39,"../UI/img/ddgPasswordIcon.js":51,"../constants.js":56,"./logo-svg.js":32,"./matching.js":35}],31:[function(require,module,exports){ +},{"../InputTypes/Credentials.js":35,"../InputTypes/CreditCard.js":36,"../InputTypes/Identity.js":37,"../UI/img/ddgPasswordIcon.js":49,"../constants.js":54,"./logo-svg.js":30,"./matching.js":33}],29:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9086,7 +8986,7 @@ const extractElementStrings = element => { exports.extractElementStrings = extractElementStrings; -},{"./matching.js":35}],32:[function(require,module,exports){ +},{"./matching.js":33}],30:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9100,7 +9000,7 @@ const daxGrayscaleSvg = "\n * {\n border-radius: 8px;\n border: 0;\n cursor: pointer;\n display: inline-block;\n font-family: inherit;\n font-style: normal;\n font-weight: bold;\n padding: 8px 12px;\n text-decoration: none;\n}\n\n.notice-controls .ghost {\n margin-left: 1rem;\n}\n\n.tooltip--email-signup a.primary {\n background: #3969EF;\n color: #fff;\n}\n\n.tooltip--email-signup a.primary:hover,\n.tooltip--email-signup a.primary:focus {\n background: #2b55ca;\n}\n\n.tooltip--email-signup a.primary:active {\n background: #1e42a4;\n}\n\n.tooltip--email-signup button.ghost {\n background: transparent;\n color: #3969EF;\n}\n\n.tooltip--email-signup button.ghost:hover,\n.tooltip--email-signup button.ghost:focus {\n background-color: rgba(0, 0, 0, 0.06);\n color: #2b55ca;\n}\n\n.tooltip--email-signup button.ghost:active {\n background-color: rgba(0, 0, 0, 0.12);\n color: #1e42a4;\n}\n\n.tooltip--email-signup button.close-tooltip {\n background-color: transparent;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMiAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjI5Mjg5NCAwLjY1NjkwN0MwLjY4MzQxOCAwLjI2NjM4MyAxLjMxNjU4IDAuMjY2MzgzIDEuNzA3MTEgMC42NTY5MDdMNiA0Ljk0OThMMTAuMjkyOSAwLjY1NjkwN0MxMC42ODM0IDAuMjY2MzgzIDExLjMxNjYgMC4yNjYzODMgMTEuNzA3MSAwLjY1NjkwN0MxMi4wOTc2IDEuMDQ3NDMgMTIuMDk3NiAxLjY4MDYgMTEuNzA3MSAyLjA3MTEyTDcuNDE0MjEgNi4zNjQwMUwxMS43MDcxIDEwLjY1NjlDMTIuMDk3NiAxMS4wNDc0IDEyLjA5NzYgMTEuNjgwNiAxMS43MDcxIDEyLjA3MTFDMTEuMzE2NiAxMi40NjE2IDEwLjY4MzQgMTIuNDYxNiAxMC4yOTI5IDEyLjA3MTFMNiA3Ljc3ODIzTDEuNzA3MTEgMTIuMDcxMUMxLjMxNjU4IDEyLjQ2MTYgMC42ODM0MTcgMTIuNDYxNiAwLjI5Mjg5MyAxMi4wNzExQy0wLjA5NzYzMTEgMTEuNjgwNiAtMC4wOTc2MzExIDExLjA0NzQgMC4yOTI4OTMgMTAuNjU2OUw0LjU4NTc5IDYuMzY0MDFMMC4yOTI4OTQgMi4wNzExMkMtMC4wOTc2MzA2IDEuNjgwNiAtMC4wOTc2MzA2IDEuMDQ3NDMgMC4yOTI4OTQgMC42NTY5MDdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjg0Ii8+Cjwvc3ZnPgo=);\n background-position: center center;\n background-repeat: no-repeat;\n border: 0;\n cursor: pointer;\n padding: 16px;\n position: absolute;\n right: 12px;\n top: 12px;\n}\n"; exports.CSS_STYLES = CSS_STYLES; -},{}],53:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14472,7 +14372,7 @@ function isFormLikelyToBeUsedAsPageWrapper(form) { return formChildrenPercentage > 50; } -},{"./Form/matching.js":35}],54:[function(require,module,exports){ +},{"./Form/matching.js":33}],52:[function(require,module,exports){ "use strict"; require("./requestIdleCallback.js"); @@ -14507,7 +14407,7 @@ var _autofillUtils = require("./autofill-utils.js"); } })(); -},{"./DeviceInterface.js":14,"./autofill-utils.js":53,"./requestIdleCallback.js":65}],55:[function(require,module,exports){ +},{"./DeviceInterface.js":12,"./autofill-utils.js":51,"./requestIdleCallback.js":63}],53:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14595,7 +14495,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],56:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14613,7 +14513,7 @@ const constants = { }; exports.constants = constants; -},{}],57:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15103,7 +15003,7 @@ class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; -},{"../../../packages/device-api":6,"./validators.zod.js":58}],58:[function(require,module,exports){ +},{"../../../packages/device-api":2,"./validators.zod.js":56}],56:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15187,7 +15087,7 @@ exports.askToUnlockProviderResultSchema = askToUnlockProviderResultSchema; const apiSchema = null; exports.apiSchema = apiSchema; -},{}],59:[function(require,module,exports){ +},{}],57:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15228,7 +15128,7 @@ class GetAlias extends _index.DeviceApiCall { exports.GetAlias = GetAlias; -},{"../../packages/device-api/index.js":6,"./__generated__/validators.zod.js":58}],60:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"./__generated__/validators.zod.js":56}],58:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15386,7 +15286,7 @@ function androidSpecificAvailableInputTypes(globalConfig) { }; } -},{"../../../packages/device-api/index.js":6,"../__generated__/deviceApiCalls.js":57}],61:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../__generated__/deviceApiCalls.js":55}],59:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15394,7 +15294,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.AppleTransport = void 0; -var _contentScopeUtils = require("@duckduckgo/content-scope-utils"); +var _messaging = require("../../../packages/messaging/messaging.js"); var _index = require("../../../packages/device-api/index.js"); @@ -15405,12 +15305,12 @@ class AppleTransport extends _index.DeviceApiTransport { constructor(globalConfig) { super(); this.config = globalConfig; - const webkitConfig = new _contentScopeUtils.WebkitMessagingConfig({ + const webkitConfig = new _messaging.WebkitMessagingConfig({ hasModernWebkitAPI: this.config.hasModernWebkitAPI, webkitMessageHandlerNames: this.config.webkitMessageHandlerNames, secret: this.config.secret }); - this.messaging = new _contentScopeUtils.Messaging(webkitConfig); + this.messaging = new _messaging.Messaging(webkitConfig); } async send(deviceApiCall) { @@ -15422,7 +15322,7 @@ class AppleTransport extends _index.DeviceApiTransport { return this.messaging.notify(deviceApiCall.method, deviceApiCall.params || undefined); } } catch (e) { - if (e instanceof _contentScopeUtils.MissingHandler) { + if (e instanceof _messaging.MissingHandler) { if (this.config.isDDGTestMode) { console.log('MissingWebkitHandler error for:', deviceApiCall.method); } @@ -15462,7 +15362,7 @@ function appleSpecificRuntimeConfiguration(globalConfig) { }; } -},{"../../../packages/device-api/index.js":6,"../__generated__/deviceApiCalls.js":57,"@duckduckgo/content-scope-utils":2}],62:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../../../packages/messaging/messaging.js":5,"../__generated__/deviceApiCalls.js":55}],60:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15634,7 +15534,7 @@ async function extensionSpecificSetIncontextSignupPermanentlyDismissedAtCall(par }); } -},{"../../../packages/device-api/index.js":6,"../../Settings.js":42,"../../autofill-utils.js":53,"../__generated__/deviceApiCalls.js":57}],63:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../../Settings.js":40,"../../autofill-utils.js":51,"../__generated__/deviceApiCalls.js":55}],61:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15688,7 +15588,7 @@ function createTransport(globalConfig) { return new _extensionTransport.ExtensionTransport(globalConfig); } -},{"./android.transport.js":60,"./apple.transport.js":61,"./extension.transport.js":62,"./windows.transport.js":64}],64:[function(require,module,exports){ +},{"./android.transport.js":58,"./apple.transport.js":59,"./extension.transport.js":60,"./windows.transport.js":62}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15788,7 +15688,7 @@ function waitForWindowsResponse(responseId, options) { }); } -},{"../../../packages/device-api/index.js":6}],65:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15836,4 +15736,4 @@ window.cancelIdleCallback = window.cancelIdleCallback || function (id) { var _default = {}; exports.default = _default; -},{}]},{},[54]); +},{}]},{},[52]); diff --git a/integration-test/helpers/mocks.android.js b/integration-test/helpers/mocks.android.js index 6921d5217..4248c9084 100644 --- a/integration-test/helpers/mocks.android.js +++ b/integration-test/helpers/mocks.android.js @@ -197,7 +197,6 @@ export function createAndroidMocks () { }, storeFormData (request) { /** @type {MockCall} */ - // @ts-expect-error const call = ['storeFormData', request, mocks.getAutofillData] window.__playwright_autofill.mocks.calls.push(JSON.parse(JSON.stringify(call))) } diff --git a/integration-test/helpers/pages.js b/integration-test/helpers/pages.js index 8138593be..782d6d1c3 100644 --- a/integration-test/helpers/pages.js +++ b/integration-test/helpers/pages.js @@ -283,7 +283,6 @@ export function signupPage (page) { const calls = await mockedCalls(page, { names: ['storeFormData'] }) expect(calls.length).toBeGreaterThanOrEqual(1) const [, sent] = calls[0] - // @ts-expect-error expect(sent.Data.credentials).toEqual(credentials) } /** @@ -481,7 +480,6 @@ export function loginPage (page, opts = {}) { */ async assertParentOpened () { const credsCalls = await mockedCalls(page, { names: ['getSelectedCredentials'] }) - // @ts-expect-error const hasSucceeded = credsCalls.some((call) => call[2]?.some(({type}) => type === 'ok')) expect(hasSucceeded).toBe(true) } diff --git a/package-lock.json b/package-lock.json index 544da2f0f..d5af5cb4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,6 @@ "@babel/eslint-parser": "^7.18.2", "@babel/preset-env": "^7.16.11", "@duckduckgo/content-scope-scripts": "github:duckduckgo/content-scope-scripts#1.3.0", - "@duckduckgo/content-scope-utils": "github:duckduckgo/content-scope-utils#1.0.1", "@playwright/test": "^1.32.0", "@types/jest": "^27.4.1", "@types/node": "^16.11.36", @@ -1752,12 +1751,6 @@ "sjcl": "^1.0.8" } }, - "node_modules/@duckduckgo/content-scope-utils": { - "version": "1.0.0", - "resolved": "git+ssh://git@github.com/duckduckgo/content-scope-utils.git#97b233e9b257c0b11d4aebb74656ed15a63660ae", - "dev": true, - "license": "ISC" - }, "node_modules/@eslint/eslintrc": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", @@ -15923,11 +15916,6 @@ "sjcl": "^1.0.8" } }, - "@duckduckgo/content-scope-utils": { - "version": "git+ssh://git@github.com/duckduckgo/content-scope-utils.git#97b233e9b257c0b11d4aebb74656ed15a63660ae", - "dev": true, - "from": "@duckduckgo/content-scope-utils@github:duckduckgo/content-scope-utils#1.0.1" - }, "@eslint/eslintrc": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz", diff --git a/package.json b/package.json index 63774fe2f..c7c36ba69 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,6 @@ "@babel/eslint-parser": "^7.18.2", "@babel/preset-env": "^7.16.11", "@duckduckgo/content-scope-scripts": "github:duckduckgo/content-scope-scripts#1.3.0", - "@duckduckgo/content-scope-utils": "github:duckduckgo/content-scope-utils#1.0.1", "@playwright/test": "^1.32.0", "@types/jest": "^27.4.1", "@types/node": "^16.11.36", diff --git a/packages/messaging/messaging.js b/packages/messaging/messaging.js new file mode 100644 index 000000000..ec940670e --- /dev/null +++ b/packages/messaging/messaging.js @@ -0,0 +1,154 @@ +/** + * @module Messaging + * + * @description + * + * An abstraction for communications between JavaScript and host platforms. + * + * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) + * 2) Then use that to get an instance of the Messaging utility which allows + * you to send and receive data in a unified way + * 3) Each platform implements {@link MessagingTransport} along with its own Configuration + * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} + * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} + * + * @example Webkit Messaging + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + * + * @example Windows Messaging + * + * ```js + * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // Messaging on Windows is namespaced, so you can create multiple messaging instances + * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); + * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); + * + * const autofillMessaging = new Messaging(autofillConfig); + * const debugMessaging = new Messaging(debugConfig); + * + * // Now send messages to both features as needed 🚀 + * autofillMessaging.notify("storeFormData", { "username": "dax" }) + * debugMessaging.notify("pageLoad", { time: window.performance.now() }) + * ``` + */ +import { WebkitMessagingConfig, WebkitMessagingTransport } from './webkit.js' + +/** + * @implements {MessagingTransport} + */ +export class Messaging { + /** + * @param {WebkitMessagingConfig} config + */ + constructor (config) { + this.transport = getTransport(config) + } + /** + * Send a 'fire-and-forget' message. + * @throws {Error} + * {@link MissingHandler} + * + * @example + * + * ``` + * const messaging = new Messaging(config) + * messaging.notify("foo", {bar: "baz"}) + * ``` + * @param {string} name + * @param {Record} [data] + */ + notify (name, data = {}) { + this.transport.notify(name, data) + } + /** + * Send a request, and wait for a response + * @throws {Error} + * {@link MissingHandler} + * + * @example + * ``` + * const messaging = new Messaging(config) + * const response = await messaging.request("foo", {bar: "baz"}) + * ``` + * + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + request (name, data = {}) { + return this.transport.request(name, data) + } +} + +/** + * @interface + */ +export class MessagingTransport { + /** + * @param {string} name + * @param {Record} [data] + * @returns {void} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + notify (name, data = {}) { + throw new Error("must implement 'notify'") + } + /** + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + request (name, data = {}) { + throw new Error('must implement') + } +} + +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ +function getTransport (config) { + if (config instanceof WebkitMessagingConfig) { + return new WebkitMessagingTransport(config) + } + throw new Error('unreachable') +} + +/** + * Thrown when a handler cannot be found + */ +export class MissingHandler extends Error { + /** + * @param {string} message + * @param {string} handlerName + */ + constructor (message, handlerName) { + super(message) + this.handlerName = handlerName + } +} + +/** + * Some re-exports for convenience + */ +export { WebkitMessagingConfig } diff --git a/packages/messaging/webkit.js b/packages/messaging/webkit.js new file mode 100644 index 000000000..51e3f6e58 --- /dev/null +++ b/packages/messaging/webkit.js @@ -0,0 +1,372 @@ +/** + * @module Webkit Messaging + * + * @description + * + * A wrapper for messaging on WebKit platforms. It supports modern WebKit messageHandlers + * along with encryption for older versions (like macOS Catalina) + * + * Note: If you wish to support Catalina then you'll need to implement the native + * part of the message handling, see {@link WebkitMessagingTransport} for details. + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + */ +import { MissingHandler } from './messaging.js' + +/** + * @typedef {import("./messaging").MessagingTransport} MessagingTransport + */ + +/** + * @example + * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` + * + * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following + * would occur: + * + * ```js + * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); + * const response = JSON.parse(json) + * ``` + * + * @example + * On macOS 10 however, the process is a little more involved. A method will be appended to `window` + * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow + * as being something along the lines of: + * + * ```js + * // add the window method + * window["_0123456"] = (response) => { + * // decrypt `response` and deliver the result to the caller here + * // then remove the temporary method + * delete window["_0123456"] + * }; + * + * // send the data + `messageHanding` values + * window.webkit.messageHandlers.foo.postMessage({ + * bar: "baz", + * messagingHandling: { + * methodName: "_0123456", + * secret: "super-secret", + * key: [1, 2, 45, 2], + * iv: [34, 4, 43], + * } + * }); + * + * // later in swift, the following JavaScript snippet will be executed + * (() => { + * window["_0123456"]({ + * ciphertext: [12, 13, 4], + * tag: [3, 5, 67, 56] + * }) + * })() + * ``` + * @implements {MessagingTransport} + */ +export class WebkitMessagingTransport { + /** @type {WebkitMessagingConfig} */ + config + globals + /** + * @param {WebkitMessagingConfig} config + */ + constructor (config) { + this.config = config + this.globals = captureGlobals() + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames) + } + } + /** + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal + */ + wkSend (handler, data = {}) { + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new MissingHandler(`Missing webkit handler: '${handler}'`, handler) + } + const outgoing = { + ...data, + messageHandling: { ...data.messageHandling, secret: this.config.secret } + } + if (!this.config.hasModernWebkitAPI) { + if (!(handler in this.globals.capturedWebkitHandlers)) { + throw new MissingHandler(`cannot continue, method ${handler} not captured on macos < 11`, handler) + } else { + return this.globals.capturedWebkitHandlers[handler](outgoing) + } + } + return this.globals.window.webkit.messageHandlers[handler].postMessage?.(outgoing) + } + + /** + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal + */ + async wkSendAndWait (handler, data = {}) { + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data) + return this.globals.JSONparse(response || '{}') + } + + try { + const randMethodName = this.createRandMethodName() + const key = await this.createRandKey() + const iv = this.createRandIv() + + const { ciphertext, tag } = await new this.globals.Promise((/** @type {any} */ resolve) => { + this.generateRandomMethod(randMethodName, resolve) + data.messageHandling = new SecureMessagingParams({ + methodName: randMethodName, + secret: this.config.secret, + key: this.globals.Arrayfrom(key), + iv: this.globals.Arrayfrom(iv) + }) + this.wkSend(handler, data) + }) + + const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]) + const decrypted = await this.decrypt(cipher, key, iv) + return this.globals.JSONparse(decrypted || '{}') + } catch (e) { + // re-throw when the error is just a 'MissingHandler' + if (e instanceof MissingHandler) { + throw e + } else { + console.error('decryption failed', e) + console.error(e) + return { error: e } + } + } + } + /** + * @param {string} name + * @param {Record} [data] + */ + notify (name, data = {}) { + this.wkSend(name, data) + } + /** + * @param {string} name + * @param {Record} [data] + */ + request (name, data = {}) { + return this.wkSendAndWait(name, data) + } + /** + * Generate a random method name and adds it to the global scope + * The native layer will use this method to send the response + * @param {string | number} randomMethodName + * @param {Function} callback + */ + generateRandomMethod (randomMethodName, callback) { + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, + /** + * @param {any[]} args + */ + value: (...args) => { + callback(...args) + // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. + delete this.globals.window[randomMethodName] + } + }) + } + + randomString () { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0] + } + + createRandMethodName () { + return '_' + this.randomString() + } + + /** + * @type {{name: string, length: number}} + */ + algoObj = { name: 'AES-GCM', length: 256 } + + /** + * @returns {Promise} + */ + async createRandKey () { + const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']) + const exportedKey = await this.globals.exportKey('raw', key) + return new this.globals.Uint8Array(exportedKey) + } + + /** + * @returns {Uint8Array} + */ + createRandIv () { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)) + } + + /** + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ + async decrypt (ciphertext, key, iv) { + const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']) + const algo = { name: 'AES-GCM', iv } + + let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext) + + let dec = new this.globals.TextDecoder() + return dec.decode(decrypted) + } + + /** + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames + */ + captureWebkitHandlers (handlerNames) { + const handlers = window.webkit.messageHandlers + if (!handlers) throw new MissingHandler('window.webkit.messageHandlers was absent', 'all') + for (let webkitMessageHandlerName of handlerNames) { + if (typeof handlers[webkitMessageHandlerName]?.postMessage === 'function') { + /** + * `bind` is used here to ensure future calls to the captured + * `postMessage` have the correct `this` context + */ + const original = handlers[webkitMessageHandlerName] + const bound = handlers[webkitMessageHandlerName].postMessage?.bind(original) + this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound + delete handlers[webkitMessageHandlerName].postMessage + } + } + } +} + +/** + * Use this configuration to create an instance of {@link Messaging} for WebKit + * + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); + * + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` + */ +export class WebkitMessagingConfig { + /** + * @param {object} params + * @param {boolean} params.hasModernWebkitAPI + * @param {string[]} params.webkitMessageHandlerNames + * @param {string} params.secret + */ + constructor (params) { + /** + * Whether or not the current WebKit Platform supports secure messaging + * by default (eg: macOS 11+) + */ + this.hasModernWebkitAPI = params.hasModernWebkitAPI + /** + * A list of WebKit message handler names that a user script can send + */ + this.webkitMessageHandlerNames = params.webkitMessageHandlerNames + /** + * A string provided by native platforms to be sent with future outgoing + * messages + */ + this.secret = params.secret + } +} + +/** + * This is the additional payload that gets appended to outgoing messages. + * It's used in the Swift side to encrypt the response that comes back + */ +export class SecureMessagingParams { + /** + * @param {object} params + * @param {string} params.methodName + * @param {string} params.secret + * @param {number[]} params.key + * @param {number[]} params.iv + */ + constructor (params) { + /** + * The method that's been appended to `window` to be called later + */ + this.methodName = params.methodName + /** + * The secret used to ensure message sender validity + */ + this.secret = params.secret + /** + * The CipherKey as number[] + */ + this.key = params.key + /** + * The Initial Vector as number[] + */ + this.iv = params.iv + } +} + +/** + * Capture some globals used for messaging handling to prevent page + * scripts from tampering with this + */ +function captureGlobals () { + // Creat base with null prototype + return { + window, + // Methods must be bound to their interface, otherwise they throw Illegal invocation + encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), + decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), + generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), + exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), + importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), + getRandomValues: window.crypto.getRandomValues.bind(window.crypto), + TextEncoder, + TextDecoder, + Uint8Array, + Uint16Array, + Uint32Array, + JSONstringify: window.JSON.stringify, + JSONparse: window.JSON.parse, + Arrayfrom: window.Array.from, + Promise: window.Promise, + ObjectDefineProperty: window.Object.defineProperty, + addEventListener: window.addEventListener.bind(window), + /** @type {Record} */ + capturedWebkitHandlers: {} + } +} diff --git a/src/deviceApiCalls/transports/apple.transport.js b/src/deviceApiCalls/transports/apple.transport.js index 7c6504f9f..434a7beed 100644 --- a/src/deviceApiCalls/transports/apple.transport.js +++ b/src/deviceApiCalls/transports/apple.transport.js @@ -1,4 +1,4 @@ -import { Messaging, MissingHandler, WebkitMessagingConfig } from '@duckduckgo/content-scope-utils' +import { Messaging, MissingHandler, WebkitMessagingConfig } from '../../../packages/messaging/messaging.js' import { DeviceApiTransport } from '../../../packages/device-api/index.js' import { GetRuntimeConfigurationCall } from '../__generated__/deviceApiCalls.js' diff --git a/swift-package/Resources/assets/autofill-debug.js b/swift-package/Resources/assets/autofill-debug.js index 9ccabd40e..f97dbde2f 100644 --- a/swift-package/Resources/assets/autofill-debug.js +++ b/swift-package/Resources/assets/autofill-debug.js @@ -58,954 +58,598 @@ function processConfig(data, userList, preferences) { Object.defineProperty(exports, "__esModule", { value: true }); +exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; -var _messaging = require("./messaging.js"); +const parseUtil_1 = require("./helpers/parseUtil"); -Object.keys(_messaging).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - if (key in exports && exports[key] === _messaging[key]) return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _messaging[key]; - } - }); -}); +const util_1 = require("./helpers/util"); -},{"./messaging.js":3}],3:[function(require,module,exports){ -"use strict"; +exports.ZodIssueCode = util_1.util.arrayToEnum(["invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of"]); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; -Object.defineProperty(exports, "WebkitMessagingConfig", { - enumerable: true, - get: function () { - return _webkit.WebkitMessagingConfig; - } -}); -Object.defineProperty(exports, "WindowsMessagingConfig", { - enumerable: true, - get: function () { - return _windows.WindowsMessagingConfig; - } -}); +const quotelessJson = obj => { + const json = JSON.stringify(obj, null, 2); + return json.replace(/"([^"]+)":/g, "$1:"); +}; -var _windows = require("./messaging/windows.js"); +exports.quotelessJson = quotelessJson; -var _webkit = require("./messaging/webkit.js"); +class ZodError extends Error { + constructor(issues) { + var _this; -/** - * @module Messaging - * - * @description - * - * An abstraction for communications between JavaScript and host platforms. - * - * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) - * 2) Then use that to get an instance of the Messaging utility which allows - * you to send and receive data in a unified way - * 3) Each platform implements {@link MessagingTransport} along with its own Configuration - * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} - * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} - * - * @example Webkit Messaging - * - * ```js - * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // This config would be injected into the UserScript - * const injectedConfig = { - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }; - * - * // Then use that config to construct platform-specific configuration - * const config = new WebkitMessagingConfig(injectedConfig); - * - * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 - * const messaging = new Messaging(config); - * messaging.notify("hello world!", {foo: "bar"}) - * - * ``` - * - * @example Windows Messaging - * - * ```js - * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // Messaging on Windows is namespaced, so you can create multiple messaging instances - * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); - * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); - * - * const autofillMessaging = new Messaging(autofillConfig); - * const debugMessaging = new Messaging(debugConfig); - * - * // Now send messages to both features as needed 🚀 - * autofillMessaging.notify("storeFormData", { "username": "dax" }) - * debugMessaging.notify("pageLoad", { time: window.performance.now() }) - * ``` - */ + super(); + _this = this; + this.issues = []; -/** - * @implements {MessagingTransport} - */ -class Messaging { - /** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - */ - constructor(config) { - this.transport = getTransport(config); - } - /** - * Send a 'fire-and-forget' message. - * @throws - * {@link MissingHandler} - * - * @example - * - * ``` - * const messaging = new Messaging(config) - * messaging.notify("foo", {bar: "baz"}) - * ``` - * @param {string} name - * @param {Record} [data] - */ + this.addIssue = sub => { + this.issues = [...this.issues, sub]; + }; + this.addIssues = function () { + let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; + _this.issues = [..._this.issues, ...subs]; + }; - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.transport.notify(name, data); - } - /** - * Send a request, and wait for a response - * @throws - * {@link MissingHandler} - * - * @example - * ``` - * const messaging = new Messaging(config) - * const response = await messaging.request("foo", {bar: "baz"}) - * ``` - * - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + const actualProto = new.target.prototype; + if (Object.setPrototypeOf) { + // eslint-disable-next-line ban/ban + Object.setPrototypeOf(this, actualProto); + } else { + this.__proto__ = actualProto; + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.transport.request(name, data); + this.name = "ZodError"; + this.issues = issues; } -} -/** - * @interface - */ + get errors() { + return this.issues; + } + format(_mapper) { + const mapper = _mapper || function (issue) { + return issue.message; + }; -exports.Messaging = Messaging; + const fieldErrors = { + _errors: [] + }; -class MessagingTransport { - /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error("must implement 'notify'"); + const processError = error => { + for (const issue of error.issues) { + if (issue.code === "invalid_union") { + issue.unionErrors.map(processError); + } else if (issue.code === "invalid_return_type") { + processError(issue.returnTypeError); + } else if (issue.code === "invalid_arguments") { + processError(issue.argumentsError); + } else if (issue.path.length === 0) { + fieldErrors._errors.push(mapper(issue)); + } else { + let curr = fieldErrors; + let i = 0; + + while (i < issue.path.length) { + const el = issue.path[i]; + const terminal = i === issue.path.length - 1; + + if (!terminal) { + curr[el] = curr[el] || { + _errors: [] + }; // if (typeof el === "string") { + // curr[el] = curr[el] || { _errors: [] }; + // } else if (typeof el === "number") { + // const errorArray: any = []; + // errorArray._errors = []; + // curr[el] = curr[el] || errorArray; + // } + } else { + curr[el] = curr[el] || { + _errors: [] + }; + + curr[el]._errors.push(mapper(issue)); + } + + curr = curr[el]; + i++; + } + } + } + }; + + processError(this); + return fieldErrors; } - /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + toString() { + return this.message; + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); + get message() { + return JSON.stringify(this.issues, null, 2); } -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + get isEmpty() { + return this.issues.length === 0; + } + flatten() { + let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; + const fieldErrors = {}; + const formErrors = []; -exports.MessagingTransport = MessagingTransport; + for (const sub of this.issues) { + if (sub.path.length > 0) { + fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; + fieldErrors[sub.path[0]].push(mapper(sub)); + } else { + formErrors.push(mapper(sub)); + } + } -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); + return { + formErrors, + fieldErrors + }; } - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + get formErrors() { + return this.flatten(); } - throw new Error('unreachable'); } -/** - * Thrown when a handler cannot be found - */ +exports.ZodError = ZodError; -class MissingHandler extends Error { - /** - * @param {string} message - * @param {string} handlerName - */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; - } +ZodError.create = issues => { + const error = new ZodError(issues); + return error; +}; -} -/** - * Some re-exports for convenience - */ +const defaultErrorMap = (issue, _ctx) => { + let message; + switch (issue.code) { + case exports.ZodIssueCode.invalid_type: + if (issue.received === parseUtil_1.ZodParsedType.undefined) { + message = "Required"; + } else { + message = "Expected ".concat(issue.expected, ", received ").concat(issue.received); + } -exports.MissingHandler = MissingHandler; + break; -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + case exports.ZodIssueCode.invalid_literal: + message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); + break; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + case exports.ZodIssueCode.unrecognized_keys: + message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); + break; -var _messaging = require("../messaging.js"); + case exports.ZodIssueCode.invalid_union: + message = "Invalid input"; + break; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + case exports.ZodIssueCode.invalid_union_discriminator: + message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); + break; -/** - * @example - * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` - * - * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following - * would occur: - * - * ```js - * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); - * const response = JSON.parse(json) - * ``` - * - * @example - * On macOS 10 however, the process is a little more involved. A method will be appended to `window` - * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow - * as being something along the lines of: - * - * ```js - * // add the window method - * window["_0123456"] = (response) => { - * // decrypt `response` and deliver the result to the caller here - * // then remove the temporary method - * delete window["_0123456"] - * }; - * - * // send the data + `messageHanding` values - * window.webkit.messageHandlers.foo.postMessage({ - * bar: "baz", - * messagingHandling: { - * methodName: "_0123456", - * secret: "super-secret", - * key: [1, 2, 45, 2], - * iv: [34, 4, 43], - * } - * }); - * - * // later in swift, the following JavaScript snippet will be executed - * (() => { - * window["_0123456"]({ - * ciphertext: [12, 13, 4], - * tag: [3, 5, 67, 56] - * }) - * })() - * ``` - * @implements {MessagingTransport} - */ -class WebkitMessagingTransport { - /** @type {WebkitMessagingConfig} */ + case exports.ZodIssueCode.invalid_enum_value: + message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); + break; - /** - * @param {WebkitMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); + case exports.ZodIssueCode.invalid_arguments: + message = "Invalid function arguments"; + break; - _defineProperty(this, "globals", void 0); + case exports.ZodIssueCode.invalid_return_type: + message = "Invalid function return type"; + break; - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); + case exports.ZodIssueCode.invalid_date: + message = "Invalid date"; + break; - this.config = config; - this.globals = captureGlobals(); + case exports.ZodIssueCode.invalid_string: + if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; + break; - if (!this.config.hasModernWebkitAPI) { - this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); - } - } - /** - * Sends message to the webkit layer (fire and forget) - * @param {String} handler - * @param {*} data - * @internal - */ + case exports.ZodIssueCode.too_small: + if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at least" : "more than", " ").concat(issue.minimum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at least" : "over", " ").concat(issue.minimum, " character(s)");else if (issue.type === "number") message = "Number must be greater than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.minimum);else message = "Invalid input"; + break; + case exports.ZodIssueCode.too_big: + if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at most" : "less than", " ").concat(issue.maximum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at most" : "under", " ").concat(issue.maximum, " character(s)");else if (issue.type === "number") message = "Number must be less than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.maximum);else message = "Invalid input"; + break; - wkSend(handler) { - var _this$globals$window$, _this$globals$window$2; + case exports.ZodIssueCode.custom: + message = "Invalid input"; + break; - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + case exports.ZodIssueCode.invalid_intersection_types: + message = "Intersection results could not be merged"; + break; - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } + case exports.ZodIssueCode.not_multiple_of: + message = "Number must be a multiple of ".concat(issue.multipleOf); + break; - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret - } - }; + default: + message = _ctx.defaultError; + util_1.util.assertNever(issue); + } - if (!this.config.hasModernWebkitAPI) { - if (!(handler in this.globals.capturedWebkitHandlers)) { - throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); - } else { - return this.globals.capturedWebkitHandlers[handler](outgoing); - } - } + return { + message + }; +}; - return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); - } - /** - * Sends message to the webkit layer and waits for the specified response - * @param {String} handler - * @param {*} data - * @returns {Promise<*>} - * @internal - */ +exports.defaultErrorMap = defaultErrorMap; +exports.overrideErrorMap = exports.defaultErrorMap; +const setErrorMap = map => { + exports.overrideErrorMap = map; +}; - async wkSendAndWait(handler) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; +exports.setErrorMap = setErrorMap; - if (this.config.hasModernWebkitAPI) { - const response = await this.wkSend(handler, data); - return this.globals.JSONparse(response || '{}'); - } +},{"./helpers/parseUtil":5,"./helpers/util":7}],3:[function(require,module,exports){ +"use strict"; - try { - const randMethodName = this.createRandMethodName(); - const key = await this.createRandKey(); - const iv = this.createRandIv(); - const { - ciphertext, - tag - } = await new this.globals.Promise(( - /** @type {any} */ - resolve) => { - this.generateRandomMethod(randMethodName, resolve); - data.messageHandling = new SecureMessagingParams({ - methodName: randMethodName, - secret: this.config.secret, - key: this.globals.Arrayfrom(key), - iv: this.globals.Arrayfrom(iv) - }); - this.wkSend(handler, data); - }); - const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); - const decrypted = await this.decrypt(cipher, key, iv); - return this.globals.JSONparse(decrypted || '{}'); - } catch (e) { - // re-throw when the error is just a 'MissingHandler' - if (e instanceof _messaging.MissingHandler) { - throw e; - } else { - console.error('decryption failed', e); - console.error(e); - return { - error: e - }; +var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + var desc = Object.getOwnPropertyDescriptor(m, k); + + if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; } - } + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); - } - /** - * @param {string} name - * @param {Record} [data] - */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); +var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { + for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); +}; - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.wkSendAndWait(name, data); - } - /** - * Generate a random method name and adds it to the global scope - * The native layer will use this method to send the response - * @param {string | number} randomMethodName - * @param {Function} callback - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +__exportStar(require("./helpers/parseUtil"), exports); - generateRandomMethod(randomMethodName, callback) { - var _this = this; +__exportStar(require("./helpers/typeAliases"), exports); - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, +__exportStar(require("./types"), exports); - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. +__exportStar(require("./ZodError"), exports); - delete _this.globals.window[randomMethodName]; - } - }); - } +},{"./ZodError":2,"./helpers/parseUtil":5,"./helpers/typeAliases":6,"./types":9}],4:[function(require,module,exports){ +"use strict"; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.errorUtil = void 0; +var errorUtil; - createRandMethodName() { - return '_' + this.randomString(); - } - /** - * @type {{name: string, length: number}} - */ +(function (errorUtil) { + errorUtil.errToObj = message => typeof message === "string" ? { + message + } : message || {}; + errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; +})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); - /** - * @returns {Promise} - */ - async createRandKey() { - const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); - const exportedKey = await this.globals.exportKey('raw', key); - return new this.globals.Uint8Array(exportedKey); - } - /** - * @returns {Uint8Array} - */ +},{}],5:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.isAsync = exports.isValid = exports.isDirty = exports.isAborted = exports.OK = exports.DIRTY = exports.INVALID = exports.ParseStatus = exports.addIssueToContext = exports.EMPTY_PATH = exports.makeIssue = exports.getParsedType = exports.ZodParsedType = void 0; - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ +const ZodError_1 = require("../ZodError"); +const util_1 = require("./util"); - async decrypt(ciphertext, key, iv) { - const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); - const algo = { - name: 'AES-GCM', - iv - }; - let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); - let dec = new this.globals.TextDecoder(); - return dec.decode(decrypted); - } - /** - * When required (such as on macos 10.x), capture the `postMessage` method on - * each webkit messageHandler - * - * @param {string[]} handlerNames - */ +exports.ZodParsedType = util_1.util.arrayToEnum(["string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set"]); +const getParsedType = data => { + const t = typeof data; - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); + switch (t) { + case "undefined": + return exports.ZodParsedType.undefined; - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case "string": + return exports.ZodParsedType.string; - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + case "number": + return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; - /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ - const original = handlers[webkitMessageHandlerName]; - const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); - this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; - delete handlers[webkitMessageHandlerName].postMessage; - } - } - } + case "boolean": + return exports.ZodParsedType.boolean; -} -/** - * Use this configuration to create an instance of {@link Messaging} for WebKit - * - * ```js - * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * const config = new WebkitMessagingConfig({ - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }); - * - * const messaging = new Messaging(config) - * const resp = await messaging.request("debugConfig") - * ``` - */ + case "function": + return exports.ZodParsedType.function; + case "bigint": + return exports.ZodParsedType.bigint; -exports.WebkitMessagingTransport = WebkitMessagingTransport; + case "object": + if (Array.isArray(data)) { + return exports.ZodParsedType.array; + } -class WebkitMessagingConfig { - /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ - constructor(params) { - /** - * Whether or not the current WebKit Platform supports secure messaging - * by default (eg: macOS 11+) - */ - this.hasModernWebkitAPI = params.hasModernWebkitAPI; - /** - * A list of WebKit message handler names that a user script can send - */ + if (data === null) { + return exports.ZodParsedType.null; + } - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return exports.ZodParsedType.promise; + } - this.secret = params.secret; - } + if (typeof Map !== "undefined" && data instanceof Map) { + return exports.ZodParsedType.map; + } -} -/** - * This is the additional payload that gets appended to outgoing messages. - * It's used in the Swift side to encrypt the response that comes back - */ + if (typeof Set !== "undefined" && data instanceof Set) { + return exports.ZodParsedType.set; + } + if (typeof Date !== "undefined" && data instanceof Date) { + return exports.ZodParsedType.date; + } -exports.WebkitMessagingConfig = WebkitMessagingConfig; + return exports.ZodParsedType.object; -class SecureMessagingParams { - /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ - constructor(params) { - /** - * The method that's been appended to `window` to be called later - */ - this.methodName = params.methodName; - /** - * The secret used to ensure message sender validity - */ + default: + return exports.ZodParsedType.unknown; + } +}; - this.secret = params.secret; - /** - * The CipherKey as number[] - */ +exports.getParsedType = getParsedType; - this.key = params.key; - /** - * The Initial Vector as number[] - */ +const makeIssue = params => { + const { + data, + path, + errorMaps, + issueData + } = params; + const fullPath = [...path, ...(issueData.path || [])]; + const fullIssue = { ...issueData, + path: fullPath + }; + let errorMessage = ""; + const maps = errorMaps.filter(m => !!m).slice().reverse(); - this.iv = params.iv; + for (const map of maps) { + errorMessage = map(fullIssue, { + data, + defaultError: errorMessage + }).message; } -} -/** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this - */ + return { ...issueData, + path: fullPath, + message: issueData.message || errorMessage + }; +}; +exports.makeIssue = makeIssue; +exports.EMPTY_PATH = []; -exports.SecureMessagingParams = SecureMessagingParams; +function addIssueToContext(ctx, issueData) { + const issue = (0, exports.makeIssue)({ + issueData: issueData, + data: ctx.data, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap // then global default map + ].filter(x => !!x) + }); + ctx.common.issues.push(issue); +} -function captureGlobals() { - // Creat base with null prototype - return { - window, - // Methods must be bound to their interface, otherwise they throw Illegal invocation - encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), - decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), - generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), - exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), - importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), - getRandomValues: window.crypto.getRandomValues.bind(window.crypto), - TextEncoder, - TextDecoder, - Uint8Array, - Uint16Array, - Uint32Array, - JSONstringify: window.JSON.stringify, - JSONparse: window.JSON.parse, - Arrayfrom: window.Array.from, - Promise: window.Promise, - ObjectDefineProperty: window.Object.defineProperty, - addEventListener: window.addEventListener.bind(window), - - /** @type {Record} */ - capturedWebkitHandlers: {} - }; -} +exports.addIssueToContext = addIssueToContext; -},{"../messaging.js":3}],5:[function(require,module,exports){ -"use strict"; +class ParseStatus { + constructor() { + this.value = "valid"; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; + dirty() { + if (this.value === "valid") this.value = "dirty"; + } -var _messaging = require("../messaging.js"); + abort() { + if (this.value !== "aborted") this.value = "aborted"; + } -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + static mergeArray(status, results) { + const arrayValue = []; -/** - * @implements {MessagingTransport} - */ -class WindowsMessagingTransport { - /** - * @param {WindowsMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); + for (const s of results) { + if (s.status === "aborted") return exports.INVALID; + if (s.status === "dirty") status.dirty(); + arrayValue.push(s.value); + } - this.config = config; + return { + status: status.value, + value: arrayValue + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + static async mergeObjectAsync(status, pairs) { + const syncPairs = []; - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); - } - /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars - + for (const pair of pairs) { + syncPairs.push({ + key: await pair.key, + value: await pair.value + }); + } - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - throw new Error('todo: implement request for windows'); + return ParseStatus.mergeObjectSync(status, syncPairs); } -} + static mergeObjectSync(status, pairs) { + const finalObject = {}; + + for (const pair of pairs) { + const { + key, + value + } = pair; + if (key.status === "aborted") return exports.INVALID; + if (value.status === "aborted") return exports.INVALID; + if (key.status === "dirty") status.dirty(); + if (value.status === "dirty") status.dirty(); -exports.WindowsMessagingTransport = WindowsMessagingTransport; + if (typeof value.value !== "undefined" || pair.alwaysSet) { + finalObject[key.value] = value.value; + } + } -class WindowsMessagingConfig { - /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; + return { + status: status.value, + value: finalObject + }; } } -exports.WindowsMessagingConfig = WindowsMessagingConfig; - -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; +exports.ParseStatus = ParseStatus; +exports.INVALID = Object.freeze({ + status: "aborted" +}); -Object.defineProperty(exports, "__esModule", { - value: true +const DIRTY = value => ({ + status: "dirty", + value }); -exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; -const parseUtil_1 = require("./helpers/parseUtil"); +exports.DIRTY = DIRTY; -const util_1 = require("./helpers/util"); +const OK = value => ({ + status: "valid", + value +}); -exports.ZodIssueCode = util_1.util.arrayToEnum(["invalid_type", "invalid_literal", "custom", "invalid_union", "invalid_union_discriminator", "invalid_enum_value", "unrecognized_keys", "invalid_arguments", "invalid_return_type", "invalid_date", "invalid_string", "too_small", "too_big", "invalid_intersection_types", "not_multiple_of"]); +exports.OK = OK; -const quotelessJson = obj => { - const json = JSON.stringify(obj, null, 2); - return json.replace(/"([^"]+)":/g, "$1:"); -}; +const isAborted = x => x.status === "aborted"; -exports.quotelessJson = quotelessJson; +exports.isAborted = isAborted; -class ZodError extends Error { - constructor(issues) { - var _this; +const isDirty = x => x.status === "dirty"; - super(); - _this = this; - this.issues = []; +exports.isDirty = isDirty; - this.addIssue = sub => { - this.issues = [...this.issues, sub]; - }; +const isValid = x => x.status === "valid"; - this.addIssues = function () { - let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - _this.issues = [..._this.issues, ...subs]; - }; +exports.isValid = isValid; - const actualProto = new.target.prototype; +const isAsync = x => typeof Promise !== undefined && x instanceof Promise; - if (Object.setPrototypeOf) { - // eslint-disable-next-line ban/ban - Object.setPrototypeOf(this, actualProto); - } else { - this.__proto__ = actualProto; - } +exports.isAsync = isAsync; - this.name = "ZodError"; - this.issues = issues; - } +},{"../ZodError":2,"./util":7}],6:[function(require,module,exports){ +"use strict"; - get errors() { - return this.issues; - } +Object.defineProperty(exports, "__esModule", { + value: true +}); - format(_mapper) { - const mapper = _mapper || function (issue) { - return issue.message; - }; +},{}],7:[function(require,module,exports){ +"use strict"; - const fieldErrors = { - _errors: [] - }; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.util = void 0; +var util; - const processError = error => { - for (const issue of error.issues) { - if (issue.code === "invalid_union") { - issue.unionErrors.map(processError); - } else if (issue.code === "invalid_return_type") { - processError(issue.returnTypeError); - } else if (issue.code === "invalid_arguments") { - processError(issue.argumentsError); - } else if (issue.path.length === 0) { - fieldErrors._errors.push(mapper(issue)); - } else { - let curr = fieldErrors; - let i = 0; +(function (util) { + function assertNever(_x) { + throw new Error(); + } - while (i < issue.path.length) { - const el = issue.path[i]; - const terminal = i === issue.path.length - 1; + util.assertNever = assertNever; - if (!terminal) { - curr[el] = curr[el] || { - _errors: [] - }; // if (typeof el === "string") { - // curr[el] = curr[el] || { _errors: [] }; - // } else if (typeof el === "number") { - // const errorArray: any = []; - // errorArray._errors = []; - // curr[el] = curr[el] || errorArray; - // } - } else { - curr[el] = curr[el] || { - _errors: [] - }; + util.arrayToEnum = items => { + const obj = {}; - curr[el]._errors.push(mapper(issue)); - } + for (const item of items) { + obj[item] = item; + } - curr = curr[el]; - i++; - } - } - } - }; + return obj; + }; - processError(this); - return fieldErrors; - } + util.getValidEnumValues = obj => { + const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); + const filtered = {}; - toString() { - return this.message; - } + for (const k of validKeys) { + filtered[k] = obj[k]; + } - get message() { - return JSON.stringify(this.issues, null, 2); - } + return util.objectValues(filtered); + }; - get isEmpty() { - return this.issues.length === 0; - } + util.objectValues = obj => { + return util.objectKeys(obj).map(function (e) { + return obj[e]; + }); + }; - flatten() { - let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; - const fieldErrors = {}; - const formErrors = []; + util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban + ? obj => Object.keys(obj) // eslint-disable-line ban/ban + : object => { + const keys = []; - for (const sub of this.issues) { - if (sub.path.length > 0) { - fieldErrors[sub.path[0]] = fieldErrors[sub.path[0]] || []; - fieldErrors[sub.path[0]].push(mapper(sub)); - } else { - formErrors.push(mapper(sub)); + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); } } - return { - formErrors, - fieldErrors - }; - } - - get formErrors() { - return this.flatten(); - } - -} - -exports.ZodError = ZodError; - -ZodError.create = issues => { - const error = new ZodError(issues); - return error; -}; - -const defaultErrorMap = (issue, _ctx) => { - let message; - - switch (issue.code) { - case exports.ZodIssueCode.invalid_type: - if (issue.received === parseUtil_1.ZodParsedType.undefined) { - message = "Required"; - } else { - message = "Expected ".concat(issue.expected, ", received ").concat(issue.received); - } - - break; - - case exports.ZodIssueCode.invalid_literal: - message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); - break; - - case exports.ZodIssueCode.unrecognized_keys: - message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); - break; - - case exports.ZodIssueCode.invalid_union: - message = "Invalid input"; - break; - - case exports.ZodIssueCode.invalid_union_discriminator: - message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); - break; - - case exports.ZodIssueCode.invalid_enum_value: - message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); - break; - - case exports.ZodIssueCode.invalid_arguments: - message = "Invalid function arguments"; - break; - - case exports.ZodIssueCode.invalid_return_type: - message = "Invalid function return type"; - break; - - case exports.ZodIssueCode.invalid_date: - message = "Invalid date"; - break; - - case exports.ZodIssueCode.invalid_string: - if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; - break; - - case exports.ZodIssueCode.too_small: - if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at least" : "more than", " ").concat(issue.minimum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at least" : "over", " ").concat(issue.minimum, " character(s)");else if (issue.type === "number") message = "Number must be greater than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.minimum);else message = "Invalid input"; - break; - - case exports.ZodIssueCode.too_big: - if (issue.type === "array") message = "Array must contain ".concat(issue.inclusive ? "at most" : "less than", " ").concat(issue.maximum, " element(s)");else if (issue.type === "string") message = "String must contain ".concat(issue.inclusive ? "at most" : "under", " ").concat(issue.maximum, " character(s)");else if (issue.type === "number") message = "Number must be less than ".concat(issue.inclusive ? "or equal to " : "").concat(issue.maximum);else message = "Invalid input"; - break; - - case exports.ZodIssueCode.custom: - message = "Invalid input"; - break; - - case exports.ZodIssueCode.invalid_intersection_types: - message = "Intersection results could not be merged"; - break; - - case exports.ZodIssueCode.not_multiple_of: - message = "Number must be a multiple of ".concat(issue.multipleOf); - break; + return keys; + }; - default: - message = _ctx.defaultError; - util_1.util.assertNever(issue); - } + util.find = (arr, checker) => { + for (const item of arr) { + if (checker(item)) return item; + } - return { - message + return undefined; }; -}; -exports.defaultErrorMap = defaultErrorMap; -exports.overrideErrorMap = exports.defaultErrorMap; + util.isInteger = typeof Number.isInteger === "function" ? val => Number.isInteger(val) // eslint-disable-line ban/ban + : val => typeof val === "number" && isFinite(val) && Math.floor(val) === val; -const setErrorMap = map => { - exports.overrideErrorMap = map; -}; + function joinValues(array) { + let separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : " | "; + return array.map(val => typeof val === "string" ? "'".concat(val, "'") : val).join(separator); + } -exports.setErrorMap = setErrorMap; + util.joinValues = joinValues; +})(util = exports.util || (exports.util = {})); -},{"./helpers/parseUtil":9,"./helpers/util":11}],7:[function(require,module,exports){ +},{}],8:[function(require,module,exports){ "use strict"; var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { @@ -1027,6 +671,25 @@ var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? fun o[k2] = m[k]; }); +var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) { + Object.defineProperty(o, "default", { + enumerable: true, + value: v + }); +} : function (o, v) { + o["default"] = v; +}); + +var __importStar = void 0 && (void 0).__importStar || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + + __setModuleDefault(result, mod); + + return result; +}; + var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); }; @@ -1034,1031 +697,659 @@ var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { Object.defineProperty(exports, "__esModule", { value: true }); +exports.z = void 0; -__exportStar(require("./helpers/parseUtil"), exports); +const mod = __importStar(require("./external")); -__exportStar(require("./helpers/typeAliases"), exports); +exports.z = mod; -__exportStar(require("./types"), exports); +__exportStar(require("./external"), exports); -__exportStar(require("./ZodError"), exports); +exports.default = mod; -},{"./ZodError":6,"./helpers/parseUtil":9,"./helpers/typeAliases":10,"./types":13}],8:[function(require,module,exports){ +},{"./external":3}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.errorUtil = void 0; -var errorUtil; - -(function (errorUtil) { - errorUtil.errToObj = message => typeof message === "string" ? { - message - } : message || {}; - - errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; -})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); - -},{}],9:[function(require,module,exports){ -"use strict"; +exports.intersection = exports.instanceof = exports.function = exports.enum = exports.effect = exports.discriminatedUnion = exports.date = exports.boolean = exports.bigint = exports.array = exports.any = exports.ZodFirstPartyTypeKind = exports.late = exports.ZodSchema = exports.Schema = exports.custom = exports.ZodNaN = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransformer = exports.ZodEffects = exports.ZodPromise = exports.ZodNativeEnum = exports.ZodEnum = exports.ZodLiteral = exports.ZodLazy = exports.ZodFunction = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodUnion = exports.ZodObject = exports.objectUtil = exports.ZodArray = exports.ZodVoid = exports.ZodNever = exports.ZodUnknown = exports.ZodAny = exports.ZodNull = exports.ZodUndefined = exports.ZodDate = exports.ZodBoolean = exports.ZodBigInt = exports.ZodNumber = exports.ZodString = exports.ZodType = void 0; +exports.void = exports.unknown = exports.union = exports.undefined = exports.tuple = exports.transformer = exports.string = exports.strictObject = exports.set = exports.record = exports.promise = exports.preprocess = exports.ostring = exports.optional = exports.onumber = exports.oboolean = exports.object = exports.number = exports.nullable = exports.null = exports.never = exports.nativeEnum = exports.nan = exports.map = exports.literal = exports.lazy = void 0; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.isAsync = exports.isValid = exports.isDirty = exports.isAborted = exports.OK = exports.DIRTY = exports.INVALID = exports.ParseStatus = exports.addIssueToContext = exports.EMPTY_PATH = exports.makeIssue = exports.getParsedType = exports.ZodParsedType = void 0; +const errorUtil_1 = require("./helpers/errorUtil"); -const ZodError_1 = require("../ZodError"); +const parseUtil_1 = require("./helpers/parseUtil"); -const util_1 = require("./util"); +const util_1 = require("./helpers/util"); -exports.ZodParsedType = util_1.util.arrayToEnum(["string", "nan", "number", "integer", "float", "boolean", "date", "bigint", "symbol", "function", "undefined", "null", "array", "object", "unknown", "promise", "void", "never", "map", "set"]); +const ZodError_1 = require("./ZodError"); -const getParsedType = data => { - const t = typeof data; +class ParseInputLazyPath { + constructor(parent, value, path, key) { + this.parent = parent; + this.data = value; + this._path = path; + this._key = key; + } - switch (t) { - case "undefined": - return exports.ZodParsedType.undefined; + get path() { + return this._path.concat(this._key); + } - case "string": - return exports.ZodParsedType.string; +} - case "number": - return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; +const handleResult = (ctx, result) => { + if ((0, parseUtil_1.isValid)(result)) { + return { + success: true, + data: result.value + }; + } else { + if (!ctx.common.issues.length) { + throw new Error("Validation failed but no issues detected."); + } - case "boolean": - return exports.ZodParsedType.boolean; + const error = new ZodError_1.ZodError(ctx.common.issues); + return { + success: false, + error + }; + } +}; - case "function": - return exports.ZodParsedType.function; +function processCreateParams(params) { + if (!params) return {}; + const { + errorMap, + invalid_type_error, + required_error, + description + } = params; - case "bigint": - return exports.ZodParsedType.bigint; + if (errorMap && (invalid_type_error || required_error)) { + throw new Error("Can't use \"invalid\" or \"required\" in conjunction with custom error map."); + } - case "object": - if (Array.isArray(data)) { - return exports.ZodParsedType.array; - } + if (errorMap) return { + errorMap: errorMap, + description + }; - if (data === null) { - return exports.ZodParsedType.null; - } - - if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { - return exports.ZodParsedType.promise; - } - - if (typeof Map !== "undefined" && data instanceof Map) { - return exports.ZodParsedType.map; - } - - if (typeof Set !== "undefined" && data instanceof Set) { - return exports.ZodParsedType.set; - } - - if (typeof Date !== "undefined" && data instanceof Date) { - return exports.ZodParsedType.date; - } - - return exports.ZodParsedType.object; - - default: - return exports.ZodParsedType.unknown; - } -}; - -exports.getParsedType = getParsedType; - -const makeIssue = params => { - const { - data, - path, - errorMaps, - issueData - } = params; - const fullPath = [...path, ...(issueData.path || [])]; - const fullIssue = { ...issueData, - path: fullPath + const customMap = (iss, ctx) => { + if (iss.code !== "invalid_type") return { + message: ctx.defaultError + }; + if (typeof ctx.data === "undefined" && required_error) return { + message: required_error + }; + if (params.invalid_type_error) return { + message: params.invalid_type_error + }; + return { + message: ctx.defaultError + }; }; - let errorMessage = ""; - const maps = errorMaps.filter(m => !!m).slice().reverse(); - - for (const map of maps) { - errorMessage = map(fullIssue, { - data, - defaultError: errorMessage - }).message; - } - return { ...issueData, - path: fullPath, - message: issueData.message || errorMessage + return { + errorMap: customMap, + description }; -}; - -exports.makeIssue = makeIssue; -exports.EMPTY_PATH = []; - -function addIssueToContext(ctx, issueData) { - const issue = (0, exports.makeIssue)({ - issueData: issueData, - data: ctx.data, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap // then global default map - ].filter(x => !!x) - }); - ctx.common.issues.push(issue); } -exports.addIssueToContext = addIssueToContext; - -class ParseStatus { - constructor() { - this.value = "valid"; +class ZodType { + constructor(def) { + /** Alias of safeParseAsync */ + this.spa = this.safeParseAsync; + this.superRefine = this._refinement; + this._def = def; + this.parse = this.parse.bind(this); + this.safeParse = this.safeParse.bind(this); + this.parseAsync = this.parseAsync.bind(this); + this.safeParseAsync = this.safeParseAsync.bind(this); + this.spa = this.spa.bind(this); + this.refine = this.refine.bind(this); + this.refinement = this.refinement.bind(this); + this.superRefine = this.superRefine.bind(this); + this.optional = this.optional.bind(this); + this.nullable = this.nullable.bind(this); + this.nullish = this.nullish.bind(this); + this.array = this.array.bind(this); + this.promise = this.promise.bind(this); + this.or = this.or.bind(this); + this.and = this.and.bind(this); + this.transform = this.transform.bind(this); + this.default = this.default.bind(this); + this.describe = this.describe.bind(this); + this.isNullable = this.isNullable.bind(this); + this.isOptional = this.isOptional.bind(this); } - dirty() { - if (this.value === "valid") this.value = "dirty"; + get description() { + return this._def.description; } - abort() { - if (this.value !== "aborted") this.value = "aborted"; + _getType(input) { + return (0, parseUtil_1.getParsedType)(input.data); } - static mergeArray(status, results) { - const arrayValue = []; - - for (const s of results) { - if (s.status === "aborted") return exports.INVALID; - if (s.status === "dirty") status.dirty(); - arrayValue.push(s.value); - } + _getOrReturnCtx(input, ctx) { + return ctx || { + common: input.parent.common, + data: input.data, + parsedType: (0, parseUtil_1.getParsedType)(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + }; + } + _processInputParams(input) { return { - status: status.value, - value: arrayValue + status: new parseUtil_1.ParseStatus(), + ctx: { + common: input.parent.common, + data: input.data, + parsedType: (0, parseUtil_1.getParsedType)(input.data), + schemaErrorMap: this._def.errorMap, + path: input.path, + parent: input.parent + } }; } - static async mergeObjectAsync(status, pairs) { - const syncPairs = []; + _parseSync(input) { + const result = this._parse(input); - for (const pair of pairs) { - syncPairs.push({ - key: await pair.key, - value: await pair.value - }); + if ((0, parseUtil_1.isAsync)(result)) { + throw new Error("Synchronous parse encountered promise."); } - return ParseStatus.mergeObjectSync(status, syncPairs); + return result; } - static mergeObjectSync(status, pairs) { - const finalObject = {}; - - for (const pair of pairs) { - const { - key, - value - } = pair; - if (key.status === "aborted") return exports.INVALID; - if (value.status === "aborted") return exports.INVALID; - if (key.status === "dirty") status.dirty(); - if (value.status === "dirty") status.dirty(); - - if (typeof value.value !== "undefined" || pair.alwaysSet) { - finalObject[key.value] = value.value; - } - } + _parseAsync(input) { + const result = this._parse(input); - return { - status: status.value, - value: finalObject - }; + return Promise.resolve(result); } -} - -exports.ParseStatus = ParseStatus; -exports.INVALID = Object.freeze({ - status: "aborted" -}); + parse(data, params) { + const result = this.safeParse(data, params); + if (result.success) return result.data; + throw result.error; + } -const DIRTY = value => ({ - status: "dirty", - value -}); + safeParse(data, params) { + var _a; -exports.DIRTY = DIRTY; + const ctx = { + common: { + issues: [], + async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false, + contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap + }, + path: (params === null || params === void 0 ? void 0 : params.path) || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: (0, parseUtil_1.getParsedType)(data) + }; -const OK = value => ({ - status: "valid", - value -}); + const result = this._parseSync({ + data, + path: ctx.path, + parent: ctx + }); -exports.OK = OK; + return handleResult(ctx, result); + } -const isAborted = x => x.status === "aborted"; + async parseAsync(data, params) { + const result = await this.safeParseAsync(data, params); + if (result.success) return result.data; + throw result.error; + } -exports.isAborted = isAborted; + async safeParseAsync(data, params) { + const ctx = { + common: { + issues: [], + contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, + async: true + }, + path: (params === null || params === void 0 ? void 0 : params.path) || [], + schemaErrorMap: this._def.errorMap, + parent: null, + data, + parsedType: (0, parseUtil_1.getParsedType)(data) + }; -const isDirty = x => x.status === "dirty"; + const maybeAsyncResult = this._parse({ + data, + path: [], + parent: ctx + }); -exports.isDirty = isDirty; + const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } -const isValid = x => x.status === "valid"; - -exports.isValid = isValid; - -const isAsync = x => typeof Promise !== undefined && x instanceof Promise; - -exports.isAsync = isAsync; - -},{"../ZodError":6,"./util":11}],10:[function(require,module,exports){ -"use strict"; + refine(check, message) { + const getIssueProperties = val => { + if (typeof message === "string" || typeof message === "undefined") { + return { + message + }; + } else if (typeof message === "function") { + return message(val); + } else { + return message; + } + }; -Object.defineProperty(exports, "__esModule", { - value: true -}); + return this._refinement((val, ctx) => { + const result = check(val); -},{}],11:[function(require,module,exports){ -"use strict"; + const setError = () => ctx.addIssue({ + code: ZodError_1.ZodIssueCode.custom, + ...getIssueProperties(val) + }); -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.util = void 0; -var util; + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then(data => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); + } -(function (util) { - function assertNever(_x) { - throw new Error(); + if (!result) { + setError(); + return false; + } else { + return true; + } + }); } - util.assertNever = assertNever; - - util.arrayToEnum = items => { - const obj = {}; - - for (const item of items) { - obj[item] = item; - } - - return obj; - }; - - util.getValidEnumValues = obj => { - const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); - const filtered = {}; - - for (const k of validKeys) { - filtered[k] = obj[k]; - } - - return util.objectValues(filtered); - }; - - util.objectValues = obj => { - return util.objectKeys(obj).map(function (e) { - return obj[e]; + refinement(check, refinementData) { + return this._refinement((val, ctx) => { + if (!check(val)) { + ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); + return false; + } else { + return true; + } }); - }; - - util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban - ? obj => Object.keys(obj) // eslint-disable-line ban/ban - : object => { - const keys = []; + } - for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key)) { - keys.push(key); + _refinement(refinement) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "refinement", + refinement } - } - - return keys; - }; + }); + } - util.find = (arr, checker) => { - for (const item of arr) { - if (checker(item)) return item; - } + optional() { + return ZodOptional.create(this); + } - return undefined; - }; + nullable() { + return ZodNullable.create(this); + } - util.isInteger = typeof Number.isInteger === "function" ? val => Number.isInteger(val) // eslint-disable-line ban/ban - : val => typeof val === "number" && isFinite(val) && Math.floor(val) === val; + nullish() { + return this.optional().nullable(); + } - function joinValues(array) { - let separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : " | "; - return array.map(val => typeof val === "string" ? "'".concat(val, "'") : val).join(separator); + array() { + return ZodArray.create(this); } - util.joinValues = joinValues; -})(util = exports.util || (exports.util = {})); + promise() { + return ZodPromise.create(this); + } -},{}],12:[function(require,module,exports){ -"use strict"; + or(option) { + return ZodUnion.create([this, option]); + } -var __createBinding = void 0 && (void 0).__createBinding || (Object.create ? function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - var desc = Object.getOwnPropertyDescriptor(m, k); + and(incoming) { + return ZodIntersection.create(this, incoming); + } - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; + transform(transform) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "transform", + transform } - }; + }); } - Object.defineProperty(o, k2, desc); -} : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -}); - -var __setModuleDefault = void 0 && (void 0).__setModuleDefault || (Object.create ? function (o, v) { - Object.defineProperty(o, "default", { - enumerable: true, - value: v - }); -} : function (o, v) { - o["default"] = v; -}); - -var __importStar = void 0 && (void 0).__importStar || function (mod) { - if (mod && mod.__esModule) return mod; - var result = {}; - if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); - - __setModuleDefault(result, mod); + default(def) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + return new ZodDefault({ + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault + }); + } - return result; -}; + describe(description) { + const This = this.constructor; + return new This({ ...this._def, + description + }); + } -var __exportStar = void 0 && (void 0).__exportStar || function (m, exports) { - for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p); -}; + isOptional() { + return this.safeParse(undefined).success; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.z = void 0; + isNullable() { + return this.safeParse(null).success; + } -const mod = __importStar(require("./external")); +} -exports.z = mod; +exports.ZodType = ZodType; +exports.Schema = ZodType; +exports.ZodSchema = ZodType; +const cuidRegex = /^c[^\s-]{8,}$/i; +const uuidRegex = /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; // from https://stackoverflow.com/a/46181/1550155 +// old version: too slow, didn't support unicode +// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; +// eslint-disable-next-line -__exportStar(require("./external"), exports); +const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; -exports.default = mod; +class ZodString extends ZodType { + constructor() { + super(...arguments); -},{"./external":7}],13:[function(require,module,exports){ -"use strict"; + this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { + validation, + code: ZodError_1.ZodIssueCode.invalid_string, + ...errorUtil_1.errorUtil.errToObj(message) + }); + /** + * Deprecated. + * Use z.string().min(1) instead. + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.intersection = exports.instanceof = exports.function = exports.enum = exports.effect = exports.discriminatedUnion = exports.date = exports.boolean = exports.bigint = exports.array = exports.any = exports.ZodFirstPartyTypeKind = exports.late = exports.ZodSchema = exports.Schema = exports.custom = exports.ZodNaN = exports.ZodDefault = exports.ZodNullable = exports.ZodOptional = exports.ZodTransformer = exports.ZodEffects = exports.ZodPromise = exports.ZodNativeEnum = exports.ZodEnum = exports.ZodLiteral = exports.ZodLazy = exports.ZodFunction = exports.ZodSet = exports.ZodMap = exports.ZodRecord = exports.ZodTuple = exports.ZodIntersection = exports.ZodDiscriminatedUnion = exports.ZodUnion = exports.ZodObject = exports.objectUtil = exports.ZodArray = exports.ZodVoid = exports.ZodNever = exports.ZodUnknown = exports.ZodAny = exports.ZodNull = exports.ZodUndefined = exports.ZodDate = exports.ZodBoolean = exports.ZodBigInt = exports.ZodNumber = exports.ZodString = exports.ZodType = void 0; -exports.void = exports.unknown = exports.union = exports.undefined = exports.tuple = exports.transformer = exports.string = exports.strictObject = exports.set = exports.record = exports.promise = exports.preprocess = exports.ostring = exports.optional = exports.onumber = exports.oboolean = exports.object = exports.number = exports.nullable = exports.null = exports.never = exports.nativeEnum = exports.nan = exports.map = exports.literal = exports.lazy = void 0; -const errorUtil_1 = require("./helpers/errorUtil"); + this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); + } -const parseUtil_1 = require("./helpers/parseUtil"); + _parse(input) { + const parsedType = this._getType(input); -const util_1 = require("./helpers/util"); + if (parsedType !== parseUtil_1.ZodParsedType.string) { + const ctx = this._getOrReturnCtx(input); -const ZodError_1 = require("./ZodError"); - -class ParseInputLazyPath { - constructor(parent, value, path, key) { - this.parent = parent; - this.data = value; - this._path = path; - this._key = key; - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.string, + received: ctx.parsedType + } // + ); + return parseUtil_1.INVALID; + } - get path() { - return this._path.concat(this._key); - } + const status = new parseUtil_1.ParseStatus(); + let ctx = undefined; -} + for (const check of this._def.checks) { + if (check.kind === "min") { + if (input.data.length < check.value) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: check.value, + type: "string", + inclusive: true, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + if (input.data.length > check.value) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: check.value, + type: "string", + inclusive: true, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "email") { + if (!emailRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "email", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "uuid") { + if (!uuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "uuid", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "cuid") { + if (!cuidRegex.test(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "cuid", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "url") { + try { + new URL(input.data); + } catch (_a) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "url", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "regex") { + check.regex.lastIndex = 0; + const testResult = check.regex.test(input.data); -const handleResult = (ctx, result) => { - if ((0, parseUtil_1.isValid)(result)) { - return { - success: true, - data: result.value - }; - } else { - if (!ctx.common.issues.length) { - throw new Error("Validation failed but no issues detected."); + if (!testResult) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + validation: "regex", + code: ZodError_1.ZodIssueCode.invalid_string, + message: check.message + }); + status.dirty(); + } + } } - const error = new ZodError_1.ZodError(ctx.common.issues); return { - success: false, - error + status: status.value, + value: input.data }; } -}; - -function processCreateParams(params) { - if (!params) return {}; - const { - errorMap, - invalid_type_error, - required_error, - description - } = params; - if (errorMap && (invalid_type_error || required_error)) { - throw new Error("Can't use \"invalid\" or \"required\" in conjunction with custom error map."); + _addCheck(check) { + return new ZodString({ ...this._def, + checks: [...this._def.checks, check] + }); } - if (errorMap) return { - errorMap: errorMap, - description - }; + email(message) { + return this._addCheck({ + kind: "email", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } - const customMap = (iss, ctx) => { - if (iss.code !== "invalid_type") return { - message: ctx.defaultError - }; - if (typeof ctx.data === "undefined" && required_error) return { - message: required_error - }; - if (params.invalid_type_error) return { - message: params.invalid_type_error - }; - return { - message: ctx.defaultError - }; - }; + url(message) { + return this._addCheck({ + kind: "url", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } - return { - errorMap: customMap, - description - }; -} + uuid(message) { + return this._addCheck({ + kind: "uuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -class ZodType { - constructor(def) { - /** Alias of safeParseAsync */ - this.spa = this.safeParseAsync; - this.superRefine = this._refinement; - this._def = def; - this.parse = this.parse.bind(this); - this.safeParse = this.safeParse.bind(this); - this.parseAsync = this.parseAsync.bind(this); - this.safeParseAsync = this.safeParseAsync.bind(this); - this.spa = this.spa.bind(this); - this.refine = this.refine.bind(this); - this.refinement = this.refinement.bind(this); - this.superRefine = this.superRefine.bind(this); - this.optional = this.optional.bind(this); - this.nullable = this.nullable.bind(this); - this.nullish = this.nullish.bind(this); - this.array = this.array.bind(this); - this.promise = this.promise.bind(this); - this.or = this.or.bind(this); - this.and = this.and.bind(this); - this.transform = this.transform.bind(this); - this.default = this.default.bind(this); - this.describe = this.describe.bind(this); - this.isNullable = this.isNullable.bind(this); - this.isOptional = this.isOptional.bind(this); + cuid(message) { + return this._addCheck({ + kind: "cuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); } - get description() { - return this._def.description; + regex(regex, message) { + return this._addCheck({ + kind: "regex", + regex: regex, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _getType(input) { - return (0, parseUtil_1.getParsedType)(input.data); + min(minLength, message) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _getOrReturnCtx(input, ctx) { - return ctx || { - common: input.parent.common, - data: input.data, - parsedType: (0, parseUtil_1.getParsedType)(input.data), - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent - }; + max(maxLength, message) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); } - _processInputParams(input) { - return { - status: new parseUtil_1.ParseStatus(), - ctx: { - common: input.parent.common, - data: input.data, - parsedType: (0, parseUtil_1.getParsedType)(input.data), - schemaErrorMap: this._def.errorMap, - path: input.path, - parent: input.parent - } - }; + length(len, message) { + return this.min(len, message).max(len, message); } - _parseSync(input) { - const result = this._parse(input); + get isEmail() { + return !!this._def.checks.find(ch => ch.kind === "email"); + } - if ((0, parseUtil_1.isAsync)(result)) { - throw new Error("Synchronous parse encountered promise."); - } - - return result; - } - - _parseAsync(input) { - const result = this._parse(input); - - return Promise.resolve(result); - } - - parse(data, params) { - const result = this.safeParse(data, params); - if (result.success) return result.data; - throw result.error; - } - - safeParse(data, params) { - var _a; - - const ctx = { - common: { - issues: [], - async: (_a = params === null || params === void 0 ? void 0 : params.async) !== null && _a !== void 0 ? _a : false, - contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap - }, - path: (params === null || params === void 0 ? void 0 : params.path) || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: (0, parseUtil_1.getParsedType)(data) - }; - - const result = this._parseSync({ - data, - path: ctx.path, - parent: ctx - }); - - return handleResult(ctx, result); - } - - async parseAsync(data, params) { - const result = await this.safeParseAsync(data, params); - if (result.success) return result.data; - throw result.error; + get isURL() { + return !!this._def.checks.find(ch => ch.kind === "url"); } - async safeParseAsync(data, params) { - const ctx = { - common: { - issues: [], - contextualErrorMap: params === null || params === void 0 ? void 0 : params.errorMap, - async: true - }, - path: (params === null || params === void 0 ? void 0 : params.path) || [], - schemaErrorMap: this._def.errorMap, - parent: null, - data, - parsedType: (0, parseUtil_1.getParsedType)(data) - }; - - const maybeAsyncResult = this._parse({ - data, - path: [], - parent: ctx - }); - - const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); - return handleResult(ctx, result); + get isUUID() { + return !!this._def.checks.find(ch => ch.kind === "uuid"); } - refine(check, message) { - const getIssueProperties = val => { - if (typeof message === "string" || typeof message === "undefined") { - return { - message - }; - } else if (typeof message === "function") { - return message(val); - } else { - return message; - } - }; - - return this._refinement((val, ctx) => { - const result = check(val); - - const setError = () => ctx.addIssue({ - code: ZodError_1.ZodIssueCode.custom, - ...getIssueProperties(val) - }); - - if (typeof Promise !== "undefined" && result instanceof Promise) { - return result.then(data => { - if (!data) { - setError(); - return false; - } else { - return true; - } - }); - } - - if (!result) { - setError(); - return false; - } else { - return true; - } - }); + get isCUID() { + return !!this._def.checks.find(ch => ch.kind === "cuid"); } - refinement(check, refinementData) { - return this._refinement((val, ctx) => { - if (!check(val)) { - ctx.addIssue(typeof refinementData === "function" ? refinementData(val, ctx) : refinementData); - return false; - } else { - return true; - } - }); - } + get minLength() { + let min = -Infinity; - _refinement(refinement) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "refinement", - refinement + this._def.checks.map(ch => { + if (ch.kind === "min") { + if (min === null || ch.value > min) { + min = ch.value; + } } }); - } - - optional() { - return ZodOptional.create(this); - } - - nullable() { - return ZodNullable.create(this); - } - - nullish() { - return this.optional().nullable(); - } - - array() { - return ZodArray.create(this); - } - - promise() { - return ZodPromise.create(this); - } - or(option) { - return ZodUnion.create([this, option]); + return min; } - and(incoming) { - return ZodIntersection.create(this, incoming); - } + get maxLength() { + let max = null; - transform(transform) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "transform", - transform + this._def.checks.map(ch => { + if (ch.kind === "max") { + if (max === null || ch.value < max) { + max = ch.value; + } } }); - } - - default(def) { - const defaultValueFunc = typeof def === "function" ? def : () => def; - return new ZodDefault({ - innerType: this, - defaultValue: defaultValueFunc, - typeName: ZodFirstPartyTypeKind.ZodDefault - }); - } - describe(description) { - const This = this.constructor; - return new This({ ...this._def, - description - }); + return max; } - isOptional() { - return this.safeParse(undefined).success; - } +} - isNullable() { - return this.safeParse(null).success; - } +exports.ZodString = ZodString; -} +ZodString.create = params => { + return new ZodString({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodString, + ...processCreateParams(params) + }); +}; // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 -exports.ZodType = ZodType; -exports.Schema = ZodType; -exports.ZodSchema = ZodType; -const cuidRegex = /^c[^\s-]{8,}$/i; -const uuidRegex = /^([a-f0-9]{8}-[a-f0-9]{4}-[1-5][a-f0-9]{3}-[a-f0-9]{4}-[a-f0-9]{12}|00000000-0000-0000-0000-000000000000)$/i; // from https://stackoverflow.com/a/46181/1550155 -// old version: too slow, didn't support unicode -// const emailRegex = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$/i; -// eslint-disable-next-line -const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; +function floatSafeRemainder(val, step) { + const valDecCount = (val.toString().split(".")[1] || "").length; + const stepDecCount = (step.toString().split(".")[1] || "").length; + const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; + const valInt = parseInt(val.toFixed(decCount).replace(".", "")); + const stepInt = parseInt(step.toFixed(decCount).replace(".", "")); + return valInt % stepInt / Math.pow(10, decCount); +} -class ZodString extends ZodType { +class ZodNumber extends ZodType { constructor() { super(...arguments); - - this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { - validation, - code: ZodError_1.ZodIssueCode.invalid_string, - ...errorUtil_1.errorUtil.errToObj(message) - }); - /** - * Deprecated. - * Use z.string().min(1) instead. - */ - - - this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); + this.min = this.gte; + this.max = this.lte; + this.step = this.multipleOf; } _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.string) { + if (parsedType !== parseUtil_1.ZodParsedType.number) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.string, + expected: parseUtil_1.ZodParsedType.number, received: ctx.parsedType - } // - ); + }); return parseUtil_1.INVALID; } - const status = new parseUtil_1.ParseStatus(); let ctx = undefined; - - for (const check of this._def.checks) { - if (check.kind === "min") { - if (input.data.length < check.value) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: check.value, - type: "string", - inclusive: true, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "max") { - if (input.data.length > check.value) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: check.value, - type: "string", - inclusive: true, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "email") { - if (!emailRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "email", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "uuid") { - if (!uuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "uuid", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "cuid") { - if (!cuidRegex.test(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "cuid", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "url") { - try { - new URL(input.data); - } catch (_a) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "url", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "regex") { - check.regex.lastIndex = 0; - const testResult = check.regex.test(input.data); - - if (!testResult) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - validation: "regex", - code: ZodError_1.ZodIssueCode.invalid_string, - message: check.message - }); - status.dirty(); - } - } - } - - return { - status: status.value, - value: input.data - }; - } - - _addCheck(check) { - return new ZodString({ ...this._def, - checks: [...this._def.checks, check] - }); - } - - email(message) { - return this._addCheck({ - kind: "email", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - url(message) { - return this._addCheck({ - kind: "url", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - uuid(message) { - return this._addCheck({ - kind: "uuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - cuid(message) { - return this._addCheck({ - kind: "cuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - regex(regex, message) { - return this._addCheck({ - kind: "regex", - regex: regex, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - min(minLength, message) { - return this._addCheck({ - kind: "min", - value: minLength, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - max(maxLength, message) { - return this._addCheck({ - kind: "max", - value: maxLength, - ...errorUtil_1.errorUtil.errToObj(message) - }); - } - - length(len, message) { - return this.min(len, message).max(len, message); - } - - get isEmail() { - return !!this._def.checks.find(ch => ch.kind === "email"); - } - - get isURL() { - return !!this._def.checks.find(ch => ch.kind === "url"); - } - - get isUUID() { - return !!this._def.checks.find(ch => ch.kind === "uuid"); - } - - get isCUID() { - return !!this._def.checks.find(ch => ch.kind === "cuid"); - } - - get minLength() { - let min = -Infinity; - - this._def.checks.map(ch => { - if (ch.kind === "min") { - if (min === null || ch.value > min) { - min = ch.value; - } - } - }); - - return min; - } - - get maxLength() { - let max = null; - - this._def.checks.map(ch => { - if (ch.kind === "max") { - if (max === null || ch.value < max) { - max = ch.value; - } - } - }); - - return max; - } - -} - -exports.ZodString = ZodString; - -ZodString.create = params => { - return new ZodString({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodString, - ...processCreateParams(params) - }); -}; // https://stackoverflow.com/questions/3966484/why-does-modulus-operator-return-fractional-number-in-javascript/31711034#31711034 - - -function floatSafeRemainder(val, step) { - const valDecCount = (val.toString().split(".")[1] || "").length; - const stepDecCount = (step.toString().split(".")[1] || "").length; - const decCount = valDecCount > stepDecCount ? valDecCount : stepDecCount; - const valInt = parseInt(val.toFixed(decCount).replace(".", "")); - const stepInt = parseInt(step.toFixed(decCount).replace(".", "")); - return valInt % stepInt / Math.pow(10, decCount); -} - -class ZodNumber extends ZodType { - constructor() { - super(...arguments); - this.min = this.gte; - this.max = this.lte; - this.step = this.multipleOf; - } - - _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.number) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.number, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } - - let ctx = undefined; - const status = new parseUtil_1.ParseStatus(); + const status = new parseUtil_1.ParseStatus(); for (const check of this._def.checks) { if (check.kind === "int") { @@ -4429,464 +3720,1073 @@ const ostring = () => stringType().optional(); exports.ostring = ostring; -const onumber = () => numberType().optional(); +const onumber = () => numberType().optional(); + +exports.onumber = onumber; + +const oboolean = () => booleanType().optional(); + +exports.oboolean = oboolean; + +},{"./ZodError":2,"./helpers/errorUtil":4,"./helpers/parseUtil":5,"./helpers/util":7}],10:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "DeviceApi", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApi; + } +}); +Object.defineProperty(exports, "DeviceApiCall", { + enumerable: true, + get: function () { + return _deviceApiCall.DeviceApiCall; + } +}); +Object.defineProperty(exports, "DeviceApiTransport", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApiTransport; + } +}); +Object.defineProperty(exports, "createNotification", { + enumerable: true, + get: function () { + return _deviceApiCall.createNotification; + } +}); +Object.defineProperty(exports, "createRequest", { + enumerable: true, + get: function () { + return _deviceApiCall.createRequest; + } +}); +Object.defineProperty(exports, "validate", { + enumerable: true, + get: function () { + return _deviceApiCall.validate; + } +}); + +var _deviceApiCall = require("./lib/device-api-call.js"); + +var _deviceApi = require("./lib/device-api.js"); + +},{"./lib/device-api-call.js":11,"./lib/device-api.js":12}],11:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; +exports.createDeviceApiCall = createDeviceApiCall; +exports.createNotification = void 0; +exports.createRequest = createRequest; +exports.validate = validate; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * This roughly follows https://www.jsonrpc.org/specification + * @template {import("zod").ZodType} Params=import("zod").ZodType + * @template {import("zod").ZodType} Result=import("zod").ZodType + */ +class DeviceApiCall { + /** @type {string} */ + + /** + * An optional 'id' - used to indicate if a request requires a response. + * @type {string|null} + */ + + /** @type {Params | null | undefined} */ + + /** @type {Result | null | undefined} */ + + /** @type {import("zod").infer} */ + + /** + * This is a carve-out for legacy messages that are not typed yet. + * If you set this to 'true', then the response will not be checked to conform + * to any shape + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ + + /** + * New messages should be in a particular format, eg: { success: T }, + * but you can set this to false if you want to access the result as-is, + * without any unwrapping logic + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ + + /** + * @param {import("zod").infer} data + */ + constructor(data) { + _defineProperty(this, "method", 'unknown'); + + _defineProperty(this, "id", null); + + _defineProperty(this, "paramsValidator", null); + + _defineProperty(this, "resultValidator", null); + + _defineProperty(this, "params", void 0); + + _defineProperty(this, "throwOnResultKeysMissing", true); + + _defineProperty(this, "unwrapResult", true); + + this.params = data; + } + /** + * @returns {import("zod").infer|undefined} + */ + + + validateParams() { + if (this.params === undefined) { + return undefined; + } + + this._validate(this.params, this.paramsValidator); + + return this.params; + } + /** + * @param {any|null} incoming + * @returns {import("zod").infer} + */ + + + validateResult(incoming) { + this._validate(incoming, this.resultValidator); + + if (!incoming) { + return incoming; + } + + if (!this.unwrapResult) { + return incoming; + } + + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } + + if ('success' in incoming) { + return incoming.success; + } + + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + } + } + + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); + } + + return incoming; + } + /** + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private + */ + + + _validate(data, validator) { + if (!validator) return data; + + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + + if (!result) { + throw new Error('unreachable, data failure', data); + } + + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } + } + } + } + /** + * @param {import('zod').ZodIssue[]} errors + */ + + + throwError(errors) { + const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); + throw error; + } + /** + * Use this helper for creating stand-in response messages that are typed correctly. + * + * @examples + * + * ```js + * const msg = new Message(); + * const response = msg.response({}) // <-- This argument will be typed correctly + * ``` + * + * @param {import("zod").infer} response + * @returns {import("zod").infer} + */ + + + result(response) { + return response; + } + /** + * @returns {import("zod").infer} + */ + + + preResultValidation(response) { + return response; + } + +} + +exports.DeviceApiCall = DeviceApiCall; + +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ + + +exports.DeviceApiCallError = DeviceApiCallError; + +class SchemaValidationError extends Error { + constructor() { + super(...arguments); + + _defineProperty(this, "validationErrors", []); + } + + /** + * @param {import("zod").ZodIssue[]} errors + * @param {string} name + * @returns {SchemaValidationError} + */ + static fromZodErrors(errors, name) { + const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; + + function log(issue) { + switch (issue.code) { + case 'invalid_literal': + case 'invalid_type': + { + console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); + break; + } + + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } + + break; + } + + default: + { + console.log(name, 'other issue:', issue); + } + } + } + + for (let error of errors) { + log(error); + } + + const message = [heading, 'please see the details above'].join('\n '); + const error = new SchemaValidationError(message); + error.validationErrors = errors; + return error; + } + +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ + + +exports.SchemaValidationError = SchemaValidationError; + +function createDeviceApiCall(method, params) { + let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + + /** @type {DeviceApiCall} */ + const deviceApiCall = new DeviceApiCall(params); + deviceApiCall.paramsValidator = paramsValidator; + deviceApiCall.resultValidator = resultValidator; + deviceApiCall.method = method; + deviceApiCall.throwOnResultKeysMissing = false; + deviceApiCall.unwrapResult = false; + return deviceApiCall; +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string + * so that transports know that it expects a response. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {string} [id] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ + + +function createRequest(method, params) { + let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; + let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); + call.id = id; + return call; +} + +const createNotification = createDeviceApiCall; +/** + * Validate any arbitrary data with any Zod validator + * + * @template {import("zod").ZodType} Validator + * @param {any} data + * @param {Validator | null} [validator] + * @returns {import("zod").infer} + */ + +exports.createNotification = createNotification; + +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (validator) { + return validator.parse(data); + } + + return data; +} + +},{}],12:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Platforms should only need to implement this `send` method + */ +class DeviceApiTransport { + /** + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} + */ + async send(_deviceApiCall, _options) { + return undefined; + } + +} +/** + * This is the base Sender class that platforms can will implement. + * + * Note: The 'handle' method must be implemented, unless you also implement 'send' + * + * @typedef CallOptions + * @property {AbortSignal} [signal] + */ + + +exports.DeviceApiTransport = DeviceApiTransport; + +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ + + + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); + } + /** + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} + */ + -exports.onumber = onumber; + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); + } -const oboolean = () => booleanType().optional(); +} -exports.oboolean = oboolean; +exports.DeviceApi = DeviceApi; -},{"./ZodError":6,"./helpers/errorUtil":8,"./helpers/parseUtil":9,"./helpers/util":11}],14:[function(require,module,exports){ +},{}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -Object.defineProperty(exports, "DeviceApi", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApi; - } -}); -Object.defineProperty(exports, "DeviceApiCall", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.DeviceApiCall; + return _webkit.WebkitMessagingConfig; } }); -Object.defineProperty(exports, "DeviceApiTransport", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApiTransport; + +var _webkit = require("./webkit.js"); + +/** + * @module Messaging + * + * @description + * + * An abstraction for communications between JavaScript and host platforms. + * + * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) + * 2) Then use that to get an instance of the Messaging utility which allows + * you to send and receive data in a unified way + * 3) Each platform implements {@link MessagingTransport} along with its own Configuration + * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} + * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} + * + * @example Webkit Messaging + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + * + * @example Windows Messaging + * + * ```js + * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // Messaging on Windows is namespaced, so you can create multiple messaging instances + * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); + * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); + * + * const autofillMessaging = new Messaging(autofillConfig); + * const debugMessaging = new Messaging(debugConfig); + * + * // Now send messages to both features as needed 🚀 + * autofillMessaging.notify("storeFormData", { "username": "dax" }) + * debugMessaging.notify("pageLoad", { time: window.performance.now() }) + * ``` + */ + +/** + * @implements {MessagingTransport} + */ +class Messaging { + /** + * @param {WebkitMessagingConfig} config + */ + constructor(config) { + this.transport = getTransport(config); } -}); -Object.defineProperty(exports, "createNotification", { - enumerable: true, - get: function () { - return _deviceApiCall.createNotification; + /** + * Send a 'fire-and-forget' message. + * @throws {Error} + * {@link MissingHandler} + * + * @example + * + * ``` + * const messaging = new Messaging(config) + * messaging.notify("foo", {bar: "baz"}) + * ``` + * @param {string} name + * @param {Record} [data] + */ + + + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.transport.notify(name, data); } -}); -Object.defineProperty(exports, "createRequest", { - enumerable: true, - get: function () { - return _deviceApiCall.createRequest; + /** + * Send a request, and wait for a response + * @throws {Error} + * {@link MissingHandler} + * + * @example + * ``` + * const messaging = new Messaging(config) + * const response = await messaging.request("foo", {bar: "baz"}) + * ``` + * + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + + + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); } -}); -Object.defineProperty(exports, "validate", { - enumerable: true, - get: function () { - return _deviceApiCall.validate; + +} +/** + * @interface + */ + + +exports.Messaging = Messaging; + +class MessagingTransport { + /** + * @param {string} name + * @param {Record} [data] + * @returns {void} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error("must implement 'notify'"); } -}); + /** + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. -var _deviceApiCall = require("./lib/device-api-call.js"); -var _deviceApi = require("./lib/device-api.js"); + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); + } -},{"./lib/device-api-call.js":15,"./lib/device-api.js":16}],15:[function(require,module,exports){ -"use strict"; +} +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; -exports.createDeviceApiCall = createDeviceApiCall; -exports.createNotification = void 0; -exports.createRequest = createRequest; -exports.validate = validate; -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +exports.MessagingTransport = MessagingTransport; + +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); + } + throw new Error('unreachable'); +} /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * Thrown when a handler cannot be found */ -class DeviceApiCall { - /** @type {string} */ + +class MissingHandler extends Error { /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} - */ + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } - /** @type {Params | null | undefined} */ +} +/** + * Some re-exports for convenience + */ - /** @type {Result | null | undefined} */ - /** @type {import("zod").infer} */ +exports.MissingHandler = MissingHandler; - /** - * This is a carve-out for legacy messages that are not typed yet. - * If you set this to 'true', then the response will not be checked to conform - * to any shape - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +},{"./webkit.js":14}],14:[function(require,module,exports){ +"use strict"; - /** - * New messages should be in a particular format, eg: { success: T }, - * but you can set this to false if you want to access the result as-is, - * without any unwrapping logic - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + +var _messaging = require("./messaging.js"); + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * @typedef {import("./messaging").MessagingTransport} MessagingTransport + */ + +/** + * @example + * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` + * + * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following + * would occur: + * + * ```js + * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); + * const response = JSON.parse(json) + * ``` + * + * @example + * On macOS 10 however, the process is a little more involved. A method will be appended to `window` + * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow + * as being something along the lines of: + * + * ```js + * // add the window method + * window["_0123456"] = (response) => { + * // decrypt `response` and deliver the result to the caller here + * // then remove the temporary method + * delete window["_0123456"] + * }; + * + * // send the data + `messageHanding` values + * window.webkit.messageHandlers.foo.postMessage({ + * bar: "baz", + * messagingHandling: { + * methodName: "_0123456", + * secret: "super-secret", + * key: [1, 2, 45, 2], + * iv: [34, 4, 43], + * } + * }); + * + * // later in swift, the following JavaScript snippet will be executed + * (() => { + * window["_0123456"]({ + * ciphertext: [12, 13, 4], + * tag: [3, 5, 67, 56] + * }) + * })() + * ``` + * @implements {MessagingTransport} + */ +class WebkitMessagingTransport { + /** @type {WebkitMessagingConfig} */ /** - * @param {import("zod").infer} data + * @param {WebkitMessagingConfig} config */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - - _defineProperty(this, "resultValidator", null); - - _defineProperty(this, "params", void 0); - - _defineProperty(this, "throwOnResultKeysMissing", true); + constructor(config) { + _defineProperty(this, "config", void 0); - _defineProperty(this, "unwrapResult", true); + _defineProperty(this, "globals", void 0); - this.params = data; - } - /** - * @returns {import("zod").infer|undefined} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - validateParams() { - if (this.params === undefined) { - return undefined; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - this._validate(this.params, this.paramsValidator); - - return this.params; } /** - * @param {any|null} incoming - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - validateResult(incoming) { - this._validate(incoming, this.resultValidator); - - if (!incoming) { - return incoming; - } - - if (!this.unwrapResult) { - return incoming; - } + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if ('success' in incoming) { - return incoming.success; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); } - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } - } + }; - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + if (!(handler in this.globals.capturedWebkitHandlers)) { + throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); + } else { + return this.globals.capturedWebkitHandlers[handler](outgoing); + } } - return incoming; + return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - _validate(data, validator) { - if (!validator) return data; - - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + try { + const randMethodName = this.createRandMethodName(); + const key = await this.createRandKey(); + const iv = this.createRandIv(); + const { + ciphertext, + tag + } = await new this.globals.Promise(( + /** @type {any} */ + resolve) => { + this.generateRandomMethod(randMethodName, resolve); + data.messageHandling = new SecureMessagingParams({ + methodName: randMethodName, + secret: this.config.secret, + key: this.globals.Arrayfrom(key), + iv: this.globals.Arrayfrom(iv) + }); + this.wkSend(handler, data); + }); + const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); + const decrypted = await this.decrypt(cipher, key, iv); + return this.globals.JSONparse(decrypted || '{}'); + } catch (e) { + // re-throw when the error is just a 'MissingHandler' + if (e instanceof _messaging.MissingHandler) { + throw e; + } else { + console.error('decryption failed', e); + console.error(e); + return { + error: e + }; } } } /** - * @param {import('zod').ZodIssue[]} errors + * @param {string} name + * @param {Record} [data] */ - throwError(errors) { - const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); - throw error; + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } /** - * Use this helper for creating stand-in response messages that are typed correctly. - * - * @examples - * - * ```js - * const msg = new Message(); - * const response = msg.response({}) // <-- This argument will be typed correctly - * ``` - * - * @param {import("zod").infer} response - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - result(response) { - return response; + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.wkSendAndWait(name, data); } /** - * @returns {import("zod").infer} + * Generate a random method name and adds it to the global scope + * The native layer will use this method to send the response + * @param {string | number} randomMethodName + * @param {Function} callback */ - preResultValidation(response) { - return response; - } + generateRandomMethod(randomMethodName, callback) { + var _this = this; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -exports.DeviceApiCall = DeviceApiCall; + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + delete _this.globals.window[randomMethodName]; + } + }); + } + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.DeviceApiCallError = DeviceApiCallError; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -class SchemaValidationError extends Error { - constructor() { - super(...arguments); - _defineProperty(this, "validationErrors", []); + /** + * @returns {Promise} + */ + async createRandKey() { + const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); + const exportedKey = await this.globals.exportKey('raw', key); + return new this.globals.Uint8Array(exportedKey); } + /** + * @returns {Uint8Array} + */ + + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } /** - * @param {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ + + + async decrypt(ciphertext, key, iv) { + const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); + const algo = { + name: 'AES-GCM', + iv + }; + let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); + let dec = new this.globals.TextDecoder(); + return dec.decode(decrypted); + } + /** + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - static fromZodErrors(errors, name) { - const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; - function log(issue) { - switch (issue.code) { - case 'invalid_literal': - case 'invalid_type': - { - console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); - break; - } - case 'invalid_union': - { - for (let unionError of issue.unionErrors) { - for (let issue1 of unionError.issues) { - log(issue1); - } - } + captureWebkitHandlers(handlerNames) { + const handlers = window.webkit.messageHandlers; + if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - break; - } + for (let webkitMessageHandlerName of handlerNames) { + var _handlers$webkitMessa; - default: - { - console.log(name, 'other issue:', issue); - } - } - } + if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { + var _handlers$webkitMessa2; - for (let error of errors) { - log(error); + /** + * `bind` is used here to ensure future calls to the captured + * `postMessage` have the correct `this` context + */ + const original = handlers[webkitMessageHandlerName]; + const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); + this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; + delete handlers[webkitMessageHandlerName].postMessage; + } } - - const message = [heading, 'please see the details above'].join('\n '); - const error = new SchemaValidationError(message); - error.validationErrors = errors; - return error; } } /** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} - */ - - -exports.SchemaValidationError = SchemaValidationError; - -function createDeviceApiCall(method, params) { - let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - /** @type {DeviceApiCall} */ - const deviceApiCall = new DeviceApiCall(params); - deviceApiCall.paramsValidator = paramsValidator; - deviceApiCall.resultValidator = resultValidator; - deviceApiCall.method = method; - deviceApiCall.throwOnResultKeysMissing = false; - deviceApiCall.unwrapResult = false; - return deviceApiCall; -} -/** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string - * so that transports know that it expects a response. + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {string} [id] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -function createRequest(method, params) { - let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; - let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); - call.id = id; - return call; -} - -const createNotification = createDeviceApiCall; -/** - * Validate any arbitrary data with any Zod validator - * - * @template {import("zod").ZodType} Validator - * @param {any} data - * @param {Validator | null} [validator] - * @returns {import("zod").infer} - */ +exports.WebkitMessagingTransport = WebkitMessagingTransport; -exports.createNotification = createNotification; +class WebkitMessagingConfig { + /** + * @param {object} params + * @param {boolean} params.hasModernWebkitAPI + * @param {string[]} params.webkitMessageHandlerNames + * @param {string} params.secret + */ + constructor(params) { + /** + * Whether or not the current WebKit Platform supports secure messaging + * by default (eg: macOS 11+) + */ + this.hasModernWebkitAPI = params.hasModernWebkitAPI; + /** + * A list of WebKit message handler names that a user script can send + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; + /** + * A string provided by native platforms to be sent with future outgoing + * messages + */ - if (validator) { - return validator.parse(data); + this.secret = params.secret; } - return data; } - -},{}],16:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - /** - * Platforms should only need to implement this `send` method + * This is the additional payload that gets appended to outgoing messages. + * It's used in the Swift side to encrypt the response that comes back */ -class DeviceApiTransport { - /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} - */ - async send(_deviceApiCall, _options) { - return undefined; - } -} -/** - * This is the base Sender class that platforms can will implement. - * - * Note: The 'handle' method must be implemented, unless you also implement 'send' - * - * @typedef CallOptions - * @property {AbortSignal} [signal] - */ +exports.WebkitMessagingConfig = WebkitMessagingConfig; -exports.DeviceApiTransport = DeviceApiTransport; +class SecureMessagingParams { + /** + * @param {object} params + * @param {string} params.methodName + * @param {string} params.secret + * @param {number[]} params.key + * @param {number[]} params.iv + */ + constructor(params) { + /** + * The method that's been appended to `window` to be called later + */ + this.methodName = params.methodName; + /** + * The secret used to ensure message sender validity + */ -class DeviceApi { - /** @type {DeviceApiTransport} */ + this.secret = params.secret; + /** + * The CipherKey as number[] + */ - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); + this.key = params.key; + /** + * The Initial Vector as number[] + */ - this.transport = transport; + this.iv = params.iv; } - /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} - */ +} +/** + * Capture some globals used for messaging handling to prevent page + * scripts from tampering with this + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); - } - /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} - */ +exports.SecureMessagingParams = SecureMessagingParams; - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); - } +function captureGlobals() { + // Creat base with null prototype + return { + window, + // Methods must be bound to their interface, otherwise they throw Illegal invocation + encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), + decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), + generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), + exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), + importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), + getRandomValues: window.crypto.getRandomValues.bind(window.crypto), + TextEncoder, + TextDecoder, + Uint8Array, + Uint16Array, + Uint32Array, + JSONstringify: window.JSON.stringify, + JSONparse: window.JSON.parse, + Arrayfrom: window.Array.from, + Promise: window.Promise, + ObjectDefineProperty: window.Object.defineProperty, + addEventListener: window.addEventListener.bind(window), + /** @type {Record} */ + capturedWebkitHandlers: {} + }; } -exports.DeviceApi = DeviceApi; - -},{}],17:[function(require,module,exports){ +},{"./messaging.js":13}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5035,7 +4935,7 @@ function _safeHostname(inputHostname) { } } -},{"./lib/apple.password.js":18,"./lib/constants.js":19,"./lib/rules-parser.js":20}],18:[function(require,module,exports){ +},{"./lib/apple.password.js":16,"./lib/constants.js":17,"./lib/rules-parser.js":18}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5659,7 +5559,7 @@ exports.Password = Password; _defineProperty(Password, "defaults", defaults); -},{"./constants.js":19,"./rules-parser.js":20}],19:[function(require,module,exports){ +},{"./constants.js":17,"./rules-parser.js":18}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5680,7 +5580,7 @@ const constants = { }; exports.constants = constants; -},{}],20:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6413,7 +6313,7 @@ function parsePasswordRules(input, formatRulesForMinifiedVersion) { return newPasswordRules; } -},{}],21:[function(require,module,exports){ +},{}],19:[function(require,module,exports){ module.exports={ "163.com": { "password-rules": "minlength: 6; maxlength: 16;" @@ -7244,7 +7144,7 @@ module.exports={ "password-rules": "minlength: 8; maxlength: 32; max-consecutive: 6; required: lower; required: upper; required: digit;" } } -},{}],22:[function(require,module,exports){ +},{}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7317,7 +7217,7 @@ function createDevice() { return new _ExtensionInterface.ExtensionInterface(globalConfig, deviceApi, settings); } -},{"../packages/device-api/index.js":14,"./DeviceInterface/AndroidInterface.js":23,"./DeviceInterface/AppleDeviceInterface.js":24,"./DeviceInterface/AppleOverlayDeviceInterface.js":25,"./DeviceInterface/ExtensionInterface.js":26,"./DeviceInterface/WindowsInterface.js":28,"./DeviceInterface/WindowsOverlayDeviceInterface.js":29,"./Settings.js":50,"./config.js":63,"./deviceApiCalls/transports/transports.js":71}],23:[function(require,module,exports){ +},{"../packages/device-api/index.js":10,"./DeviceInterface/AndroidInterface.js":21,"./DeviceInterface/AppleDeviceInterface.js":22,"./DeviceInterface/AppleOverlayDeviceInterface.js":23,"./DeviceInterface/ExtensionInterface.js":24,"./DeviceInterface/WindowsInterface.js":26,"./DeviceInterface/WindowsOverlayDeviceInterface.js":27,"./Settings.js":48,"./config.js":61,"./deviceApiCalls/transports/transports.js":69}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7467,7 +7367,7 @@ class AndroidInterface extends _InterfacePrototype.default { exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],24:[function(require,module,exports){ +},{"../UI/controllers/NativeUIController.js":54,"../autofill-utils.js":59,"./InterfacePrototype.js":25,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7919,7 +7819,7 @@ class AppleDeviceInterface extends _InterfacePrototype.default { exports.AppleDeviceInterface = AppleDeviceInterface; -},{"../../packages/device-api/index.js":14,"../Form/matching.js":43,"../InContextSignup.js":44,"../UI/HTMLTooltip.js":54,"../UI/controllers/HTMLTooltipUIController.js":55,"../UI/controllers/NativeUIController.js":56,"../UI/controllers/OverlayUIController.js":57,"../autofill-utils.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/additionalDeviceApiCalls.js":67,"./InterfacePrototype.js":27,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],25:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../Form/matching.js":41,"../InContextSignup.js":42,"../UI/HTMLTooltip.js":52,"../UI/controllers/HTMLTooltipUIController.js":53,"../UI/controllers/NativeUIController.js":54,"../UI/controllers/OverlayUIController.js":55,"../autofill-utils.js":59,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/additionalDeviceApiCalls.js":65,"./InterfacePrototype.js":25,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8074,7 +7974,7 @@ class AppleOverlayDeviceInterface extends _AppleDeviceInterface.AppleDeviceInter exports.AppleOverlayDeviceInterface = AppleOverlayDeviceInterface; -},{"../../packages/device-api/index.js":14,"../UI/controllers/HTMLTooltipUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/__generated__/validators.zod.js":66,"./AppleDeviceInterface.js":24,"./overlayApi.js":31}],26:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../UI/controllers/HTMLTooltipUIController.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/__generated__/validators.zod.js":64,"./AppleDeviceInterface.js":22,"./overlayApi.js":29}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8352,7 +8252,7 @@ class ExtensionInterface extends _InterfacePrototype.default { exports.ExtensionInterface = ExtensionInterface; -},{"../Form/matching.js":43,"../InContextSignup.js":44,"../UI/HTMLTooltip.js":54,"../UI/controllers/HTMLTooltipUIController.js":55,"../autofill-utils.js":61,"./InterfacePrototype.js":27}],27:[function(require,module,exports){ +},{"../Form/matching.js":41,"../InContextSignup.js":42,"../UI/HTMLTooltip.js":52,"../UI/controllers/HTMLTooltipUIController.js":53,"../autofill-utils.js":59,"./InterfacePrototype.js":25}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9421,7 +9321,7 @@ class InterfacePrototype { var _default = InterfacePrototype; exports.default = _default; -},{"../../packages/device-api/index.js":14,"../EmailProtection.js":32,"../Form/formatters.js":36,"../Form/matching.js":43,"../InputTypes/Credentials.js":45,"../PasswordGenerator.js":48,"../Scanner.js":49,"../Settings.js":50,"../UI/controllers/NativeUIController.js":56,"../autofill-utils.js":61,"../config.js":63,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"../deviceApiCalls/__generated__/validators.zod.js":66,"../deviceApiCalls/transports/transports.js":71,"./initFormSubmissionsApi.js":30}],28:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"../EmailProtection.js":30,"../Form/formatters.js":34,"../Form/matching.js":41,"../InputTypes/Credentials.js":43,"../PasswordGenerator.js":46,"../Scanner.js":47,"../Settings.js":48,"../UI/controllers/NativeUIController.js":54,"../autofill-utils.js":59,"../config.js":61,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"../deviceApiCalls/__generated__/validators.zod.js":64,"../deviceApiCalls/transports/transports.js":69,"./initFormSubmissionsApi.js":28}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9637,7 +9537,7 @@ class WindowsInterface extends _InterfacePrototype.default { exports.WindowsInterface = WindowsInterface; -},{"../UI/controllers/OverlayUIController.js":57,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27}],29:[function(require,module,exports){ +},{"../UI/controllers/OverlayUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"./InterfacePrototype.js":25}],27:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9846,7 +9746,7 @@ class WindowsOverlayDeviceInterface extends _InterfacePrototype.default { exports.WindowsOverlayDeviceInterface = WindowsOverlayDeviceInterface; -},{"../UI/controllers/HTMLTooltipUIController.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":65,"./InterfacePrototype.js":27,"./overlayApi.js":31}],30:[function(require,module,exports){ +},{"../UI/controllers/HTMLTooltipUIController.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":63,"./InterfacePrototype.js":25,"./overlayApi.js":29}],28:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9952,7 +9852,7 @@ function initFormSubmissionsApi(forms, matching) { }); } -},{"../Form/label-util.js":39,"../autofill-utils.js":61}],31:[function(require,module,exports){ +},{"../Form/label-util.js":37,"../autofill-utils.js":59}],29:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -10019,7 +9919,7 @@ function overlayApi(device) { }; } -},{"../deviceApiCalls/__generated__/deviceApiCalls.js":65}],32:[function(require,module,exports){ +},{"../deviceApiCalls/__generated__/deviceApiCalls.js":63}],30:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -10080,7 +9980,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],33:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11000,7 +10900,7 @@ class Form { exports.Form = Form; -},{"../autofill-utils.js":61,"../constants.js":64,"./FormAnalyzer.js":34,"./formatters.js":36,"./inputStyles.js":37,"./inputTypeConfig.js":38,"./matching.js":43}],34:[function(require,module,exports){ +},{"../autofill-utils.js":59,"../constants.js":62,"./FormAnalyzer.js":32,"./formatters.js":34,"./inputStyles.js":35,"./inputTypeConfig.js":36,"./matching.js":41}],32:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11394,7 +11294,7 @@ class FormAnalyzer { var _default = FormAnalyzer; exports.default = _default; -},{"../autofill-utils.js":61,"../constants.js":64,"./matching-config/__generated__/compiled-matching-config.js":41,"./matching.js":43}],35:[function(require,module,exports){ +},{"../autofill-utils.js":59,"../constants.js":62,"./matching-config/__generated__/compiled-matching-config.js":39,"./matching.js":41}],33:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11962,7 +11862,7 @@ const COUNTRY_NAMES_TO_CODES = { }; exports.COUNTRY_NAMES_TO_CODES = COUNTRY_NAMES_TO_CODES; -},{}],36:[function(require,module,exports){ +},{}],34:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12319,7 +12219,7 @@ const prepareFormValuesForStorage = formValues => { exports.prepareFormValuesForStorage = prepareFormValuesForStorage; -},{"./countryNames.js":35,"./matching.js":43}],37:[function(require,module,exports){ +},{"./countryNames.js":33,"./matching.js":41}],35:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12421,7 +12321,7 @@ const getIconStylesAutofilled = (input, form) => { exports.getIconStylesAutofilled = getIconStylesAutofilled; -},{"./inputTypeConfig.js":38}],38:[function(require,module,exports){ +},{"./inputTypeConfig.js":36}],36:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12701,7 +12601,7 @@ const isFieldDecorated = input => { exports.isFieldDecorated = isFieldDecorated; -},{"../InputTypes/Credentials.js":45,"../InputTypes/CreditCard.js":46,"../InputTypes/Identity.js":47,"../UI/img/ddgPasswordIcon.js":59,"../constants.js":64,"./logo-svg.js":40,"./matching.js":43}],39:[function(require,module,exports){ +},{"../InputTypes/Credentials.js":43,"../InputTypes/CreditCard.js":44,"../InputTypes/Identity.js":45,"../UI/img/ddgPasswordIcon.js":57,"../constants.js":62,"./logo-svg.js":38,"./matching.js":41}],37:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12762,7 +12662,7 @@ const extractElementStrings = element => { exports.extractElementStrings = extractElementStrings; -},{"./matching.js":43}],40:[function(require,module,exports){ +},{"./matching.js":41}],38:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -12776,7 +12676,7 @@ const daxGrayscaleSvg = "\n * {\n border-radius: 8px;\n border: 0;\n cursor: pointer;\n display: inline-block;\n font-family: inherit;\n font-style: normal;\n font-weight: bold;\n padding: 8px 12px;\n text-decoration: none;\n}\n\n.notice-controls .ghost {\n margin-left: 1rem;\n}\n\n.tooltip--email-signup a.primary {\n background: #3969EF;\n color: #fff;\n}\n\n.tooltip--email-signup a.primary:hover,\n.tooltip--email-signup a.primary:focus {\n background: #2b55ca;\n}\n\n.tooltip--email-signup a.primary:active {\n background: #1e42a4;\n}\n\n.tooltip--email-signup button.ghost {\n background: transparent;\n color: #3969EF;\n}\n\n.tooltip--email-signup button.ghost:hover,\n.tooltip--email-signup button.ghost:focus {\n background-color: rgba(0, 0, 0, 0.06);\n color: #2b55ca;\n}\n\n.tooltip--email-signup button.ghost:active {\n background-color: rgba(0, 0, 0, 0.12);\n color: #1e42a4;\n}\n\n.tooltip--email-signup button.close-tooltip {\n background-color: transparent;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMiAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjI5Mjg5NCAwLjY1NjkwN0MwLjY4MzQxOCAwLjI2NjM4MyAxLjMxNjU4IDAuMjY2MzgzIDEuNzA3MTEgMC42NTY5MDdMNiA0Ljk0OThMMTAuMjkyOSAwLjY1NjkwN0MxMC42ODM0IDAuMjY2MzgzIDExLjMxNjYgMC4yNjYzODMgMTEuNzA3MSAwLjY1NjkwN0MxMi4wOTc2IDEuMDQ3NDMgMTIuMDk3NiAxLjY4MDYgMTEuNzA3MSAyLjA3MTEyTDcuNDE0MjEgNi4zNjQwMUwxMS43MDcxIDEwLjY1NjlDMTIuMDk3NiAxMS4wNDc0IDEyLjA5NzYgMTEuNjgwNiAxMS43MDcxIDEyLjA3MTFDMTEuMzE2NiAxMi40NjE2IDEwLjY4MzQgMTIuNDYxNiAxMC4yOTI5IDEyLjA3MTFMNiA3Ljc3ODIzTDEuNzA3MTEgMTIuMDcxMUMxLjMxNjU4IDEyLjQ2MTYgMC42ODM0MTcgMTIuNDYxNiAwLjI5Mjg5MyAxMi4wNzExQy0wLjA5NzYzMTEgMTEuNjgwNiAtMC4wOTc2MzExIDExLjA0NzQgMC4yOTI4OTMgMTAuNjU2OUw0LjU4NTc5IDYuMzY0MDFMMC4yOTI4OTQgMi4wNzExMkMtMC4wOTc2MzA2IDEuNjgwNiAtMC4wOTc2MzA2IDEuMDQ3NDMgMC4yOTI4OTQgMC42NTY5MDdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjg0Ii8+Cjwvc3ZnPgo=);\n background-position: center center;\n background-repeat: no-repeat;\n border: 0;\n cursor: pointer;\n padding: 16px;\n position: absolute;\n right: 12px;\n top: 12px;\n}\n"; exports.CSS_STYLES = CSS_STYLES; -},{}],61:[function(require,module,exports){ +},{}],59:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18148,7 +18048,7 @@ function isFormLikelyToBeUsedAsPageWrapper(form) { return formChildrenPercentage > 50; } -},{"./Form/matching.js":43}],62:[function(require,module,exports){ +},{"./Form/matching.js":41}],60:[function(require,module,exports){ "use strict"; require("./requestIdleCallback.js"); @@ -18183,7 +18083,7 @@ var _autofillUtils = require("./autofill-utils.js"); } })(); -},{"./DeviceInterface.js":22,"./autofill-utils.js":61,"./requestIdleCallback.js":73}],63:[function(require,module,exports){ +},{"./DeviceInterface.js":20,"./autofill-utils.js":59,"./requestIdleCallback.js":71}],61:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18271,7 +18171,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],64:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18289,7 +18189,7 @@ const constants = { }; exports.constants = constants; -},{}],65:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18779,7 +18679,7 @@ class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; -},{"../../../packages/device-api":14,"./validators.zod.js":66}],66:[function(require,module,exports){ +},{"../../../packages/device-api":10,"./validators.zod.js":64}],64:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19285,7 +19185,7 @@ const apiSchema = _zod.z.object({ exports.apiSchema = apiSchema; -},{"zod":12}],67:[function(require,module,exports){ +},{"zod":8}],65:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19326,7 +19226,7 @@ class GetAlias extends _index.DeviceApiCall { exports.GetAlias = GetAlias; -},{"../../packages/device-api/index.js":14,"./__generated__/validators.zod.js":66}],68:[function(require,module,exports){ +},{"../../packages/device-api/index.js":10,"./__generated__/validators.zod.js":64}],66:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19484,7 +19384,7 @@ function androidSpecificAvailableInputTypes(globalConfig) { }; } -},{"../../../packages/device-api/index.js":14,"../__generated__/deviceApiCalls.js":65}],69:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../__generated__/deviceApiCalls.js":63}],67:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19492,7 +19392,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.AppleTransport = void 0; -var _contentScopeUtils = require("@duckduckgo/content-scope-utils"); +var _messaging = require("../../../packages/messaging/messaging.js"); var _index = require("../../../packages/device-api/index.js"); @@ -19503,12 +19403,12 @@ class AppleTransport extends _index.DeviceApiTransport { constructor(globalConfig) { super(); this.config = globalConfig; - const webkitConfig = new _contentScopeUtils.WebkitMessagingConfig({ + const webkitConfig = new _messaging.WebkitMessagingConfig({ hasModernWebkitAPI: this.config.hasModernWebkitAPI, webkitMessageHandlerNames: this.config.webkitMessageHandlerNames, secret: this.config.secret }); - this.messaging = new _contentScopeUtils.Messaging(webkitConfig); + this.messaging = new _messaging.Messaging(webkitConfig); } async send(deviceApiCall) { @@ -19520,7 +19420,7 @@ class AppleTransport extends _index.DeviceApiTransport { return this.messaging.notify(deviceApiCall.method, deviceApiCall.params || undefined); } } catch (e) { - if (e instanceof _contentScopeUtils.MissingHandler) { + if (e instanceof _messaging.MissingHandler) { if (this.config.isDDGTestMode) { console.log('MissingWebkitHandler error for:', deviceApiCall.method); } @@ -19560,7 +19460,7 @@ function appleSpecificRuntimeConfiguration(globalConfig) { }; } -},{"../../../packages/device-api/index.js":14,"../__generated__/deviceApiCalls.js":65,"@duckduckgo/content-scope-utils":2}],70:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../../../packages/messaging/messaging.js":13,"../__generated__/deviceApiCalls.js":63}],68:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19732,7 +19632,7 @@ async function extensionSpecificSetIncontextSignupPermanentlyDismissedAtCall(par }); } -},{"../../../packages/device-api/index.js":14,"../../Settings.js":50,"../../autofill-utils.js":61,"../__generated__/deviceApiCalls.js":65}],71:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10,"../../Settings.js":48,"../../autofill-utils.js":59,"../__generated__/deviceApiCalls.js":63}],69:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19786,7 +19686,7 @@ function createTransport(globalConfig) { return new _extensionTransport.ExtensionTransport(globalConfig); } -},{"./android.transport.js":68,"./apple.transport.js":69,"./extension.transport.js":70,"./windows.transport.js":72}],72:[function(require,module,exports){ +},{"./android.transport.js":66,"./apple.transport.js":67,"./extension.transport.js":68,"./windows.transport.js":70}],70:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19886,7 +19786,7 @@ function waitForWindowsResponse(responseId, options) { }); } -},{"../../../packages/device-api/index.js":14}],73:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":10}],71:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -19934,4 +19834,4 @@ window.cancelIdleCallback = window.cancelIdleCallback || function (id) { var _default = {}; exports.default = _default; -},{}]},{},[62]); +},{}]},{},[60]); diff --git a/swift-package/Resources/assets/autofill.js b/swift-package/Resources/assets/autofill.js index 36465880d..24c9967c9 100644 --- a/swift-package/Resources/assets/autofill.js +++ b/swift-package/Resources/assets/autofill.js @@ -58,1159 +58,1059 @@ function processConfig(data, userList, preferences) { Object.defineProperty(exports, "__esModule", { value: true }); - -var _messaging = require("./messaging.js"); - -Object.keys(_messaging).forEach(function (key) { - if (key === "default" || key === "__esModule") return; - if (key in exports && exports[key] === _messaging[key]) return; - Object.defineProperty(exports, key, { - enumerable: true, - get: function () { - return _messaging[key]; - } - }); +Object.defineProperty(exports, "DeviceApi", { + enumerable: true, + get: function () { + return _deviceApi.DeviceApi; + } }); - -},{"./messaging.js":3}],3:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true +Object.defineProperty(exports, "DeviceApiCall", { + enumerable: true, + get: function () { + return _deviceApiCall.DeviceApiCall; + } }); -exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; -Object.defineProperty(exports, "WebkitMessagingConfig", { +Object.defineProperty(exports, "DeviceApiTransport", { enumerable: true, get: function () { - return _webkit.WebkitMessagingConfig; + return _deviceApi.DeviceApiTransport; + } +}); +Object.defineProperty(exports, "createNotification", { + enumerable: true, + get: function () { + return _deviceApiCall.createNotification; + } +}); +Object.defineProperty(exports, "createRequest", { + enumerable: true, + get: function () { + return _deviceApiCall.createRequest; } }); -Object.defineProperty(exports, "WindowsMessagingConfig", { +Object.defineProperty(exports, "validate", { enumerable: true, get: function () { - return _windows.WindowsMessagingConfig; + return _deviceApiCall.validate; } }); -var _windows = require("./messaging/windows.js"); +var _deviceApiCall = require("./lib/device-api-call.js"); -var _webkit = require("./messaging/webkit.js"); +var _deviceApi = require("./lib/device-api.js"); -/** - * @module Messaging - * - * @description - * - * An abstraction for communications between JavaScript and host platforms. - * - * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) - * 2) Then use that to get an instance of the Messaging utility which allows - * you to send and receive data in a unified way - * 3) Each platform implements {@link MessagingTransport} along with its own Configuration - * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} - * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} - * - * @example Webkit Messaging - * - * ```js - * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // This config would be injected into the UserScript - * const injectedConfig = { - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }; - * - * // Then use that config to construct platform-specific configuration - * const config = new WebkitMessagingConfig(injectedConfig); - * - * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 - * const messaging = new Messaging(config); - * messaging.notify("hello world!", {foo: "bar"}) - * - * ``` - * - * @example Windows Messaging - * - * ```js - * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" - * - * // Messaging on Windows is namespaced, so you can create multiple messaging instances - * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); - * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); - * - * const autofillMessaging = new Messaging(autofillConfig); - * const debugMessaging = new Messaging(debugConfig); - * - * // Now send messages to both features as needed 🚀 - * autofillMessaging.notify("storeFormData", { "username": "dax" }) - * debugMessaging.notify("pageLoad", { time: window.performance.now() }) - * ``` - */ +},{"./lib/device-api-call.js":3,"./lib/device-api.js":4}],3:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; +exports.createDeviceApiCall = createDeviceApiCall; +exports.createNotification = void 0; +exports.createRequest = createRequest; +exports.validate = validate; + +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** - * @implements {MessagingTransport} + * This roughly follows https://www.jsonrpc.org/specification + * @template {import("zod").ZodType} Params=import("zod").ZodType + * @template {import("zod").ZodType} Result=import("zod").ZodType */ -class Messaging { - /** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - */ - constructor(config) { - this.transport = getTransport(config); - } - /** - * Send a 'fire-and-forget' message. - * @throws - * {@link MissingHandler} - * - * @example - * - * ``` - * const messaging = new Messaging(config) - * messaging.notify("foo", {bar: "baz"}) - * ``` - * @param {string} name - * @param {Record} [data] - */ - +class DeviceApiCall { + /** @type {string} */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.transport.notify(name, data); - } /** - * Send a request, and wait for a response - * @throws - * {@link MissingHandler} - * - * @example - * ``` - * const messaging = new Messaging(config) - * const response = await messaging.request("foo", {bar: "baz"}) - * ``` - * - * @param {string} name - * @param {Record} [data] - * @return {Promise} + * An optional 'id' - used to indicate if a request requires a response. + * @type {string|null} */ + /** @type {Params | null | undefined} */ - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.transport.request(name, data); - } - -} -/** - * @interface - */ + /** @type {Result | null | undefined} */ + /** @type {import("zod").infer} */ -exports.Messaging = Messaging; + /** + * This is a carve-out for legacy messages that are not typed yet. + * If you set this to 'true', then the response will not be checked to conform + * to any shape + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} + */ -class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} + * New messages should be in a particular format, eg: { success: T }, + * but you can set this to false if you want to access the result as-is, + * without any unwrapping logic + * @deprecated this is here to aid migration, should be removed ASAP + * @type {boolean} */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error("must implement 'notify'"); - } + /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} + * @param {import("zod").infer} data */ - // @ts-ignore - ignoring a no-unused ts error, this is only an interface. - // eslint-disable-next-line @typescript-eslint/no-unused-vars + constructor(data) { + _defineProperty(this, "method", 'unknown'); + _defineProperty(this, "id", null); - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); - } + _defineProperty(this, "paramsValidator", null); -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + _defineProperty(this, "resultValidator", null); + _defineProperty(this, "params", void 0); -exports.MessagingTransport = MessagingTransport; + _defineProperty(this, "throwOnResultKeysMissing", true); -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); - } + _defineProperty(this, "unwrapResult", true); - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + this.params = data; } + /** + * @returns {import("zod").infer|undefined} + */ - throw new Error('unreachable'); -} -/** - * Thrown when a handler cannot be found - */ + validateParams() { + if (this.params === undefined) { + return undefined; + } -class MissingHandler extends Error { + this._validate(this.params, this.paramsValidator); + + return this.params; + } /** - * @param {string} message - * @param {string} handlerName + * @param {any|null} incoming + * @returns {import("zod").infer} */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; - } - -} -/** - * Some re-exports for convenience - */ -exports.MissingHandler = MissingHandler; + validateResult(incoming) { + this._validate(incoming, this.resultValidator); -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + if (!incoming) { + return incoming; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + if (!this.unwrapResult) { + return incoming; + } -var _messaging = require("../messaging.js"); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + if ('success' in incoming) { + return incoming.success; + } -/** - * @example - * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` - * - * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following - * would occur: - * - * ```js - * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); - * const response = JSON.parse(json) - * ``` - * - * @example - * On macOS 10 however, the process is a little more involved. A method will be appended to `window` - * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow - * as being something along the lines of: - * - * ```js - * // add the window method - * window["_0123456"] = (response) => { - * // decrypt `response` and deliver the result to the caller here - * // then remove the temporary method - * delete window["_0123456"] - * }; - * - * // send the data + `messageHanding` values - * window.webkit.messageHandlers.foo.postMessage({ - * bar: "baz", - * messagingHandling: { - * methodName: "_0123456", - * secret: "super-secret", - * key: [1, 2, 45, 2], - * iv: [34, 4, 43], - * } - * }); - * - * // later in swift, the following JavaScript snippet will be executed - * (() => { - * window["_0123456"]({ - * ciphertext: [12, 13, 4], - * tag: [3, 5, 67, 56] - * }) - * })() - * ``` - * @implements {MessagingTransport} - */ -class WebkitMessagingTransport { - /** @type {WebkitMessagingConfig} */ - - /** - * @param {WebkitMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); - - _defineProperty(this, "globals", void 0); - - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); - - this.config = config; - this.globals = captureGlobals(); + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + } + } - if (!this.config.hasModernWebkitAPI) { - this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); } + + return incoming; } /** - * Sends message to the webkit layer (fire and forget) - * @param {String} handler - * @param {*} data - * @internal + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private */ - wkSend(handler) { - var _this$globals$window$, _this$globals$window$2; - - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + _validate(data, validator) { + if (!validator) return data; - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret + if (!result) { + throw new Error('unreachable, data failure', data); } - }; - if (!this.config.hasModernWebkitAPI) { - if (!(handler in this.globals.capturedWebkitHandlers)) { - throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); - } else { - return this.globals.capturedWebkitHandlers[handler](outgoing); + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } } } - - return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * Sends message to the webkit layer and waits for the specified response - * @param {String} handler - * @param {*} data - * @returns {Promise<*>} - * @internal + * @param {import('zod').ZodIssue[]} errors */ - async wkSendAndWait(handler) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (this.config.hasModernWebkitAPI) { - const response = await this.wkSend(handler, data); - return this.globals.JSONparse(response || '{}'); - } - - try { - const randMethodName = this.createRandMethodName(); - const key = await this.createRandKey(); - const iv = this.createRandIv(); - const { - ciphertext, - tag - } = await new this.globals.Promise(( - /** @type {any} */ - resolve) => { - this.generateRandomMethod(randMethodName, resolve); - data.messageHandling = new SecureMessagingParams({ - methodName: randMethodName, - secret: this.config.secret, - key: this.globals.Arrayfrom(key), - iv: this.globals.Arrayfrom(iv) - }); - this.wkSend(handler, data); - }); - const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); - const decrypted = await this.decrypt(cipher, key, iv); - return this.globals.JSONparse(decrypted || '{}'); - } catch (e) { - // re-throw when the error is just a 'MissingHandler' - if (e instanceof _messaging.MissingHandler) { - throw e; - } else { - console.error('decryption failed', e); - console.error(e); - return { - error: e - }; - } - } + throwError(errors) { + const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); + throw error; } /** - * @param {string} name - * @param {Record} [data] + * Use this helper for creating stand-in response messages that are typed correctly. + * + * @examples + * + * ```js + * const msg = new Message(); + * const response = msg.response({}) // <-- This argument will be typed correctly + * ``` + * + * @param {import("zod").infer} response + * @returns {import("zod").infer} */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); + result(response) { + return response; } /** - * @param {string} name - * @param {Record} [data] + * @returns {import("zod").infer} */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - return this.wkSendAndWait(name, data); + preResultValidation(response) { + return response; } - /** - * Generate a random method name and adds it to the global scope - * The native layer will use this method to send the response - * @param {string | number} randomMethodName - * @param {Function} callback - */ +} - generateRandomMethod(randomMethodName, callback) { - var _this = this; +exports.DeviceApiCall = DeviceApiCall; - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. - delete _this.globals.window[randomMethodName]; - } - }); - } +exports.DeviceApiCallError = DeviceApiCallError; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } +class SchemaValidationError extends Error { + constructor() { + super(...arguments); - createRandMethodName() { - return '_' + this.randomString(); + _defineProperty(this, "validationErrors", []); } + /** - * @type {{name: string, length: number}} + * @param {import("zod").ZodIssue[]} errors + * @param {string} name + * @returns {SchemaValidationError} */ + static fromZodErrors(errors, name) { + const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; + function log(issue) { + switch (issue.code) { + case 'invalid_literal': + case 'invalid_type': + { + console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); + break; + } - /** - * @returns {Promise} - */ - async createRandKey() { - const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); - const exportedKey = await this.globals.exportKey('raw', key); - return new this.globals.Uint8Array(exportedKey); - } - /** - * @returns {Uint8Array} - */ + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } + break; + } - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ + default: + { + console.log(name, 'other issue:', issue); + } + } + } + for (let error of errors) { + log(error); + } - async decrypt(ciphertext, key, iv) { - const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); - const algo = { - name: 'AES-GCM', - iv - }; - let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); - let dec = new this.globals.TextDecoder(); - return dec.decode(decrypted); + const message = [heading, 'please see the details above'].join('\n '); + const error = new SchemaValidationError(message); + error.validationErrors = errors; + return error; } - /** - * When required (such as on macos 10.x), capture the `postMessage` method on - * each webkit messageHandler - * - * @param {string[]} handlerNames - */ +} +/** + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. + * + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} + */ - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; - - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; +exports.SchemaValidationError = SchemaValidationError; - /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ - const original = handlers[webkitMessageHandlerName]; - const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); - this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; - delete handlers[webkitMessageHandlerName].postMessage; - } - } - } +function createDeviceApiCall(method, params) { + let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; + let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + /** @type {DeviceApiCall} */ + const deviceApiCall = new DeviceApiCall(params); + deviceApiCall.paramsValidator = paramsValidator; + deviceApiCall.resultValidator = resultValidator; + deviceApiCall.method = method; + deviceApiCall.throwOnResultKeysMissing = false; + deviceApiCall.unwrapResult = false; + return deviceApiCall; } /** - * Use this configuration to create an instance of {@link Messaging} for WebKit - * - * ```js - * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. * - * const config = new WebkitMessagingConfig({ - * hasModernWebkitAPI: true, - * webkitMessageHandlerNames: ["foo", "bar", "baz"], - * secret: "dax", - * }); + * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string + * so that transports know that it expects a response. * - * const messaging = new Messaging(config) - * const resp = await messaging.request("debugConfig") - * ``` + * @template {import("zod").ZodType} Params + * @template {import("zod").ZodType} Result + * @param {string} method + * @param {import("zod").infer} [params] + * @param {string} [id] + * @param {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} */ -exports.WebkitMessagingTransport = WebkitMessagingTransport; +function createRequest(method, params) { + let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; + let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; + let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; + const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); + call.id = id; + return call; +} -class WebkitMessagingConfig { - /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ - constructor(params) { - /** - * Whether or not the current WebKit Platform supports secure messaging - * by default (eg: macOS 11+) - */ - this.hasModernWebkitAPI = params.hasModernWebkitAPI; - /** - * A list of WebKit message handler names that a user script can send - */ +const createNotification = createDeviceApiCall; +/** + * Validate any arbitrary data with any Zod validator + * + * @template {import("zod").ZodType} Validator + * @param {any} data + * @param {Validator | null} [validator] + * @returns {import("zod").infer} + */ - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ +exports.createNotification = createNotification; - this.secret = params.secret; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + if (validator) { + return validator.parse(data); } + return data; } -/** - * This is the additional payload that gets appended to outgoing messages. - * It's used in the Swift side to encrypt the response that comes back - */ +},{}],4:[function(require,module,exports){ +"use strict"; -exports.WebkitMessagingConfig = WebkitMessagingConfig; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; -class SecureMessagingParams { +function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } + +/** + * Platforms should only need to implement this `send` method + */ +class DeviceApiTransport { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} */ - constructor(params) { - /** - * The method that's been appended to `window` to be called later - */ - this.methodName = params.methodName; - /** - * The secret used to ensure message sender validity - */ - - this.secret = params.secret; - /** - * The CipherKey as number[] - */ - - this.key = params.key; - /** - * The Initial Vector as number[] - */ - - this.iv = params.iv; + async send(_deviceApiCall, _options) { + return undefined; } } /** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this + * This is the base Sender class that platforms can will implement. + * + * Note: The 'handle' method must be implemented, unless you also implement 'send' + * + * @typedef CallOptions + * @property {AbortSignal} [signal] */ -exports.SecureMessagingParams = SecureMessagingParams; +exports.DeviceApiTransport = DeviceApiTransport; -function captureGlobals() { - // Creat base with null prototype - return { - window, - // Methods must be bound to their interface, otherwise they throw Illegal invocation - encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), - decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), - generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), - exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), - importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), - getRandomValues: window.crypto.getRandomValues.bind(window.crypto), - TextEncoder, - TextDecoder, - Uint8Array, - Uint16Array, - Uint32Array, - JSONstringify: window.JSON.stringify, - JSONparse: window.JSON.parse, - Arrayfrom: window.Array.from, - Promise: window.Promise, - ObjectDefineProperty: window.Object.defineProperty, - addEventListener: window.addEventListener.bind(window), +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ + + + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); + } + /** + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} + */ + + + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); + } - /** @type {Record} */ - capturedWebkitHandlers: {} - }; } -},{"../messaging.js":3}],5:[function(require,module,exports){ +exports.DeviceApi = DeviceApi; + +},{}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { + enumerable: true, + get: function () { + return _webkit.WebkitMessagingConfig; + } +}); -var _messaging = require("../messaging.js"); +var _webkit = require("./webkit.js"); -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } +/** + * @module Messaging + * + * @description + * + * An abstraction for communications between JavaScript and host platforms. + * + * 1) First you construct your platform-specific configuration (eg: {@link WebkitMessagingConfig}) + * 2) Then use that to get an instance of the Messaging utility which allows + * you to send and receive data in a unified way + * 3) Each platform implements {@link MessagingTransport} along with its own Configuration + * - For example, to learn what configuration is required for Webkit, see: {@link "Webkit Messaging".WebkitMessagingConfig} + * - Or, to learn about how messages are sent and received in Webkit, see {@link "Webkit Messaging".WebkitMessagingTransport} + * + * @example Webkit Messaging + * + * ```js + * import { Messaging, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // This config would be injected into the UserScript + * const injectedConfig = { + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }; + * + * // Then use that config to construct platform-specific configuration + * const config = new WebkitMessagingConfig(injectedConfig); + * + * // finally, get an instance of Messaging and start sending messages in a unified way 🚀 + * const messaging = new Messaging(config); + * messaging.notify("hello world!", {foo: "bar"}) + * + * ``` + * + * @example Windows Messaging + * + * ```js + * import { Messaging, WindowsMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" + * + * // Messaging on Windows is namespaced, so you can create multiple messaging instances + * const autofillConfig = new WindowsMessagingConfig({ featureName: "Autofill" }); + * const debugConfig = new WindowsMessagingConfig({ featureName: "Debugging" }); + * + * const autofillMessaging = new Messaging(autofillConfig); + * const debugMessaging = new Messaging(debugConfig); + * + * // Now send messages to both features as needed 🚀 + * autofillMessaging.notify("storeFormData", { "username": "dax" }) + * debugMessaging.notify("pageLoad", { time: window.performance.now() }) + * ``` + */ /** * @implements {MessagingTransport} */ -class WindowsMessagingTransport { +class Messaging { /** - * @param {WindowsMessagingConfig} config - */ + * @param {WebkitMessagingConfig} config + */ constructor(config) { - _defineProperty(this, "config", void 0); - - this.config = config; + this.transport = getTransport(config); } /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + * Send a 'fire-and-forget' message. + * @throws {Error} + * {@link MissingHandler} + * + * @example + * + * ``` + * const messaging = new Messaging(config) + * messaging.notify("foo", {bar: "baz"}) + * ``` + * @param {string} name + * @param {Record} [data] + */ notify(name) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); + this.transport.notify(name, data); } /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars + * Send a request, and wait for a response + * @throws {Error} + * {@link MissingHandler} + * + * @example + * ``` + * const messaging = new Messaging(config) + * const response = await messaging.request("foo", {bar: "baz"}) + * ``` + * + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ request(name) { let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - let opts = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; - throw new Error('todo: implement request for windows'); + return this.transport.request(name, data); } } +/** + * @interface + */ -exports.WindowsMessagingTransport = WindowsMessagingTransport; -class WindowsMessagingConfig { +exports.Messaging = Messaging; + +class MessagingTransport { /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; + * @param {string} name + * @param {Record} [data] + * @returns {void} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error("must implement 'notify'"); + } + /** + * @param {string} name + * @param {Record} [data] + * @return {Promise} + */ + // @ts-ignore - ignoring a no-unused ts error, this is only an interface. + + + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); } } +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ -exports.WindowsMessagingConfig = WindowsMessagingConfig; -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; +exports.MessagingTransport = MessagingTransport; -Object.defineProperty(exports, "__esModule", { - value: true -}); -Object.defineProperty(exports, "DeviceApi", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApi; - } -}); -Object.defineProperty(exports, "DeviceApiCall", { - enumerable: true, - get: function () { - return _deviceApiCall.DeviceApiCall; - } -}); -Object.defineProperty(exports, "DeviceApiTransport", { - enumerable: true, - get: function () { - return _deviceApi.DeviceApiTransport; - } -}); -Object.defineProperty(exports, "createNotification", { - enumerable: true, - get: function () { - return _deviceApiCall.createNotification; - } -}); -Object.defineProperty(exports, "createRequest", { - enumerable: true, - get: function () { - return _deviceApiCall.createRequest; +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); } -}); -Object.defineProperty(exports, "validate", { - enumerable: true, - get: function () { - return _deviceApiCall.validate; + + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ + + +class MissingHandler extends Error { + /** + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; } -}); -var _deviceApiCall = require("./lib/device-api-call.js"); +} +/** + * Some re-exports for convenience + */ -var _deviceApi = require("./lib/device-api.js"); -},{"./lib/device-api-call.js":7,"./lib/device-api.js":8}],7:[function(require,module,exports){ +exports.MissingHandler = MissingHandler; + +},{"./webkit.js":6}],6:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.SchemaValidationError = exports.DeviceApiCallError = exports.DeviceApiCall = void 0; -exports.createDeviceApiCall = createDeviceApiCall; -exports.createNotification = void 0; -exports.createRequest = createRequest; -exports.validate = validate; +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; + +var _messaging = require("./messaging.js"); function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @typedef {import("./messaging").MessagingTransport} MessagingTransport */ -class DeviceApiCall { - /** @type {string} */ - - /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} - */ - - /** @type {Params | null | undefined} */ - - /** @type {Result | null | undefined} */ - - /** @type {import("zod").infer} */ - - /** - * This is a carve-out for legacy messages that are not typed yet. - * If you set this to 'true', then the response will not be checked to conform - * to any shape - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ - /** - * New messages should be in a particular format, eg: { success: T }, - * but you can set this to false if you want to access the result as-is, - * without any unwrapping logic - * @deprecated this is here to aid migration, should be removed ASAP - * @type {boolean} - */ +/** + * @example + * On macOS 11+, this will just call through to `window.webkit.messageHandlers.x.postMessage` + * + * Eg: for a `foo` message defined in Swift that accepted the payload `{"bar": "baz"}`, the following + * would occur: + * + * ```js + * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" }); + * const response = JSON.parse(json) + * ``` + * + * @example + * On macOS 10 however, the process is a little more involved. A method will be appended to `window` + * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow + * as being something along the lines of: + * + * ```js + * // add the window method + * window["_0123456"] = (response) => { + * // decrypt `response` and deliver the result to the caller here + * // then remove the temporary method + * delete window["_0123456"] + * }; + * + * // send the data + `messageHanding` values + * window.webkit.messageHandlers.foo.postMessage({ + * bar: "baz", + * messagingHandling: { + * methodName: "_0123456", + * secret: "super-secret", + * key: [1, 2, 45, 2], + * iv: [34, 4, 43], + * } + * }); + * + * // later in swift, the following JavaScript snippet will be executed + * (() => { + * window["_0123456"]({ + * ciphertext: [12, 13, 4], + * tag: [3, 5, 67, 56] + * }) + * })() + * ``` + * @implements {MessagingTransport} + */ +class WebkitMessagingTransport { + /** @type {WebkitMessagingConfig} */ /** - * @param {import("zod").infer} data + * @param {WebkitMessagingConfig} config */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - - _defineProperty(this, "resultValidator", null); - - _defineProperty(this, "params", void 0); - - _defineProperty(this, "throwOnResultKeysMissing", true); + constructor(config) { + _defineProperty(this, "config", void 0); - _defineProperty(this, "unwrapResult", true); + _defineProperty(this, "globals", void 0); - this.params = data; - } - /** - * @returns {import("zod").infer|undefined} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - validateParams() { - if (this.params === undefined) { - return undefined; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - this._validate(this.params, this.paramsValidator); - - return this.params; } /** - * @param {any|null} incoming - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - validateResult(incoming) { - this._validate(incoming, this.resultValidator); - - if (!incoming) { - return incoming; - } - - if (!this.unwrapResult) { - return incoming; - } + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if ('success' in incoming) { - return incoming.success; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); } - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } - } + }; - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + if (!(handler in this.globals.capturedWebkitHandlers)) { + throw new _messaging.MissingHandler("cannot continue, method ".concat(handler, " not captured on macos < 11"), handler); + } else { + return this.globals.capturedWebkitHandlers[handler](outgoing); + } } - return incoming; + return (_this$globals$window$ = (_this$globals$window$2 = this.globals.window.webkit.messageHandlers[handler]).postMessage) === null || _this$globals$window$ === void 0 ? void 0 : _this$globals$window$.call(_this$globals$window$2, outgoing); } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - _validate(data, validator) { - if (!validator) return data; - - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + try { + const randMethodName = this.createRandMethodName(); + const key = await this.createRandKey(); + const iv = this.createRandIv(); + const { + ciphertext, + tag + } = await new this.globals.Promise(( + /** @type {any} */ + resolve) => { + this.generateRandomMethod(randMethodName, resolve); + data.messageHandling = new SecureMessagingParams({ + methodName: randMethodName, + secret: this.config.secret, + key: this.globals.Arrayfrom(key), + iv: this.globals.Arrayfrom(iv) + }); + this.wkSend(handler, data); + }); + const cipher = new this.globals.Uint8Array([...ciphertext, ...tag]); + const decrypted = await this.decrypt(cipher, key, iv); + return this.globals.JSONparse(decrypted || '{}'); + } catch (e) { + // re-throw when the error is just a 'MissingHandler' + if (e instanceof _messaging.MissingHandler) { + throw e; + } else { + console.error('decryption failed', e); + console.error(e); + return { + error: e + }; } } } /** - * @param {import('zod').ZodIssue[]} errors + * @param {string} name + * @param {Record} [data] */ - throwError(errors) { - const error = SchemaValidationError.fromZodErrors(errors, this.constructor.name); - throw error; + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } /** - * Use this helper for creating stand-in response messages that are typed correctly. - * - * @examples - * - * ```js - * const msg = new Message(); - * const response = msg.response({}) // <-- This argument will be typed correctly - * ``` - * - * @param {import("zod").infer} response - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - result(response) { - return response; + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.wkSendAndWait(name, data); } /** - * @returns {import("zod").infer} + * Generate a random method name and adds it to the global scope + * The native layer will use this method to send the response + * @param {string | number} randomMethodName + * @param {Function} callback */ - preResultValidation(response) { - return response; - } + generateRandomMethod(randomMethodName, callback) { + var _this = this; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -exports.DeviceApiCall = DeviceApiCall; + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + delete _this.globals.window[randomMethodName]; + } + }); + } + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.DeviceApiCallError = DeviceApiCallError; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -class SchemaValidationError extends Error { - constructor() { - super(...arguments); - _defineProperty(this, "validationErrors", []); + /** + * @returns {Promise} + */ + async createRandKey() { + const key = await this.globals.generateKey(this.algoObj, true, ['encrypt', 'decrypt']); + const exportedKey = await this.globals.exportKey('raw', key); + return new this.globals.Uint8Array(exportedKey); } + /** + * @returns {Uint8Array} + */ + + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } /** - * @param {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ + + + async decrypt(ciphertext, key, iv) { + const cryptoKey = await this.globals.importKey('raw', key, 'AES-GCM', false, ['decrypt']); + const algo = { + name: 'AES-GCM', + iv + }; + let decrypted = await this.globals.decrypt(algo, cryptoKey, ciphertext); + let dec = new this.globals.TextDecoder(); + return dec.decode(decrypted); + } + /** + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - static fromZodErrors(errors, name) { - const heading = "".concat(errors.length, " SchemaValidationError(s) errors for ") + name; - function log(issue) { - switch (issue.code) { - case 'invalid_literal': - case 'invalid_type': - { - console.log("".concat(name, ". Path: '").concat(issue.path.join('.'), "', Error: '").concat(issue.message, "'")); - break; - } - case 'invalid_union': - { - for (let unionError of issue.unionErrors) { - for (let issue1 of unionError.issues) { - log(issue1); - } - } + captureWebkitHandlers(handlerNames) { + const handlers = window.webkit.messageHandlers; + if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - break; - } + for (let webkitMessageHandlerName of handlerNames) { + var _handlers$webkitMessa; - default: - { - console.log(name, 'other issue:', issue); - } - } - } + if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { + var _handlers$webkitMessa2; - for (let error of errors) { - log(error); + /** + * `bind` is used here to ensure future calls to the captured + * `postMessage` have the correct `this` context + */ + const original = handlers[webkitMessageHandlerName]; + const bound = (_handlers$webkitMessa2 = handlers[webkitMessageHandlerName].postMessage) === null || _handlers$webkitMessa2 === void 0 ? void 0 : _handlers$webkitMessa2.bind(original); + this.globals.capturedWebkitHandlers[webkitMessageHandlerName] = bound; + delete handlers[webkitMessageHandlerName].postMessage; + } } - - const message = [heading, 'please see the details above'].join('\n '); - const error = new SchemaValidationError(message); - error.validationErrors = errors; - return error; } } /** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} - */ - - -exports.SchemaValidationError = SchemaValidationError; - -function createDeviceApiCall(method, params) { - let paramsValidator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null; - let resultValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - - /** @type {DeviceApiCall} */ - const deviceApiCall = new DeviceApiCall(params); - deviceApiCall.paramsValidator = paramsValidator; - deviceApiCall.resultValidator = resultValidator; - deviceApiCall.method = method; - deviceApiCall.throwOnResultKeysMissing = false; - deviceApiCall.unwrapResult = false; - return deviceApiCall; -} -/** - * Creates an instance of `DeviceApiCall` from only a name and 'params' - * and optional validators. Use this to help migrate existing messages. + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * Note: This creates a regular DeviceApiCall, but adds the 'id' as a string - * so that transports know that it expects a response. + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); * - * @template {import("zod").ZodType} Params - * @template {import("zod").ZodType} Result - * @param {string} method - * @param {import("zod").infer} [params] - * @param {string} [id] - * @param {Params|null} [paramsValidator] - * @param {Result|null} [resultValidator] - * @returns {DeviceApiCall} + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -function createRequest(method, params) { - let id = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'n/a'; - let paramsValidator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null; - let resultValidator = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null; - const call = createDeviceApiCall(method, params, paramsValidator, resultValidator); - call.id = id; - return call; -} - -const createNotification = createDeviceApiCall; -/** - * Validate any arbitrary data with any Zod validator - * - * @template {import("zod").ZodType} Validator - * @param {any} data - * @param {Validator | null} [validator] - * @returns {import("zod").infer} - */ +exports.WebkitMessagingTransport = WebkitMessagingTransport; -exports.createNotification = createNotification; +class WebkitMessagingConfig { + /** + * @param {object} params + * @param {boolean} params.hasModernWebkitAPI + * @param {string[]} params.webkitMessageHandlerNames + * @param {string} params.secret + */ + constructor(params) { + /** + * Whether or not the current WebKit Platform supports secure messaging + * by default (eg: macOS 11+) + */ + this.hasModernWebkitAPI = params.hasModernWebkitAPI; + /** + * A list of WebKit message handler names that a user script can send + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; + /** + * A string provided by native platforms to be sent with future outgoing + * messages + */ - if (validator) { - return validator.parse(data); + this.secret = params.secret; } - return data; } - -},{}],8:[function(require,module,exports){ -"use strict"; - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; - -function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } - /** - * Platforms should only need to implement this `send` method + * This is the additional payload that gets appended to outgoing messages. + * It's used in the Swift side to encrypt the response that comes back */ -class DeviceApiTransport { - /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} - */ - async send(_deviceApiCall, _options) { - return undefined; - } -} -/** - * This is the base Sender class that platforms can will implement. - * - * Note: The 'handle' method must be implemented, unless you also implement 'send' - * - * @typedef CallOptions - * @property {AbortSignal} [signal] - */ +exports.WebkitMessagingConfig = WebkitMessagingConfig; -exports.DeviceApiTransport = DeviceApiTransport; +class SecureMessagingParams { + /** + * @param {object} params + * @param {string} params.methodName + * @param {string} params.secret + * @param {number[]} params.key + * @param {number[]} params.iv + */ + constructor(params) { + /** + * The method that's been appended to `window` to be called later + */ + this.methodName = params.methodName; + /** + * The secret used to ensure message sender validity + */ -class DeviceApi { - /** @type {DeviceApiTransport} */ + this.secret = params.secret; + /** + * The CipherKey as number[] + */ - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); + this.key = params.key; + /** + * The Initial Vector as number[] + */ - this.transport = transport; + this.iv = params.iv; } - /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} - */ +} +/** + * Capture some globals used for messaging handling to prevent page + * scripts from tampering with this + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); - } - /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} - */ +exports.SecureMessagingParams = SecureMessagingParams; - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); - } +function captureGlobals() { + // Creat base with null prototype + return { + window, + // Methods must be bound to their interface, otherwise they throw Illegal invocation + encrypt: window.crypto.subtle.encrypt.bind(window.crypto.subtle), + decrypt: window.crypto.subtle.decrypt.bind(window.crypto.subtle), + generateKey: window.crypto.subtle.generateKey.bind(window.crypto.subtle), + exportKey: window.crypto.subtle.exportKey.bind(window.crypto.subtle), + importKey: window.crypto.subtle.importKey.bind(window.crypto.subtle), + getRandomValues: window.crypto.getRandomValues.bind(window.crypto), + TextEncoder, + TextDecoder, + Uint8Array, + Uint16Array, + Uint32Array, + JSONstringify: window.JSON.stringify, + JSONparse: window.JSON.parse, + Arrayfrom: window.Array.from, + Promise: window.Promise, + ObjectDefineProperty: window.Object.defineProperty, + addEventListener: window.addEventListener.bind(window), + /** @type {Record} */ + capturedWebkitHandlers: {} + }; } -exports.DeviceApi = DeviceApi; - -},{}],9:[function(require,module,exports){ +},{"./messaging.js":5}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1359,7 +1259,7 @@ function _safeHostname(inputHostname) { } } -},{"./lib/apple.password.js":10,"./lib/constants.js":11,"./lib/rules-parser.js":12}],10:[function(require,module,exports){ +},{"./lib/apple.password.js":8,"./lib/constants.js":9,"./lib/rules-parser.js":10}],8:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1983,7 +1883,7 @@ exports.Password = Password; _defineProperty(Password, "defaults", defaults); -},{"./constants.js":11,"./rules-parser.js":12}],11:[function(require,module,exports){ +},{"./constants.js":9,"./rules-parser.js":10}],9:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2004,7 +1904,7 @@ const constants = { }; exports.constants = constants; -},{}],12:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2737,7 +2637,7 @@ function parsePasswordRules(input, formatRulesForMinifiedVersion) { return newPasswordRules; } -},{}],13:[function(require,module,exports){ +},{}],11:[function(require,module,exports){ module.exports={ "163.com": { "password-rules": "minlength: 6; maxlength: 16;" @@ -3568,7 +3468,7 @@ module.exports={ "password-rules": "minlength: 8; maxlength: 32; max-consecutive: 6; required: lower; required: upper; required: digit;" } } -},{}],14:[function(require,module,exports){ +},{}],12:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -3641,7 +3541,7 @@ function createDevice() { return new _ExtensionInterface.ExtensionInterface(globalConfig, deviceApi, settings); } -},{"../packages/device-api/index.js":6,"./DeviceInterface/AndroidInterface.js":15,"./DeviceInterface/AppleDeviceInterface.js":16,"./DeviceInterface/AppleOverlayDeviceInterface.js":17,"./DeviceInterface/ExtensionInterface.js":18,"./DeviceInterface/WindowsInterface.js":20,"./DeviceInterface/WindowsOverlayDeviceInterface.js":21,"./Settings.js":42,"./config.js":55,"./deviceApiCalls/transports/transports.js":63}],15:[function(require,module,exports){ +},{"../packages/device-api/index.js":2,"./DeviceInterface/AndroidInterface.js":13,"./DeviceInterface/AppleDeviceInterface.js":14,"./DeviceInterface/AppleOverlayDeviceInterface.js":15,"./DeviceInterface/ExtensionInterface.js":16,"./DeviceInterface/WindowsInterface.js":18,"./DeviceInterface/WindowsOverlayDeviceInterface.js":19,"./Settings.js":40,"./config.js":53,"./deviceApiCalls/transports/transports.js":61}],13:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -3791,7 +3691,7 @@ class AndroidInterface extends _InterfacePrototype.default { exports.AndroidInterface = AndroidInterface; -},{"../UI/controllers/NativeUIController.js":48,"../autofill-utils.js":53,"./InterfacePrototype.js":19,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],16:[function(require,module,exports){ +},{"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],14:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4243,7 +4143,7 @@ class AppleDeviceInterface extends _InterfacePrototype.default { exports.AppleDeviceInterface = AppleDeviceInterface; -},{"../../packages/device-api/index.js":6,"../Form/matching.js":35,"../InContextSignup.js":36,"../UI/HTMLTooltip.js":46,"../UI/controllers/HTMLTooltipUIController.js":47,"../UI/controllers/NativeUIController.js":48,"../UI/controllers/OverlayUIController.js":49,"../autofill-utils.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/additionalDeviceApiCalls.js":59,"./InterfacePrototype.js":19,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],17:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../Form/matching.js":33,"../InContextSignup.js":34,"../UI/HTMLTooltip.js":44,"../UI/controllers/HTMLTooltipUIController.js":45,"../UI/controllers/NativeUIController.js":46,"../UI/controllers/OverlayUIController.js":47,"../autofill-utils.js":51,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/additionalDeviceApiCalls.js":57,"./InterfacePrototype.js":17,"@duckduckgo/content-scope-scripts/src/apple-utils":1}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4398,7 +4298,7 @@ class AppleOverlayDeviceInterface extends _AppleDeviceInterface.AppleDeviceInter exports.AppleOverlayDeviceInterface = AppleOverlayDeviceInterface; -},{"../../packages/device-api/index.js":6,"../UI/controllers/HTMLTooltipUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/__generated__/validators.zod.js":58,"./AppleDeviceInterface.js":16,"./overlayApi.js":23}],18:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../UI/controllers/HTMLTooltipUIController.js":45,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/__generated__/validators.zod.js":56,"./AppleDeviceInterface.js":14,"./overlayApi.js":21}],16:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -4676,7 +4576,7 @@ class ExtensionInterface extends _InterfacePrototype.default { exports.ExtensionInterface = ExtensionInterface; -},{"../Form/matching.js":35,"../InContextSignup.js":36,"../UI/HTMLTooltip.js":46,"../UI/controllers/HTMLTooltipUIController.js":47,"../autofill-utils.js":53,"./InterfacePrototype.js":19}],19:[function(require,module,exports){ +},{"../Form/matching.js":33,"../InContextSignup.js":34,"../UI/HTMLTooltip.js":44,"../UI/controllers/HTMLTooltipUIController.js":45,"../autofill-utils.js":51,"./InterfacePrototype.js":17}],17:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5745,7 +5645,7 @@ class InterfacePrototype { var _default = InterfacePrototype; exports.default = _default; -},{"../../packages/device-api/index.js":6,"../EmailProtection.js":24,"../Form/formatters.js":28,"../Form/matching.js":35,"../InputTypes/Credentials.js":37,"../PasswordGenerator.js":40,"../Scanner.js":41,"../Settings.js":42,"../UI/controllers/NativeUIController.js":48,"../autofill-utils.js":53,"../config.js":55,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"../deviceApiCalls/__generated__/validators.zod.js":58,"../deviceApiCalls/transports/transports.js":63,"./initFormSubmissionsApi.js":22}],20:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"../EmailProtection.js":22,"../Form/formatters.js":26,"../Form/matching.js":33,"../InputTypes/Credentials.js":35,"../PasswordGenerator.js":38,"../Scanner.js":39,"../Settings.js":40,"../UI/controllers/NativeUIController.js":46,"../autofill-utils.js":51,"../config.js":53,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"../deviceApiCalls/__generated__/validators.zod.js":56,"../deviceApiCalls/transports/transports.js":61,"./initFormSubmissionsApi.js":20}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5961,7 +5861,7 @@ class WindowsInterface extends _InterfacePrototype.default { exports.WindowsInterface = WindowsInterface; -},{"../UI/controllers/OverlayUIController.js":49,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"./InterfacePrototype.js":19}],21:[function(require,module,exports){ +},{"../UI/controllers/OverlayUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17}],19:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6170,7 +6070,7 @@ class WindowsOverlayDeviceInterface extends _InterfacePrototype.default { exports.WindowsOverlayDeviceInterface = WindowsOverlayDeviceInterface; -},{"../UI/controllers/HTMLTooltipUIController.js":47,"../deviceApiCalls/__generated__/deviceApiCalls.js":57,"./InterfacePrototype.js":19,"./overlayApi.js":23}],22:[function(require,module,exports){ +},{"../UI/controllers/HTMLTooltipUIController.js":45,"../deviceApiCalls/__generated__/deviceApiCalls.js":55,"./InterfacePrototype.js":17,"./overlayApi.js":21}],20:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6276,7 +6176,7 @@ function initFormSubmissionsApi(forms, matching) { }); } -},{"../Form/label-util.js":31,"../autofill-utils.js":53}],23:[function(require,module,exports){ +},{"../Form/label-util.js":29,"../autofill-utils.js":51}],21:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6343,7 +6243,7 @@ function overlayApi(device) { }; } -},{"../deviceApiCalls/__generated__/deviceApiCalls.js":57}],24:[function(require,module,exports){ +},{"../deviceApiCalls/__generated__/deviceApiCalls.js":55}],22:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6404,7 +6304,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],25:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7324,7 +7224,7 @@ class Form { exports.Form = Form; -},{"../autofill-utils.js":53,"../constants.js":56,"./FormAnalyzer.js":26,"./formatters.js":28,"./inputStyles.js":29,"./inputTypeConfig.js":30,"./matching.js":35}],26:[function(require,module,exports){ +},{"../autofill-utils.js":51,"../constants.js":54,"./FormAnalyzer.js":24,"./formatters.js":26,"./inputStyles.js":27,"./inputTypeConfig.js":28,"./matching.js":33}],24:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7718,7 +7618,7 @@ class FormAnalyzer { var _default = FormAnalyzer; exports.default = _default; -},{"../autofill-utils.js":53,"../constants.js":56,"./matching-config/__generated__/compiled-matching-config.js":33,"./matching.js":35}],27:[function(require,module,exports){ +},{"../autofill-utils.js":51,"../constants.js":54,"./matching-config/__generated__/compiled-matching-config.js":31,"./matching.js":33}],25:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8286,7 +8186,7 @@ const COUNTRY_NAMES_TO_CODES = { }; exports.COUNTRY_NAMES_TO_CODES = COUNTRY_NAMES_TO_CODES; -},{}],28:[function(require,module,exports){ +},{}],26:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8643,7 +8543,7 @@ const prepareFormValuesForStorage = formValues => { exports.prepareFormValuesForStorage = prepareFormValuesForStorage; -},{"./countryNames.js":27,"./matching.js":35}],29:[function(require,module,exports){ +},{"./countryNames.js":25,"./matching.js":33}],27:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -8745,7 +8645,7 @@ const getIconStylesAutofilled = (input, form) => { exports.getIconStylesAutofilled = getIconStylesAutofilled; -},{"./inputTypeConfig.js":30}],30:[function(require,module,exports){ +},{"./inputTypeConfig.js":28}],28:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9025,7 +8925,7 @@ const isFieldDecorated = input => { exports.isFieldDecorated = isFieldDecorated; -},{"../InputTypes/Credentials.js":37,"../InputTypes/CreditCard.js":38,"../InputTypes/Identity.js":39,"../UI/img/ddgPasswordIcon.js":51,"../constants.js":56,"./logo-svg.js":32,"./matching.js":35}],31:[function(require,module,exports){ +},{"../InputTypes/Credentials.js":35,"../InputTypes/CreditCard.js":36,"../InputTypes/Identity.js":37,"../UI/img/ddgPasswordIcon.js":49,"../constants.js":54,"./logo-svg.js":30,"./matching.js":33}],29:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9086,7 +8986,7 @@ const extractElementStrings = element => { exports.extractElementStrings = extractElementStrings; -},{"./matching.js":35}],32:[function(require,module,exports){ +},{"./matching.js":33}],30:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -9100,7 +9000,7 @@ const daxGrayscaleSvg = "\n * {\n border-radius: 8px;\n border: 0;\n cursor: pointer;\n display: inline-block;\n font-family: inherit;\n font-style: normal;\n font-weight: bold;\n padding: 8px 12px;\n text-decoration: none;\n}\n\n.notice-controls .ghost {\n margin-left: 1rem;\n}\n\n.tooltip--email-signup a.primary {\n background: #3969EF;\n color: #fff;\n}\n\n.tooltip--email-signup a.primary:hover,\n.tooltip--email-signup a.primary:focus {\n background: #2b55ca;\n}\n\n.tooltip--email-signup a.primary:active {\n background: #1e42a4;\n}\n\n.tooltip--email-signup button.ghost {\n background: transparent;\n color: #3969EF;\n}\n\n.tooltip--email-signup button.ghost:hover,\n.tooltip--email-signup button.ghost:focus {\n background-color: rgba(0, 0, 0, 0.06);\n color: #2b55ca;\n}\n\n.tooltip--email-signup button.ghost:active {\n background-color: rgba(0, 0, 0, 0.12);\n color: #1e42a4;\n}\n\n.tooltip--email-signup button.close-tooltip {\n background-color: transparent;\n background-image: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTIiIGhlaWdodD0iMTMiIHZpZXdCb3g9IjAgMCAxMiAxMyIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik0wLjI5Mjg5NCAwLjY1NjkwN0MwLjY4MzQxOCAwLjI2NjM4MyAxLjMxNjU4IDAuMjY2MzgzIDEuNzA3MTEgMC42NTY5MDdMNiA0Ljk0OThMMTAuMjkyOSAwLjY1NjkwN0MxMC42ODM0IDAuMjY2MzgzIDExLjMxNjYgMC4yNjYzODMgMTEuNzA3MSAwLjY1NjkwN0MxMi4wOTc2IDEuMDQ3NDMgMTIuMDk3NiAxLjY4MDYgMTEuNzA3MSAyLjA3MTEyTDcuNDE0MjEgNi4zNjQwMUwxMS43MDcxIDEwLjY1NjlDMTIuMDk3NiAxMS4wNDc0IDEyLjA5NzYgMTEuNjgwNiAxMS43MDcxIDEyLjA3MTFDMTEuMzE2NiAxMi40NjE2IDEwLjY4MzQgMTIuNDYxNiAxMC4yOTI5IDEyLjA3MTFMNiA3Ljc3ODIzTDEuNzA3MTEgMTIuMDcxMUMxLjMxNjU4IDEyLjQ2MTYgMC42ODM0MTcgMTIuNDYxNiAwLjI5Mjg5MyAxMi4wNzExQy0wLjA5NzYzMTEgMTEuNjgwNiAtMC4wOTc2MzExIDExLjA0NzQgMC4yOTI4OTMgMTAuNjU2OUw0LjU4NTc5IDYuMzY0MDFMMC4yOTI4OTQgMi4wNzExMkMtMC4wOTc2MzA2IDEuNjgwNiAtMC4wOTc2MzA2IDEuMDQ3NDMgMC4yOTI4OTQgMC42NTY5MDdaIiBmaWxsPSJibGFjayIgZmlsbC1vcGFjaXR5PSIwLjg0Ii8+Cjwvc3ZnPgo=);\n background-position: center center;\n background-repeat: no-repeat;\n border: 0;\n cursor: pointer;\n padding: 16px;\n position: absolute;\n right: 12px;\n top: 12px;\n}\n"; exports.CSS_STYLES = CSS_STYLES; -},{}],53:[function(require,module,exports){ +},{}],51:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14472,7 +14372,7 @@ function isFormLikelyToBeUsedAsPageWrapper(form) { return formChildrenPercentage > 50; } -},{"./Form/matching.js":35}],54:[function(require,module,exports){ +},{"./Form/matching.js":33}],52:[function(require,module,exports){ "use strict"; require("./requestIdleCallback.js"); @@ -14507,7 +14407,7 @@ var _autofillUtils = require("./autofill-utils.js"); } })(); -},{"./DeviceInterface.js":14,"./autofill-utils.js":53,"./requestIdleCallback.js":65}],55:[function(require,module,exports){ +},{"./DeviceInterface.js":12,"./autofill-utils.js":51,"./requestIdleCallback.js":63}],53:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14595,7 +14495,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],56:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14613,7 +14513,7 @@ const constants = { }; exports.constants = constants; -},{}],57:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15103,7 +15003,7 @@ class CloseEmailProtectionTabCall extends _deviceApi.DeviceApiCall { exports.CloseEmailProtectionTabCall = CloseEmailProtectionTabCall; -},{"../../../packages/device-api":6,"./validators.zod.js":58}],58:[function(require,module,exports){ +},{"../../../packages/device-api":2,"./validators.zod.js":56}],56:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15187,7 +15087,7 @@ exports.askToUnlockProviderResultSchema = askToUnlockProviderResultSchema; const apiSchema = null; exports.apiSchema = apiSchema; -},{}],59:[function(require,module,exports){ +},{}],57:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15228,7 +15128,7 @@ class GetAlias extends _index.DeviceApiCall { exports.GetAlias = GetAlias; -},{"../../packages/device-api/index.js":6,"./__generated__/validators.zod.js":58}],60:[function(require,module,exports){ +},{"../../packages/device-api/index.js":2,"./__generated__/validators.zod.js":56}],58:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15386,7 +15286,7 @@ function androidSpecificAvailableInputTypes(globalConfig) { }; } -},{"../../../packages/device-api/index.js":6,"../__generated__/deviceApiCalls.js":57}],61:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../__generated__/deviceApiCalls.js":55}],59:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15394,7 +15294,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.AppleTransport = void 0; -var _contentScopeUtils = require("@duckduckgo/content-scope-utils"); +var _messaging = require("../../../packages/messaging/messaging.js"); var _index = require("../../../packages/device-api/index.js"); @@ -15405,12 +15305,12 @@ class AppleTransport extends _index.DeviceApiTransport { constructor(globalConfig) { super(); this.config = globalConfig; - const webkitConfig = new _contentScopeUtils.WebkitMessagingConfig({ + const webkitConfig = new _messaging.WebkitMessagingConfig({ hasModernWebkitAPI: this.config.hasModernWebkitAPI, webkitMessageHandlerNames: this.config.webkitMessageHandlerNames, secret: this.config.secret }); - this.messaging = new _contentScopeUtils.Messaging(webkitConfig); + this.messaging = new _messaging.Messaging(webkitConfig); } async send(deviceApiCall) { @@ -15422,7 +15322,7 @@ class AppleTransport extends _index.DeviceApiTransport { return this.messaging.notify(deviceApiCall.method, deviceApiCall.params || undefined); } } catch (e) { - if (e instanceof _contentScopeUtils.MissingHandler) { + if (e instanceof _messaging.MissingHandler) { if (this.config.isDDGTestMode) { console.log('MissingWebkitHandler error for:', deviceApiCall.method); } @@ -15462,7 +15362,7 @@ function appleSpecificRuntimeConfiguration(globalConfig) { }; } -},{"../../../packages/device-api/index.js":6,"../__generated__/deviceApiCalls.js":57,"@duckduckgo/content-scope-utils":2}],62:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../../../packages/messaging/messaging.js":5,"../__generated__/deviceApiCalls.js":55}],60:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15634,7 +15534,7 @@ async function extensionSpecificSetIncontextSignupPermanentlyDismissedAtCall(par }); } -},{"../../../packages/device-api/index.js":6,"../../Settings.js":42,"../../autofill-utils.js":53,"../__generated__/deviceApiCalls.js":57}],63:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2,"../../Settings.js":40,"../../autofill-utils.js":51,"../__generated__/deviceApiCalls.js":55}],61:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15688,7 +15588,7 @@ function createTransport(globalConfig) { return new _extensionTransport.ExtensionTransport(globalConfig); } -},{"./android.transport.js":60,"./apple.transport.js":61,"./extension.transport.js":62,"./windows.transport.js":64}],64:[function(require,module,exports){ +},{"./android.transport.js":58,"./apple.transport.js":59,"./extension.transport.js":60,"./windows.transport.js":62}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15788,7 +15688,7 @@ function waitForWindowsResponse(responseId, options) { }); } -},{"../../../packages/device-api/index.js":6}],65:[function(require,module,exports){ +},{"../../../packages/device-api/index.js":2}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15836,4 +15736,4 @@ window.cancelIdleCallback = window.cancelIdleCallback || function (id) { var _default = {}; exports.default = _default; -},{}]},{},[54]); +},{}]},{},[52]); diff --git a/tsconfig.json b/tsconfig.json index 2bac71091..2f1bab6ab 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -27,12 +27,12 @@ "maxNodeModuleJsDepth": 1 }, "include": [ - "node_modules/@duckduckgo/content-scope-utils", "src", "scripts", "packages/password", "integration-test", "packages/device-api", + "packages/messaging", "*.js", "types.d.ts" ],