From bfdcfc161dc1a18e59f8ebd58646d779cc45db2c Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Tue, 26 Sep 2023 09:16:52 +0100 Subject: [PATCH 1/2] deps: remove deprecated content-scope-utils --- dist/autofill-debug.js | 7393 ++++++++--------- dist/autofill.js | 1799 ++-- integration-test/helpers/mocks.android.js | 1 - integration-test/helpers/pages.js | 2 - package-lock.json | 12 - package.json | 1 - packages/messaging/messaging.js | 154 + packages/messaging/webkit.js | 372 + .../transports/apple.transport.js | 2 +- .../Resources/assets/autofill-debug.js | 7393 ++++++++--------- swift-package/Resources/assets/autofill.js | 1799 ++-- tsconfig.json | 2 +- 12 files changed, 9518 insertions(+), 9412 deletions(-) create mode 100644 packages/messaging/messaging.js create mode 100644 packages/messaging/webkit.js diff --git a/dist/autofill-debug.js b/dist/autofill-debug.js index 9ccabd40e..2dafa7744 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; + } -exports.Messaging = Messaging; + format(_mapper) { + const mapper = _mapper || function (issue) { + return issue.message; + }; -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'"); - } - /** - * @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 + const fieldErrors = { + _errors: [] + }; + 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; - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); - } + while (i < issue.path.length) { + const el = issue.path[i]; + const terminal = i === issue.path.length - 1; -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + 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)); + } -exports.MessagingTransport = MessagingTransport; + curr = curr[el]; + i++; + } + } + } + }; -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); + processError(this); + return fieldErrors; } - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + toString() { + return this.message; } - throw new Error('unreachable'); -} -/** - * Thrown when a handler cannot be found - */ - + get message() { + return JSON.stringify(this.issues, null, 2); + } -class MissingHandler extends Error { - /** - * @param {string} message - * @param {string} handlerName - */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; + get isEmpty() { + return this.issues.length === 0; } -} -/** - * Some re-exports for convenience - */ - - -exports.MissingHandler = MissingHandler; - -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; - -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; } - -/** - * @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 (!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) { - var _this$globals$window$, _this$globals$window$2; - - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } - - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret - } - }; + flatten() { + let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; + const fieldErrors = {}; + const formErrors = []; - 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); + 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 { - return this.globals.capturedWebkitHandlers[handler](outgoing); + formErrors.push(mapper(sub)); } } - 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 - */ - - - 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 - }; - } - } + return { + formErrors, + fieldErrors + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); + get formErrors() { + return this.flatten(); } - /** - * @param {string} name - * @param {Record} [data] - */ - // 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); - } - /** - * 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 - */ +exports.ZodError = ZodError; +ZodError.create = issues => { + const error = new ZodError(issues); + return error; +}; - generateRandomMethod(randomMethodName, callback) { - var _this = this; +const defaultErrorMap = (issue, _ctx) => { + let message; - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, + 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); + } - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. + break; - delete _this.globals.window[randomMethodName]; - } - }); - } + case exports.ZodIssueCode.invalid_literal: + message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); + break; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } + case exports.ZodIssueCode.unrecognized_keys: + message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); + break; - createRandMethodName() { - return '_' + this.randomString(); - } - /** - * @type {{name: string, length: number}} - */ + 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; - /** - * @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 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; - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ + case exports.ZodIssueCode.invalid_return_type: + message = "Invalid function return type"; + break; + case exports.ZodIssueCode.invalid_date: + message = "Invalid date"; + break; - 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 - */ + 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; - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); + 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; - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case exports.ZodIssueCode.custom: + message = "Invalid input"; + break; - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + case exports.ZodIssueCode.invalid_intersection_types: + message = "Intersection results could not be merged"; + break; - /** - * `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 exports.ZodIssueCode.not_multiple_of: + message = "Number must be a multiple of ".concat(issue.multipleOf); + break; + + default: + message = _ctx.defaultError; + util_1.util.assertNever(issue); } -} -/** - * 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") - * ``` - */ + return { + message + }; +}; +exports.defaultErrorMap = defaultErrorMap; +exports.overrideErrorMap = exports.defaultErrorMap; -exports.WebkitMessagingTransport = WebkitMessagingTransport; +const setErrorMap = map => { + exports.overrideErrorMap = map; +}; -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 - */ +exports.setErrorMap = setErrorMap; - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ +},{"./helpers/parseUtil":5,"./helpers/util":7}],3:[function(require,module,exports){ +"use strict"; - this.secret = params.secret; - } +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); -} -/** - * 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 (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + } + }; + } + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); -exports.WebkitMessagingConfig = WebkitMessagingConfig; +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); +}; -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 - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); - this.secret = params.secret; - /** - * The CipherKey as number[] - */ +__exportStar(require("./helpers/parseUtil"), exports); - this.key = params.key; - /** - * The Initial Vector as number[] - */ +__exportStar(require("./helpers/typeAliases"), exports); - this.iv = params.iv; - } +__exportStar(require("./types"), exports); -} -/** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this - */ +__exportStar(require("./ZodError"), exports); +},{"./ZodError":2,"./helpers/parseUtil":5,"./helpers/typeAliases":6,"./types":9}],4:[function(require,module,exports){ +"use strict"; -exports.SecureMessagingParams = SecureMessagingParams; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.errorUtil = void 0; +var errorUtil; -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), +(function (errorUtil) { + errorUtil.errToObj = message => typeof message === "string" ? { + message + } : message || {}; - /** @type {Record} */ - capturedWebkitHandlers: {} - }; -} + errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; +})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); -},{"../messaging.js":3}],5:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; - -var _messaging = require("../messaging.js"); +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; -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; } +const ZodError_1 = require("../ZodError"); -/** - * @implements {MessagingTransport} - */ -class WindowsMessagingTransport { - /** - * @param {WindowsMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); +const util_1 = require("./util"); - this.config = config; - } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars +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; - 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 + switch (t) { + case "undefined": + return exports.ZodParsedType.undefined; + case "string": + return exports.ZodParsedType.string; - 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'); - } + case "number": + return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; -} + case "boolean": + return exports.ZodParsedType.boolean; -exports.WindowsMessagingTransport = WindowsMessagingTransport; + case "function": + return exports.ZodParsedType.function; -class WindowsMessagingConfig { - /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; - } + case "bigint": + return exports.ZodParsedType.bigint; -} + case "object": + if (Array.isArray(data)) { + return exports.ZodParsedType.array; + } -exports.WindowsMessagingConfig = WindowsMessagingConfig; + if (data === null) { + return exports.ZodParsedType.null; + } -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return exports.ZodParsedType.promise; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; + if (typeof Map !== "undefined" && data instanceof Map) { + return exports.ZodParsedType.map; + } -const parseUtil_1 = require("./helpers/parseUtil"); + if (typeof Set !== "undefined" && data instanceof Set) { + return exports.ZodParsedType.set; + } -const util_1 = require("./helpers/util"); + if (typeof Date !== "undefined" && data instanceof Date) { + return exports.ZodParsedType.date; + } -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"]); + return exports.ZodParsedType.object; -const quotelessJson = obj => { - const json = JSON.stringify(obj, null, 2); - return json.replace(/"([^"]+)":/g, "$1:"); + default: + return exports.ZodParsedType.unknown; + } }; -exports.quotelessJson = quotelessJson; +exports.getParsedType = getParsedType; -class ZodError extends Error { - constructor(issues) { - var _this; +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(); - super(); - _this = this; - this.issues = []; + for (const map of maps) { + errorMessage = map(fullIssue, { + data, + defaultError: errorMessage + }).message; + } - this.addIssue = sub => { - this.issues = [...this.issues, sub]; - }; + return { ...issueData, + path: fullPath, + message: issueData.message || errorMessage + }; +}; - this.addIssues = function () { - let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - _this.issues = [..._this.issues, ...subs]; - }; +exports.makeIssue = makeIssue; +exports.EMPTY_PATH = []; - const actualProto = new.target.prototype; +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); +} - if (Object.setPrototypeOf) { - // eslint-disable-next-line ban/ban - Object.setPrototypeOf(this, actualProto); - } else { - this.__proto__ = actualProto; - } +exports.addIssueToContext = addIssueToContext; - this.name = "ZodError"; - this.issues = issues; +class ParseStatus { + constructor() { + this.value = "valid"; } - get errors() { - return this.issues; + dirty() { + if (this.value === "valid") this.value = "dirty"; } - format(_mapper) { - const mapper = _mapper || function (issue) { - return issue.message; - }; - - const fieldErrors = { - _errors: [] - }; - - 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; + abort() { + if (this.value !== "aborted") this.value = "aborted"; + } - 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: [] - }; + static mergeArray(status, results) { + const arrayValue = []; - curr[el]._errors.push(mapper(issue)); - } + for (const s of results) { + if (s.status === "aborted") return exports.INVALID; + if (s.status === "dirty") status.dirty(); + arrayValue.push(s.value); + } - curr = curr[el]; - i++; - } - } - } + return { + status: status.value, + value: arrayValue }; - - processError(this); - return fieldErrors; } - toString() { - return this.message; - } + static async mergeObjectAsync(status, pairs) { + const syncPairs = []; - get message() { - return JSON.stringify(this.issues, null, 2); - } + for (const pair of pairs) { + syncPairs.push({ + key: await pair.key, + value: await pair.value + }); + } - get isEmpty() { - return this.issues.length === 0; + return ParseStatus.mergeObjectSync(status, syncPairs); } - flatten() { - let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; - const fieldErrors = {}; - const formErrors = []; + static mergeObjectSync(status, pairs) { + const finalObject = {}; - 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 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; } } return { - formErrors, - fieldErrors + status: status.value, + value: finalObject }; } - get formErrors() { - return this.flatten(); - } - } -exports.ZodError = ZodError; +exports.ParseStatus = ParseStatus; +exports.INVALID = Object.freeze({ + status: "aborted" +}); -ZodError.create = issues => { - const error = new ZodError(issues); - return error; -}; +const DIRTY = value => ({ + status: "dirty", + value +}); -const defaultErrorMap = (issue, _ctx) => { - let message; +exports.DIRTY = DIRTY; - 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); - } +const OK = value => ({ + status: "valid", + value +}); - break; +exports.OK = OK; + +const isAborted = x => x.status === "aborted"; + +exports.isAborted = isAborted; + +const isDirty = x => x.status === "dirty"; + +exports.isDirty = isDirty; + +const isValid = x => x.status === "valid"; + +exports.isValid = isValid; + +const isAsync = x => typeof Promise !== undefined && x instanceof Promise; + +exports.isAsync = isAsync; + +},{"../ZodError":2,"./util":7}],6:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); - case exports.ZodIssueCode.invalid_literal: - message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); - break; +},{}],7:[function(require,module,exports){ +"use strict"; - case exports.ZodIssueCode.unrecognized_keys: - message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); - break; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.util = void 0; +var util; - case exports.ZodIssueCode.invalid_union: - message = "Invalid input"; - break; +(function (util) { + function assertNever(_x) { + throw new Error(); + } - case exports.ZodIssueCode.invalid_union_discriminator: - message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); - break; + util.assertNever = assertNever; - case exports.ZodIssueCode.invalid_enum_value: - message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); - break; + util.arrayToEnum = items => { + const obj = {}; - case exports.ZodIssueCode.invalid_arguments: - message = "Invalid function arguments"; - break; + for (const item of items) { + obj[item] = item; + } - case exports.ZodIssueCode.invalid_return_type: - message = "Invalid function return type"; - break; + return obj; + }; - case exports.ZodIssueCode.invalid_date: - message = "Invalid date"; - break; + util.getValidEnumValues = obj => { + const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); + const filtered = {}; - case exports.ZodIssueCode.invalid_string: - if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; - break; + for (const k of validKeys) { + filtered[k] = obj[k]; + } - 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; + return util.objectValues(filtered); + }; - 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; + util.objectValues = obj => { + return util.objectKeys(obj).map(function (e) { + return obj[e]; + }); + }; - case exports.ZodIssueCode.custom: - message = "Invalid input"; - break; + util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban + ? obj => Object.keys(obj) // eslint-disable-line ban/ban + : object => { + const keys = []; - case exports.ZodIssueCode.invalid_intersection_types: - message = "Intersection results could not be merged"; - break; + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); + } + } - 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,941 +671,1201 @@ 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); }; -Object.defineProperty(exports, "__esModule", { - value: true -}); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.z = void 0; + +const mod = __importStar(require("./external")); + +exports.z = mod; + +__exportStar(require("./external"), exports); + +exports.default = mod; + +},{"./external":3}],9:[function(require,module,exports){ +"use strict"; + +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"); + +const parseUtil_1 = require("./helpers/parseUtil"); + +const util_1 = require("./helpers/util"); + +const ZodError_1 = require("./ZodError"); + +class ParseInputLazyPath { + constructor(parent, value, path, key) { + this.parent = parent; + this.data = value; + this._path = path; + this._key = key; + } + + get path() { + return this._path.concat(this._key); + } + +} + +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."); + } + + const error = new ZodError_1.ZodError(ctx.common.issues); + return { + success: false, + error + }; + } +}; + +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."); + } + + if (errorMap) return { + errorMap: errorMap, + description + }; + + 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 + }; + }; + + return { + errorMap: customMap, + description + }; +} + +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); + } + + get description() { + return this._def.description; + } -__exportStar(require("./helpers/parseUtil"), exports); + _getType(input) { + return (0, parseUtil_1.getParsedType)(input.data); + } -__exportStar(require("./helpers/typeAliases"), exports); + _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 + }; + } -__exportStar(require("./types"), exports); + _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 + } + }; + } -__exportStar(require("./ZodError"), exports); + _parseSync(input) { + const result = this._parse(input); -},{"./ZodError":6,"./helpers/parseUtil":9,"./helpers/typeAliases":10,"./types":13}],8:[function(require,module,exports){ -"use strict"; + if ((0, parseUtil_1.isAsync)(result)) { + throw new Error("Synchronous parse encountered promise."); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.errorUtil = void 0; -var errorUtil; + return result; + } -(function (errorUtil) { - errorUtil.errToObj = message => typeof message === "string" ? { - message - } : message || {}; + _parseAsync(input) { + const result = this._parse(input); - errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; -})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); + return Promise.resolve(result); + } -},{}],9:[function(require,module,exports){ -"use strict"; + parse(data, params) { + const result = this.safeParse(data, params); + if (result.success) return result.data; + throw result.error; + } -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; + safeParse(data, params) { + var _a; -const ZodError_1 = require("../ZodError"); + 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 util_1 = require("./util"); + const result = this._parseSync({ + data, + path: ctx.path, + parent: ctx + }); -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"]); + return handleResult(ctx, result); + } -const getParsedType = data => { - const t = typeof data; + async parseAsync(data, params) { + const result = await this.safeParseAsync(data, params); + if (result.success) return result.data; + throw result.error; + } - switch (t) { - case "undefined": - return exports.ZodParsedType.undefined; + 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) + }; - case "string": - return exports.ZodParsedType.string; + const maybeAsyncResult = this._parse({ + data, + path: [], + parent: ctx + }); - case "number": - return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; + const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } - case "boolean": - return exports.ZodParsedType.boolean; + 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; + } + }; - case "function": - return exports.ZodParsedType.function; + return this._refinement((val, ctx) => { + const result = check(val); - case "bigint": - return exports.ZodParsedType.bigint; + const setError = () => ctx.addIssue({ + code: ZodError_1.ZodIssueCode.custom, + ...getIssueProperties(val) + }); - case "object": - if (Array.isArray(data)) { - return exports.ZodParsedType.array; + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then(data => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); } - if (data === null) { - return exports.ZodParsedType.null; + if (!result) { + setError(); + return false; + } else { + return true; } + }); + } - if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { - return exports.ZodParsedType.promise; + 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; } + }); + } - if (typeof Map !== "undefined" && data instanceof Map) { - return exports.ZodParsedType.map; + _refinement(refinement) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "refinement", + refinement } + }); + } - if (typeof Set !== "undefined" && data instanceof Set) { - return exports.ZodParsedType.set; - } + optional() { + return ZodOptional.create(this); + } - if (typeof Date !== "undefined" && data instanceof Date) { - return exports.ZodParsedType.date; - } + nullable() { + return ZodNullable.create(this); + } - return exports.ZodParsedType.object; + nullish() { + return this.optional().nullable(); + } - default: - return exports.ZodParsedType.unknown; + array() { + return ZodArray.create(this); } -}; -exports.getParsedType = getParsedType; + promise() { + return ZodPromise.create(this); + } -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(); + or(option) { + return ZodUnion.create([this, option]); + } + + and(incoming) { + return ZodIntersection.create(this, incoming); + } + + transform(transform) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "transform", + transform + } + }); + } + + default(def) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + return new ZodDefault({ + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault + }); + } - for (const map of maps) { - errorMessage = map(fullIssue, { - data, - defaultError: errorMessage - }).message; + describe(description) { + const This = this.constructor; + return new This({ ...this._def, + description + }); } - return { ...issueData, - path: fullPath, - message: issueData.message || errorMessage - }; -}; + isOptional() { + return this.safeParse(undefined).success; + } -exports.makeIssue = makeIssue; -exports.EMPTY_PATH = []; + isNullable() { + return this.safeParse(null).success; + } -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"; - } +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 - dirty() { - if (this.value === "valid") this.value = "dirty"; - } +const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; - abort() { - if (this.value !== "aborted") this.value = "aborted"; - } +class ZodString extends ZodType { + constructor() { + super(...arguments); - static mergeArray(status, results) { - const arrayValue = []; + 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. + */ - for (const s of results) { - if (s.status === "aborted") return exports.INVALID; - if (s.status === "dirty") status.dirty(); - arrayValue.push(s.value); - } - return { - status: status.value, - value: arrayValue - }; + this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); } - static async mergeObjectAsync(status, pairs) { - const syncPairs = []; + _parse(input) { + const parsedType = this._getType(input); - for (const pair of pairs) { - syncPairs.push({ - key: await pair.key, - value: await pair.value - }); - } + if (parsedType !== parseUtil_1.ZodParsedType.string) { + const ctx = this._getOrReturnCtx(input); - return ParseStatus.mergeObjectSync(status, syncPairs); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.string, + received: ctx.parsedType + } // + ); + return parseUtil_1.INVALID; + } - static mergeObjectSync(status, pairs) { - const finalObject = {}; + const status = new parseUtil_1.ParseStatus(); + let ctx = undefined; - 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(); + 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 (typeof value.value !== "undefined" || pair.alwaysSet) { - finalObject[key.value] = value.value; + 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: finalObject + value: input.data }; } -} - -exports.ParseStatus = ParseStatus; -exports.INVALID = Object.freeze({ - status: "aborted" -}); - -const DIRTY = value => ({ - status: "dirty", - value -}); - -exports.DIRTY = DIRTY; - -const OK = value => ({ - status: "valid", - value -}); - -exports.OK = OK; - -const isAborted = x => x.status === "aborted"; + _addCheck(check) { + return new ZodString({ ...this._def, + checks: [...this._def.checks, check] + }); + } -exports.isAborted = isAborted; + email(message) { + return this._addCheck({ + kind: "email", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isDirty = x => x.status === "dirty"; + url(message) { + return this._addCheck({ + kind: "url", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isDirty = isDirty; + uuid(message) { + return this._addCheck({ + kind: "uuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isValid = x => x.status === "valid"; + cuid(message) { + return this._addCheck({ + kind: "cuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isValid = isValid; + regex(regex, message) { + return this._addCheck({ + kind: "regex", + regex: regex, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isAsync = x => typeof Promise !== undefined && x instanceof Promise; + min(minLength, message) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isAsync = isAsync; + max(maxLength, message) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -},{"../ZodError":6,"./util":11}],10:[function(require,module,exports){ -"use strict"; + length(len, message) { + return this.min(len, message).max(len, message); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + get isEmail() { + return !!this._def.checks.find(ch => ch.kind === "email"); + } -},{}],11:[function(require,module,exports){ -"use strict"; + get isURL() { + return !!this._def.checks.find(ch => ch.kind === "url"); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.util = void 0; -var util; + get isUUID() { + return !!this._def.checks.find(ch => ch.kind === "uuid"); + } -(function (util) { - function assertNever(_x) { - throw new Error(); + get isCUID() { + return !!this._def.checks.find(ch => ch.kind === "cuid"); } - util.assertNever = assertNever; + get minLength() { + let min = -Infinity; - util.arrayToEnum = items => { - const obj = {}; + this._def.checks.map(ch => { + if (ch.kind === "min") { + if (min === null || ch.value > min) { + min = ch.value; + } + } + }); - for (const item of items) { - obj[item] = item; - } + return min; + } - return obj; - }; + get maxLength() { + let max = null; - util.getValidEnumValues = obj => { - const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); - const filtered = {}; + this._def.checks.map(ch => { + if (ch.kind === "max") { + if (max === null || ch.value < max) { + max = ch.value; + } + } + }); - for (const k of validKeys) { - filtered[k] = obj[k]; - } + return max; + } - return util.objectValues(filtered); - }; +} - util.objectValues = obj => { - return util.objectKeys(obj).map(function (e) { - return obj[e]; - }); - }; +exports.ZodString = ZodString; - util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban - ? obj => Object.keys(obj) // eslint-disable-line ban/ban - : object => { - const keys = []; +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 - for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key)) { - keys.push(key); - } - } - return keys; - }; +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); +} - util.find = (arr, checker) => { - for (const item of arr) { - if (checker(item)) return item; - } +class ZodNumber extends ZodType { + constructor() { + super(...arguments); + this.min = this.gte; + this.max = this.lte; + this.step = this.multipleOf; + } - return undefined; - }; + _parse(input) { + const parsedType = this._getType(input); - 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; + if (parsedType !== parseUtil_1.ZodParsedType.number) { + const ctx = this._getOrReturnCtx(input); - 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); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.number, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - util.joinValues = joinValues; -})(util = exports.util || (exports.util = {})); + let ctx = undefined; + const status = new parseUtil_1.ParseStatus(); -},{}],12:[function(require,module,exports){ -"use strict"; + for (const check of this._def.checks) { + if (check.kind === "int") { + if (!util_1.util.isInteger(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: "integer", + received: "float", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; -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 (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: check.value, + type: "number", + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: check.value, + type: "number", + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (floatSafeRemainder(input.data, check.value) !== 0) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message + }); + status.dirty(); + } + } else { + util_1.util.assertNever(check); } + } + + return { + status: status.value, + value: input.data }; } - Object.defineProperty(o, k2, desc); -} : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -}); + gte(value, message) { + return this.setLimit("min", value, true, errorUtil_1.errorUtil.toString(message)); + } -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; -}); + gt(value, message) { + return this.setLimit("min", value, false, errorUtil_1.errorUtil.toString(message)); + } -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); + lte(value, message) { + return this.setLimit("max", value, true, errorUtil_1.errorUtil.toString(message)); + } - __setModuleDefault(result, mod); + lt(value, message) { + return this.setLimit("max", value, false, errorUtil_1.errorUtil.toString(message)); + } - return result; -}; + setLimit(kind, value, inclusive, message) { + return new ZodNumber({ ...this._def, + checks: [...this._def.checks, { + kind, + value, + inclusive, + message: errorUtil_1.errorUtil.toString(message) + }] + }); + } -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); -}; + _addCheck(check) { + return new ZodNumber({ ...this._def, + checks: [...this._def.checks, check] + }); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.z = void 0; + int(message) { + return this._addCheck({ + kind: "int", + message: errorUtil_1.errorUtil.toString(message) + }); + } -const mod = __importStar(require("./external")); + positive(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: false, + message: errorUtil_1.errorUtil.toString(message) + }); + } -exports.z = mod; + negative(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: false, + message: errorUtil_1.errorUtil.toString(message) + }); + } -__exportStar(require("./external"), exports); + nonpositive(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: true, + message: errorUtil_1.errorUtil.toString(message) + }); + } -exports.default = mod; + nonnegative(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: true, + message: errorUtil_1.errorUtil.toString(message) + }); + } -},{"./external":7}],13:[function(require,module,exports){ -"use strict"; + multipleOf(value, message) { + return this._addCheck({ + kind: "multipleOf", + value: value, + message: errorUtil_1.errorUtil.toString(message) + }); + } -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; + get minValue() { + let min = null; -const errorUtil_1 = require("./helpers/errorUtil"); + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } -const parseUtil_1 = require("./helpers/parseUtil"); + return min; + } -const util_1 = require("./helpers/util"); + get maxValue() { + let max = null; -const ZodError_1 = require("./ZodError"); + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } -class ParseInputLazyPath { - constructor(parent, value, path, key) { - this.parent = parent; - this.data = value; - this._path = path; - this._key = key; + return max; } - get path() { - return this._path.concat(this._key); + get isInt() { + return !!this._def.checks.find(ch => ch.kind === "int"); } } -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."); - } +exports.ZodNumber = ZodNumber; - const error = new ZodError_1.ZodError(ctx.common.issues); - return { - success: false, - error - }; - } +ZodNumber.create = params => { + return new ZodNumber({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodNumber, + ...processCreateParams(params) + }); }; -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."); - } - - if (errorMap) return { - errorMap: errorMap, - description - }; +class ZodBigInt extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - 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 - }; - }; + if (parsedType !== parseUtil_1.ZodParsedType.bigint) { + const ctx = this._getOrReturnCtx(input); - return { - errorMap: customMap, - description - }; -} + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.bigint, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } -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); + return (0, parseUtil_1.OK)(input.data); } - get description() { - return this._def.description; - } +} - _getType(input) { - return (0, parseUtil_1.getParsedType)(input.data); - } +exports.ZodBigInt = ZodBigInt; - _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 - }; - } +ZodBigInt.create = params => { + return new ZodBigInt({ + typeName: ZodFirstPartyTypeKind.ZodBigInt, + ...processCreateParams(params) + }); +}; - _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 - } - }; - } +class ZodBoolean extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - _parseSync(input) { - const result = this._parse(input); + if (parsedType !== parseUtil_1.ZodParsedType.boolean) { + const ctx = this._getOrReturnCtx(input); - if ((0, parseUtil_1.isAsync)(result)) { - throw new Error("Synchronous parse encountered promise."); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.boolean, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; } - return result; + return (0, parseUtil_1.OK)(input.data); } - _parseAsync(input) { - const result = this._parse(input); +} - return Promise.resolve(result); - } +exports.ZodBoolean = ZodBoolean; - parse(data, params) { - const result = this.safeParse(data, params); - if (result.success) return result.data; - throw result.error; - } +ZodBoolean.create = params => { + return new ZodBoolean({ + typeName: ZodFirstPartyTypeKind.ZodBoolean, + ...processCreateParams(params) + }); +}; - safeParse(data, params) { - var _a; +class ZodDate extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - 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) - }; + if (parsedType !== parseUtil_1.ZodParsedType.date) { + const ctx = this._getOrReturnCtx(input); - const result = this._parseSync({ - data, - path: ctx.path, - parent: ctx - }); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.date, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - return handleResult(ctx, result); - } + if (isNaN(input.data.getTime())) { + const ctx = this._getOrReturnCtx(input); - async parseAsync(data, params) { - const result = await this.safeParseAsync(data, params); - if (result.success) return result.data; - throw result.error; - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_date + }); + return parseUtil_1.INVALID; + } - 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) + return { + status: "valid", + value: new Date(input.data.getTime()) }; + } - const maybeAsyncResult = this._parse({ - data, - path: [], - parent: ctx - }); +} - const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); - return handleResult(ctx, result); - } +exports.ZodDate = ZodDate; - 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; - } - }; +ZodDate.create = params => { + return new ZodDate({ + typeName: ZodFirstPartyTypeKind.ZodDate, + ...processCreateParams(params) + }); +}; - return this._refinement((val, ctx) => { - const result = check(val); +class ZodUndefined extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - const setError = () => ctx.addIssue({ - code: ZodError_1.ZodIssueCode.custom, - ...getIssueProperties(val) - }); + if (parsedType !== parseUtil_1.ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); - if (typeof Promise !== "undefined" && result instanceof Promise) { - return result.then(data => { - if (!data) { - setError(); - return false; - } else { - return true; - } - }); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.undefined, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - if (!result) { - setError(); - return false; - } else { - return true; - } - }); + return (0, parseUtil_1.OK)(input.data); } - 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; - } - }); - } +} - _refinement(refinement) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "refinement", - refinement - } - }); - } +exports.ZodUndefined = ZodUndefined; - optional() { - return ZodOptional.create(this); - } +ZodUndefined.create = params => { + return new ZodUndefined({ + typeName: ZodFirstPartyTypeKind.ZodUndefined, + ...processCreateParams(params) + }); +}; - nullable() { - return ZodNullable.create(this); - } +class ZodNull extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - nullish() { - return this.optional().nullable(); - } + if (parsedType !== parseUtil_1.ZodParsedType.null) { + const ctx = this._getOrReturnCtx(input); - array() { - return ZodArray.create(this); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.null, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - promise() { - return ZodPromise.create(this); + return (0, parseUtil_1.OK)(input.data); } - or(option) { - return ZodUnion.create([this, option]); - } +} - and(incoming) { - return ZodIntersection.create(this, incoming); - } +exports.ZodNull = ZodNull; - transform(transform) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "transform", - transform - } - }); - } +ZodNull.create = params => { + return new ZodNull({ + typeName: ZodFirstPartyTypeKind.ZodNull, + ...processCreateParams(params) + }); +}; - default(def) { - const defaultValueFunc = typeof def === "function" ? def : () => def; - return new ZodDefault({ - innerType: this, - defaultValue: defaultValueFunc, - typeName: ZodFirstPartyTypeKind.ZodDefault - }); +class ZodAny extends ZodType { + constructor() { + super(...arguments); // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. + + this._any = true; } - describe(description) { - const This = this.constructor; - return new This({ ...this._def, - description - }); + _parse(input) { + return (0, parseUtil_1.OK)(input.data); } - isOptional() { - return this.safeParse(undefined).success; +} + +exports.ZodAny = ZodAny; + +ZodAny.create = params => { + return new ZodAny({ + typeName: ZodFirstPartyTypeKind.ZodAny, + ...processCreateParams(params) + }); +}; + +class ZodUnknown extends ZodType { + constructor() { + super(...arguments); // required + + this._unknown = true; } - isNullable() { - return this.safeParse(null).success; + _parse(input) { + return (0, parseUtil_1.OK)(input.data); } } -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 +exports.ZodUnknown = ZodUnknown; -const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; +ZodUnknown.create = params => { + return new ZodUnknown({ + typeName: ZodFirstPartyTypeKind.ZodUnknown, + ...processCreateParams(params) + }); +}; -class ZodString extends ZodType { - constructor() { - super(...arguments); +class ZodNever extends ZodType { + _parse(input) { + const ctx = this._getOrReturnCtx(input); - this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { - validation, - code: ZodError_1.ZodIssueCode.invalid_string, - ...errorUtil_1.errorUtil.errToObj(message) + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.never, + received: ctx.parsedType }); - /** - * Deprecated. - * Use z.string().min(1) instead. - */ + return parseUtil_1.INVALID; + } +} - this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); - } +exports.ZodNever = ZodNever; +ZodNever.create = params => { + return new ZodNever({ + typeName: ZodFirstPartyTypeKind.ZodNever, + ...processCreateParams(params) + }); +}; + +class ZodVoid extends ZodType { _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.string) { + if (parsedType !== parseUtil_1.ZodParsedType.undefined) { 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.void, received: ctx.parsedType - } // - ); + }); return parseUtil_1.INVALID; } - const status = new parseUtil_1.ParseStatus(); - let ctx = undefined; + return (0, parseUtil_1.OK)(input.data); + } - 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(); - } - } - } +exports.ZodVoid = ZodVoid; - return { - status: status.value, - value: input.data - }; - } +ZodVoid.create = params => { + return new ZodVoid({ + typeName: ZodFirstPartyTypeKind.ZodVoid, + ...processCreateParams(params) + }); +}; - _addCheck(check) { - return new ZodString({ ...this._def, - checks: [...this._def.checks, check] - }); - } +class ZodArray extends ZodType { + _parse(input) { + const { + ctx, + status + } = this._processInputParams(input); - email(message) { - return this._addCheck({ - kind: "email", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + const def = this._def; - url(message) { - return this._addCheck({ - kind: "url", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.array, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - uuid(message) { - return this._addCheck({ - kind: "uuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + if (def.minLength !== null) { + if (ctx.data.length < def.minLength.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: def.minLength.value, + type: "array", + inclusive: true, + message: def.minLength.message + }); + status.dirty(); + } + } - cuid(message) { - return this._addCheck({ - kind: "cuid", - ...errorUtil_1.errorUtil.errToObj(message) + if (def.maxLength !== null) { + if (ctx.data.length > def.maxLength.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: def.maxLength.value, + type: "array", + inclusive: true, + message: def.maxLength.message + }); + status.dirty(); + } + } + + if (ctx.common.async) { + return Promise.all(ctx.data.map((item, i) => { + return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); + })).then(result => { + return parseUtil_1.ParseStatus.mergeArray(status, result); + }); + } + + const result = ctx.data.map((item, i) => { + return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); }); + return parseUtil_1.ParseStatus.mergeArray(status, result); } - regex(regex, message) { - return this._addCheck({ - kind: "regex", - regex: regex, - ...errorUtil_1.errorUtil.errToObj(message) - }); + get element() { + return this._def.type; } min(minLength, message) { - return this._addCheck({ - kind: "min", - value: minLength, - ...errorUtil_1.errorUtil.errToObj(message) + return new ZodArray({ ...this._def, + minLength: { + value: minLength, + message: errorUtil_1.errorUtil.toString(message) + } }); } max(maxLength, message) { - return this._addCheck({ - kind: "max", - value: maxLength, - ...errorUtil_1.errorUtil.errToObj(message) + return new ZodArray({ ...this._def, + maxLength: { + value: maxLength, + message: errorUtil_1.errorUtil.toString(message) + } }); } @@ -1969,544 +1873,742 @@ class ZodString extends ZodType { return this.min(len, message).max(len, message); } - get isEmail() { - return !!this._def.checks.find(ch => ch.kind === "email"); + nonempty(message) { + return this.min(1, message); } - get isURL() { - return !!this._def.checks.find(ch => ch.kind === "url"); - } +} - get isUUID() { - return !!this._def.checks.find(ch => ch.kind === "uuid"); - } +exports.ZodArray = ZodArray; - get isCUID() { - return !!this._def.checks.find(ch => ch.kind === "cuid"); - } +ZodArray.create = (schema, params) => { + return new ZodArray({ + type: schema, + minLength: null, + maxLength: null, + typeName: ZodFirstPartyTypeKind.ZodArray, + ...processCreateParams(params) + }); +}; ///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodObject ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// - get minLength() { - let min = -Infinity; - this._def.checks.map(ch => { - if (ch.kind === "min") { - if (min === null || ch.value > min) { - min = ch.value; - } - } - }); +var objectUtil; - return min; - } +(function (objectUtil) { + objectUtil.mergeShapes = (first, second) => { + return { ...first, + ...second // second overwrites first - get maxLength() { - let max = null; + }; + }; +})(objectUtil = exports.objectUtil || (exports.objectUtil = {})); - this._def.checks.map(ch => { - if (ch.kind === "max") { - if (max === null || ch.value < max) { - max = ch.value; - } - } - }); +const AugmentFactory = def => augmentation => { + return new ZodObject({ ...def, + shape: () => ({ ...def.shape(), + ...augmentation + }) + }); +}; - return max; - } +function deepPartialify(schema) { + if (schema instanceof ZodObject) { + const newShape = {}; + + for (const key in schema.shape) { + const fieldSchema = schema.shape[key]; + newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + } + return new ZodObject({ ...schema._def, + shape: () => newShape + }); + } else if (schema instanceof ZodArray) { + return ZodArray.create(deepPartialify(schema.element)); + } else if (schema instanceof ZodOptional) { + return ZodOptional.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodNullable) { + return ZodNullable.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodTuple) { + return ZodTuple.create(schema.items.map(item => deepPartialify(item))); + } else { + return schema; + } } -exports.ZodString = ZodString; +class ZodObject extends ZodType { + constructor() { + super(...arguments); + this._cached = null; + /** + * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. + * If you want to pass through unknown properties, use `.passthrough()` instead. + */ -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 + this.nonstrict = this.passthrough; + this.augment = AugmentFactory(this._def); + this.extend = AugmentFactory(this._def); + } + _getCached() { + if (this._cached !== null) return this._cached; -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); -} + const shape = this._def.shape(); -class ZodNumber extends ZodType { - constructor() { - super(...arguments); - this.min = this.gte; - this.max = this.lte; - this.step = this.multipleOf; + const keys = util_1.util.objectKeys(shape); + return this._cached = { + shape, + keys + }; } _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.number) { + if (parsedType !== parseUtil_1.ZodParsedType.object) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.number, + expected: parseUtil_1.ZodParsedType.object, received: ctx.parsedType }); return parseUtil_1.INVALID; } - let ctx = undefined; - const status = new parseUtil_1.ParseStatus(); + const { + status, + ctx + } = this._processInputParams(input); - for (const check of this._def.checks) { - if (check.kind === "int") { - if (!util_1.util.isInteger(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: "integer", - received: "float", - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "min") { - const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + const { + shape, + keys: shapeKeys + } = this._getCached(); - if (tooSmall) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: check.value, - type: "number", - inclusive: check.inclusive, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "max") { - const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + const extraKeys = []; - if (tooBig) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: check.value, - type: "number", - inclusive: check.inclusive, - message: check.message + for (const key in ctx.data) { + if (!shapeKeys.includes(key)) { + extraKeys.push(key); + } + } + + const pairs = []; + + for (const key of shapeKeys) { + const keyValidator = shape[key]; + const value = ctx.data[key]; + pairs.push({ + key: { + status: "valid", + value: key + }, + value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), + alwaysSet: key in ctx.data + }); + } + + if (this._def.catchall instanceof ZodNever) { + const unknownKeys = this._def.unknownKeys; + + if (unknownKeys === "passthrough") { + for (const key of extraKeys) { + pairs.push({ + key: { + status: "valid", + value: key + }, + value: { + status: "valid", + value: ctx.data[key] + } }); - status.dirty(); } - } else if (check.kind === "multipleOf") { - if (floatSafeRemainder(input.data, check.value) !== 0) { - ctx = this._getOrReturnCtx(input, ctx); + } else if (unknownKeys === "strict") { + if (extraKeys.length > 0) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.not_multiple_of, - multipleOf: check.value, - message: check.message + code: ZodError_1.ZodIssueCode.unrecognized_keys, + keys: extraKeys }); status.dirty(); } - } else { - util_1.util.assertNever(check); + } else if (unknownKeys === "strip") {} else { + throw new Error("Internal ZodObject error: invalid unknownKeys value."); + } + } else { + // run catchall validation + const catchall = this._def.catchall; + + for (const key of extraKeys) { + const value = ctx.data[key]; + pairs.push({ + key: { + status: "valid", + value: key + }, + value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) + ), + alwaysSet: key in ctx.data + }); } } - return { - status: status.value, - value: input.data - }; - } + if (ctx.common.async) { + return Promise.resolve().then(async () => { + const syncPairs = []; - gte(value, message) { - return this.setLimit("min", value, true, errorUtil_1.errorUtil.toString(message)); - } + for (const pair of pairs) { + const key = await pair.key; + syncPairs.push({ + key, + value: await pair.value, + alwaysSet: pair.alwaysSet + }); + } - gt(value, message) { - return this.setLimit("min", value, false, errorUtil_1.errorUtil.toString(message)); + return syncPairs; + }).then(syncPairs => { + return parseUtil_1.ParseStatus.mergeObjectSync(status, syncPairs); + }); + } else { + return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); + } } - lte(value, message) { - return this.setLimit("max", value, true, errorUtil_1.errorUtil.toString(message)); + get shape() { + return this._def.shape(); } - lt(value, message) { - return this.setLimit("max", value, false, errorUtil_1.errorUtil.toString(message)); - } + strict(message) { + errorUtil_1.errorUtil.errToObj; + return new ZodObject({ ...this._def, + unknownKeys: "strict", + ...(message !== undefined ? { + errorMap: (issue, ctx) => { + var _a, _b, _c, _d; - setLimit(kind, value, inclusive, message) { - return new ZodNumber({ ...this._def, - checks: [...this._def.checks, { - kind, - value, - inclusive, - message: errorUtil_1.errorUtil.toString(message) - }] + const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError; + if (issue.code === "unrecognized_keys") return { + message: (_d = errorUtil_1.errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError + }; + return { + message: defaultError + }; + } + } : {}) }); } - _addCheck(check) { - return new ZodNumber({ ...this._def, - checks: [...this._def.checks, check] + strip() { + return new ZodObject({ ...this._def, + unknownKeys: "strip" }); } - int(message) { - return this._addCheck({ - kind: "int", - message: errorUtil_1.errorUtil.toString(message) + passthrough() { + return new ZodObject({ ...this._def, + unknownKeys: "passthrough" }); } - positive(message) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: false, - message: errorUtil_1.errorUtil.toString(message) + setKey(key, schema) { + return this.augment({ + [key]: schema }); } + /** + * Prior to zod@1.0.12 there was a bug in the + * inferred type of merged objects. Please + * upgrade if you are experiencing issues. + */ - negative(message) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: false, - message: errorUtil_1.errorUtil.toString(message) + + merge(merging) { + // const mergedShape = objectUtil.mergeShapes( + // this._def.shape(), + // merging._def.shape() + // ); + const merged = new ZodObject({ + unknownKeys: merging._def.unknownKeys, + catchall: merging._def.catchall, + shape: () => objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + typeName: ZodFirstPartyTypeKind.ZodObject }); + return merged; } - nonpositive(message) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: true, - message: errorUtil_1.errorUtil.toString(message) + catchall(index) { + return new ZodObject({ ...this._def, + catchall: index }); } - nonnegative(message) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: true, - message: errorUtil_1.errorUtil.toString(message) + pick(mask) { + const shape = {}; + util_1.util.objectKeys(mask).map(key => { + shape[key] = this.shape[key]; + }); + return new ZodObject({ ...this._def, + shape: () => shape }); } - multipleOf(value, message) { - return this._addCheck({ - kind: "multipleOf", - value: value, - message: errorUtil_1.errorUtil.toString(message) + omit(mask) { + const shape = {}; + util_1.util.objectKeys(this.shape).map(key => { + if (util_1.util.objectKeys(mask).indexOf(key) === -1) { + shape[key] = this.shape[key]; + } + }); + return new ZodObject({ ...this._def, + shape: () => shape }); } - get minValue() { - let min = null; + deepPartial() { + return deepPartialify(this); + } - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; + partial(mask) { + const newShape = {}; + + if (mask) { + util_1.util.objectKeys(this.shape).map(key => { + if (util_1.util.objectKeys(mask).indexOf(key) === -1) { + newShape[key] = this.shape[key]; + } else { + newShape[key] = this.shape[key].optional(); + } + }); + return new ZodObject({ ...this._def, + shape: () => newShape + }); + } else { + for (const key in this.shape) { + const fieldSchema = this.shape[key]; + newShape[key] = fieldSchema.optional(); } } - return min; + return new ZodObject({ ...this._def, + shape: () => newShape + }); } - get maxValue() { - let max = null; + required() { + const newShape = {}; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; + for (const key in this.shape) { + const fieldSchema = this.shape[key]; + let newField = fieldSchema; + + while (newField instanceof ZodOptional) { + newField = newField._def.innerType; } - } - return max; - } + newShape[key] = newField; + } - get isInt() { - return !!this._def.checks.find(ch => ch.kind === "int"); + return new ZodObject({ ...this._def, + shape: () => newShape + }); } } -exports.ZodNumber = ZodNumber; +exports.ZodObject = ZodObject; -ZodNumber.create = params => { - return new ZodNumber({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodNumber, +ZodObject.create = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, ...processCreateParams(params) }); }; -class ZodBigInt extends ZodType { +ZodObject.strictCreate = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strict", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; + +ZodObject.lazycreate = (shape, params) => { + return new ZodObject({ + shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; + +class ZodUnion extends ZodType { _parse(input) { - const parsedType = this._getType(input); + const { + ctx + } = this._processInputParams(input); - if (parsedType !== parseUtil_1.ZodParsedType.bigint) { - const ctx = this._getOrReturnCtx(input); + const options = this._def.options; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.bigint, - received: ctx.parsedType + function handleResults(results) { + // return first issue-free validation if it exists + for (const result of results) { + if (result.result.status === "valid") { + return result.result; + } + } + + for (const result of results) { + if (result.result.status === "dirty") { + // add issues from dirty option + ctx.common.issues.push(...result.ctx.common.issues); + return result.result; + } + } // return invalid + + + const unionErrors = results.map(result => new ZodError_1.ZodError(result.ctx.common.issues)); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_union, + unionErrors }); return parseUtil_1.INVALID; } - return (0, parseUtil_1.OK)(input.data); - } + if (ctx.common.async) { + return Promise.all(options.map(async option => { + const childCtx = { ...ctx, + common: { ...ctx.common, + issues: [] + }, + parent: null + }; + return { + result: await option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }), + ctx: childCtx + }; + })).then(handleResults); + } else { + let dirty = undefined; + const issues = []; -} + for (const option of options) { + const childCtx = { ...ctx, + common: { ...ctx.common, + issues: [] + }, + parent: null + }; -exports.ZodBigInt = ZodBigInt; + const result = option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }); -ZodBigInt.create = params => { - return new ZodBigInt({ - typeName: ZodFirstPartyTypeKind.ZodBigInt, - ...processCreateParams(params) - }); -}; + if (result.status === "valid") { + return result; + } else if (result.status === "dirty" && !dirty) { + dirty = { + result, + ctx: childCtx + }; + } -class ZodBoolean extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + if (childCtx.common.issues.length) { + issues.push(childCtx.common.issues); + } + } - if (parsedType !== parseUtil_1.ZodParsedType.boolean) { - const ctx = this._getOrReturnCtx(input); + if (dirty) { + ctx.common.issues.push(...dirty.ctx.common.issues); + return dirty.result; + } + const unionErrors = issues.map(issues => new ZodError_1.ZodError(issues)); (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.boolean, - received: ctx.parsedType + code: ZodError_1.ZodIssueCode.invalid_union, + unionErrors }); return parseUtil_1.INVALID; } + } - return (0, parseUtil_1.OK)(input.data); + get options() { + return this._def.options; } } -exports.ZodBoolean = ZodBoolean; +exports.ZodUnion = ZodUnion; -ZodBoolean.create = params => { - return new ZodBoolean({ - typeName: ZodFirstPartyTypeKind.ZodBoolean, +ZodUnion.create = (types, params) => { + return new ZodUnion({ + options: types, + typeName: ZodFirstPartyTypeKind.ZodUnion, ...processCreateParams(params) }); }; -class ZodDate extends ZodType { +class ZodDiscriminatedUnion extends ZodType { _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.date) { - const ctx = this._getOrReturnCtx(input); + const { + ctx + } = this._processInputParams(input); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.date, + expected: parseUtil_1.ZodParsedType.object, received: ctx.parsedType }); return parseUtil_1.INVALID; } - if (isNaN(input.data.getTime())) { - const ctx = this._getOrReturnCtx(input); + const discriminator = this.discriminator; + const discriminatorValue = ctx.data[discriminator]; + const option = this.options.get(discriminatorValue); + if (!option) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_date + code: ZodError_1.ZodIssueCode.invalid_union_discriminator, + options: this.validDiscriminatorValues, + path: [discriminator] }); return parseUtil_1.INVALID; } - return { - status: "valid", - value: new Date(input.data.getTime()) - }; - } - -} - -exports.ZodDate = ZodDate; - -ZodDate.create = params => { - return new ZodDate({ - typeName: ZodFirstPartyTypeKind.ZodDate, - ...processCreateParams(params) - }); -}; - -class ZodUndefined extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.undefined, - received: ctx.parsedType + if (ctx.common.async) { + return option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } else { + return option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx }); - return parseUtil_1.INVALID; } - - return (0, parseUtil_1.OK)(input.data); } -} + get discriminator() { + return this._def.discriminator; + } -exports.ZodUndefined = ZodUndefined; + get validDiscriminatorValues() { + return Array.from(this.options.keys()); + } -ZodUndefined.create = params => { - return new ZodUndefined({ - typeName: ZodFirstPartyTypeKind.ZodUndefined, - ...processCreateParams(params) - }); -}; + get options() { + return this._def.options; + } + /** + * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. + * However, it only allows a union of objects, all of which need to share a discriminator property. This property must + * have a different value for each object in the union. + * @param discriminator the name of the discriminator property + * @param types an array of object schemas + * @param params + */ -class ZodNull extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.null) { - const ctx = this._getOrReturnCtx(input); + static create(discriminator, types, params) { + // Get all the valid discriminator values + const options = new Map(); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.null, - received: ctx.parsedType + try { + types.forEach(type => { + const discriminatorValue = type.shape[discriminator].value; + options.set(discriminatorValue, type); }); - return parseUtil_1.INVALID; + } catch (e) { + throw new Error("The discriminator value could not be extracted from all the provided schemas"); + } // Assert that all the discriminator values are unique + + + if (options.size !== types.length) { + throw new Error("Some of the discriminator values are not unique"); } - return (0, parseUtil_1.OK)(input.data); + return new ZodDiscriminatedUnion({ + typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, + discriminator, + options, + ...processCreateParams(params) + }); } } -exports.ZodNull = ZodNull; +exports.ZodDiscriminatedUnion = ZodDiscriminatedUnion; -ZodNull.create = params => { - return new ZodNull({ - typeName: ZodFirstPartyTypeKind.ZodNull, - ...processCreateParams(params) - }); -}; +function mergeValues(a, b) { + const aType = (0, parseUtil_1.getParsedType)(a); + const bType = (0, parseUtil_1.getParsedType)(b); -class ZodAny extends ZodType { - constructor() { - super(...arguments); // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. + if (a === b) { + return { + valid: true, + data: a + }; + } else if (aType === parseUtil_1.ZodParsedType.object && bType === parseUtil_1.ZodParsedType.object) { + const bKeys = util_1.util.objectKeys(b); + const sharedKeys = util_1.util.objectKeys(a).filter(key => bKeys.indexOf(key) !== -1); + const newObj = { ...a, + ...b + }; - this._any = true; - } + for (const key of sharedKeys) { + const sharedValue = mergeValues(a[key], b[key]); - _parse(input) { - return (0, parseUtil_1.OK)(input.data); - } + if (!sharedValue.valid) { + return { + valid: false + }; + } -} + newObj[key] = sharedValue.data; + } + + return { + valid: true, + data: newObj + }; + } else if (aType === parseUtil_1.ZodParsedType.array && bType === parseUtil_1.ZodParsedType.array) { + if (a.length !== b.length) { + return { + valid: false + }; + } -exports.ZodAny = ZodAny; + const newArray = []; -ZodAny.create = params => { - return new ZodAny({ - typeName: ZodFirstPartyTypeKind.ZodAny, - ...processCreateParams(params) - }); -}; + for (let index = 0; index < a.length; index++) { + const itemA = a[index]; + const itemB = b[index]; + const sharedValue = mergeValues(itemA, itemB); -class ZodUnknown extends ZodType { - constructor() { - super(...arguments); // required + if (!sharedValue.valid) { + return { + valid: false + }; + } - this._unknown = true; - } + newArray.push(sharedValue.data); + } - _parse(input) { - return (0, parseUtil_1.OK)(input.data); + return { + valid: true, + data: newArray + }; + } else if (aType === parseUtil_1.ZodParsedType.date && bType === parseUtil_1.ZodParsedType.date && +a === +b) { + return { + valid: true, + data: a + }; + } else { + return { + valid: false + }; } - } -exports.ZodUnknown = ZodUnknown; - -ZodUnknown.create = params => { - return new ZodUnknown({ - typeName: ZodFirstPartyTypeKind.ZodUnknown, - ...processCreateParams(params) - }); -}; - -class ZodNever extends ZodType { +class ZodIntersection extends ZodType { _parse(input) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.never, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + const { + status, + ctx + } = this._processInputParams(input); -} + const handleParsed = (parsedLeft, parsedRight) => { + if ((0, parseUtil_1.isAborted)(parsedLeft) || (0, parseUtil_1.isAborted)(parsedRight)) { + return parseUtil_1.INVALID; + } -exports.ZodNever = ZodNever; + const merged = mergeValues(parsedLeft.value, parsedRight.value); -ZodNever.create = params => { - return new ZodNever({ - typeName: ZodFirstPartyTypeKind.ZodNever, - ...processCreateParams(params) - }); -}; + if (!merged.valid) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_intersection_types + }); + return parseUtil_1.INVALID; + } -class ZodVoid extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + if ((0, parseUtil_1.isDirty)(parsedLeft) || (0, parseUtil_1.isDirty)(parsedRight)) { + status.dirty(); + } - if (parsedType !== parseUtil_1.ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); + return { + status: status.value, + value: merged.data + }; + }; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.void, - received: ctx.parsedType + if (ctx.common.async) { + return Promise.all([this._def.left._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), this._def.right._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + })]).then(_ref => { + let [left, right] = _ref; + return handleParsed(left, right); }); - return parseUtil_1.INVALID; + } else { + return handleParsed(this._def.left._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), this._def.right._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + })); } - - return (0, parseUtil_1.OK)(input.data); } } -exports.ZodVoid = ZodVoid; +exports.ZodIntersection = ZodIntersection; -ZodVoid.create = params => { - return new ZodVoid({ - typeName: ZodFirstPartyTypeKind.ZodVoid, +ZodIntersection.create = (left, right, params) => { + return new ZodIntersection({ + left: left, + right: right, + typeName: ZodFirstPartyTypeKind.ZodIntersection, ...processCreateParams(params) }); }; -class ZodArray extends ZodType { +class ZodTuple extends ZodType { _parse(input) { const { - ctx, - status + status, + ctx } = this._processInputParams(input); - const def = this._def; - if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, @@ -2516,173 +2618,82 @@ class ZodArray extends ZodType { return parseUtil_1.INVALID; } - if (def.minLength !== null) { - if (ctx.data.length < def.minLength.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: def.minLength.value, - type: "array", - inclusive: true, - message: def.minLength.message - }); - status.dirty(); - } - } - - if (def.maxLength !== null) { - if (ctx.data.length > def.maxLength.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: def.maxLength.value, - type: "array", - inclusive: true, - message: def.maxLength.message - }); - status.dirty(); - } - } - - if (ctx.common.async) { - return Promise.all(ctx.data.map((item, i) => { - return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - })).then(result => { - return parseUtil_1.ParseStatus.mergeArray(status, result); + if (ctx.data.length < this._def.items.length) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: this._def.items.length, + inclusive: true, + type: "array" }); + return parseUtil_1.INVALID; } - const result = ctx.data.map((item, i) => { - return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - }); - return parseUtil_1.ParseStatus.mergeArray(status, result); - } - - get element() { - return this._def.type; - } - - min(minLength, message) { - return new ZodArray({ ...this._def, - minLength: { - value: minLength, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } - - max(maxLength, message) { - return new ZodArray({ ...this._def, - maxLength: { - value: maxLength, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } - - length(len, message) { - return this.min(len, message).max(len, message); - } - - nonempty(message) { - return this.min(1, message); - } - -} - -exports.ZodArray = ZodArray; - -ZodArray.create = (schema, params) => { - return new ZodArray({ - type: schema, - minLength: null, - maxLength: null, - typeName: ZodFirstPartyTypeKind.ZodArray, - ...processCreateParams(params) - }); -}; ///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodObject ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// - - -var objectUtil; - -(function (objectUtil) { - objectUtil.mergeShapes = (first, second) => { - return { ...first, - ...second // second overwrites first - - }; - }; -})(objectUtil = exports.objectUtil || (exports.objectUtil = {})); + const rest = this._def.rest; -const AugmentFactory = def => augmentation => { - return new ZodObject({ ...def, - shape: () => ({ ...def.shape(), - ...augmentation - }) - }); -}; + if (!rest && ctx.data.length > this._def.items.length) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: this._def.items.length, + inclusive: true, + type: "array" + }); + status.dirty(); + } -function deepPartialify(schema) { - if (schema instanceof ZodObject) { - const newShape = {}; + const items = ctx.data.map((item, itemIndex) => { + const schema = this._def.items[itemIndex] || this._def.rest; + if (!schema) return null; + return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); + }).filter(x => !!x); // filter nulls - for (const key in schema.shape) { - const fieldSchema = schema.shape[key]; - newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + if (ctx.common.async) { + return Promise.all(items).then(results => { + return parseUtil_1.ParseStatus.mergeArray(status, results); + }); + } else { + return parseUtil_1.ParseStatus.mergeArray(status, items); } + } - return new ZodObject({ ...schema._def, - shape: () => newShape + get items() { + return this._def.items; + } + + rest(rest) { + return new ZodTuple({ ...this._def, + rest }); - } else if (schema instanceof ZodArray) { - return ZodArray.create(deepPartialify(schema.element)); - } else if (schema instanceof ZodOptional) { - return ZodOptional.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodNullable) { - return ZodNullable.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodTuple) { - return ZodTuple.create(schema.items.map(item => deepPartialify(item))); - } else { - return schema; } -} -class ZodObject extends ZodType { - constructor() { - super(...arguments); - this._cached = null; - /** - * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. - * If you want to pass through unknown properties, use `.passthrough()` instead. - */ +} - this.nonstrict = this.passthrough; - this.augment = AugmentFactory(this._def); - this.extend = AugmentFactory(this._def); - } +exports.ZodTuple = ZodTuple; - _getCached() { - if (this._cached !== null) return this._cached; +ZodTuple.create = (schemas, params) => { + return new ZodTuple({ + items: schemas, + typeName: ZodFirstPartyTypeKind.ZodTuple, + rest: null, + ...processCreateParams(params) + }); +}; - const shape = this._def.shape(); +class ZodRecord extends ZodType { + get keySchema() { + return this._def.keyType; + } - const keys = util_1.util.objectKeys(shape); - return this._cached = { - shape, - keys - }; + get valueSchema() { + return this._def.valueType; } _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.object) { - const ctx = this._getOrReturnCtx(input); + const { + status, + ctx + } = this._processInputParams(input); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, expected: parseUtil_1.ZodParsedType.object, @@ -2691,1147 +2702,880 @@ class ZodObject extends ZodType { return parseUtil_1.INVALID; } - const { - status, - ctx - } = this._processInputParams(input); - - const { - shape, - keys: shapeKeys - } = this._getCached(); - - const extraKeys = []; - - for (const key in ctx.data) { - if (!shapeKeys.includes(key)) { - extraKeys.push(key); - } - } - const pairs = []; + const keyType = this._def.keyType; + const valueType = this._def.valueType; - for (const key of shapeKeys) { - const keyValidator = shape[key]; - const value = ctx.data[key]; + for (const key in ctx.data) { pairs.push({ - key: { - status: "valid", - value: key - }, - value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), - alwaysSet: key in ctx.data + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), + value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)) }); } - if (this._def.catchall instanceof ZodNever) { - const unknownKeys = this._def.unknownKeys; - - if (unknownKeys === "passthrough") { - for (const key of extraKeys) { - pairs.push({ - key: { - status: "valid", - value: key - }, - value: { - status: "valid", - value: ctx.data[key] - } - }); - } - } else if (unknownKeys === "strict") { - if (extraKeys.length > 0) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.unrecognized_keys, - keys: extraKeys - }); - status.dirty(); - } - } else if (unknownKeys === "strip") {} else { - throw new Error("Internal ZodObject error: invalid unknownKeys value."); - } - } else { - // run catchall validation - const catchall = this._def.catchall; - - for (const key of extraKeys) { - const value = ctx.data[key]; - pairs.push({ - key: { - status: "valid", - value: key - }, - value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) - ), - alwaysSet: key in ctx.data - }); - } - } - if (ctx.common.async) { - return Promise.resolve().then(async () => { - const syncPairs = []; - - for (const pair of pairs) { - const key = await pair.key; - syncPairs.push({ - key, - value: await pair.value, - alwaysSet: pair.alwaysSet - }); - } - - return syncPairs; - }).then(syncPairs => { - return parseUtil_1.ParseStatus.mergeObjectSync(status, syncPairs); - }); + return parseUtil_1.ParseStatus.mergeObjectAsync(status, pairs); } else { return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); } } - get shape() { - return this._def.shape(); - } - - strict(message) { - errorUtil_1.errorUtil.errToObj; - return new ZodObject({ ...this._def, - unknownKeys: "strict", - ...(message !== undefined ? { - errorMap: (issue, ctx) => { - var _a, _b, _c, _d; - - const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError; - if (issue.code === "unrecognized_keys") return { - message: (_d = errorUtil_1.errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError - }; - return { - message: defaultError - }; - } - } : {}) - }); - } - - strip() { - return new ZodObject({ ...this._def, - unknownKeys: "strip" - }); - } - - passthrough() { - return new ZodObject({ ...this._def, - unknownKeys: "passthrough" - }); - } - - setKey(key, schema) { - return this.augment({ - [key]: schema - }); + get element() { + return this._def.valueType; } - /** - * Prior to zod@1.0.12 there was a bug in the - * inferred type of merged objects. Please - * upgrade if you are experiencing issues. - */ + static create(first, second, third) { + if (second instanceof ZodType) { + return new ZodRecord({ + keyType: first, + valueType: second, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(third) + }); + } - merge(merging) { - // const mergedShape = objectUtil.mergeShapes( - // this._def.shape(), - // merging._def.shape() - // ); - const merged = new ZodObject({ - unknownKeys: merging._def.unknownKeys, - catchall: merging._def.catchall, - shape: () => objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), - typeName: ZodFirstPartyTypeKind.ZodObject + return new ZodRecord({ + keyType: ZodString.create(), + valueType: first, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(second) }); - return merged; } - catchall(index) { - return new ZodObject({ ...this._def, - catchall: index - }); - } +} - pick(mask) { - const shape = {}; - util_1.util.objectKeys(mask).map(key => { - shape[key] = this.shape[key]; - }); - return new ZodObject({ ...this._def, - shape: () => shape - }); - } +exports.ZodRecord = ZodRecord; - omit(mask) { - const shape = {}; - util_1.util.objectKeys(this.shape).map(key => { - if (util_1.util.objectKeys(mask).indexOf(key) === -1) { - shape[key] = this.shape[key]; - } - }); - return new ZodObject({ ...this._def, - shape: () => shape +class ZodMap extends ZodType { + _parse(input) { + const { + status, + ctx + } = this._processInputParams(input); + + if (ctx.parsedType !== parseUtil_1.ZodParsedType.map) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.map, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } + + const keyType = this._def.keyType; + const valueType = this._def.valueType; + const pairs = [...ctx.data.entries()].map((_ref2, index) => { + let [key, value] = _ref2; + return { + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), + value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])) + }; }); - } - deepPartial() { - return deepPartialify(this); - } + if (ctx.common.async) { + const finalMap = new Map(); + return Promise.resolve().then(async () => { + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; - partial(mask) { - const newShape = {}; + if (key.status === "aborted" || value.status === "aborted") { + return parseUtil_1.INVALID; + } - if (mask) { - util_1.util.objectKeys(this.shape).map(key => { - if (util_1.util.objectKeys(mask).indexOf(key) === -1) { - newShape[key] = this.shape[key]; - } else { - newShape[key] = this.shape[key].optional(); + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + + finalMap.set(key.value, value.value); } - }); - return new ZodObject({ ...this._def, - shape: () => newShape + + return { + status: status.value, + value: finalMap + }; }); } else { - for (const key in this.shape) { - const fieldSchema = this.shape[key]; - newShape[key] = fieldSchema.optional(); - } - } + const finalMap = new Map(); - return new ZodObject({ ...this._def, - shape: () => newShape - }); - } + for (const pair of pairs) { + const key = pair.key; + const value = pair.value; - required() { - const newShape = {}; + if (key.status === "aborted" || value.status === "aborted") { + return parseUtil_1.INVALID; + } - for (const key in this.shape) { - const fieldSchema = this.shape[key]; - let newField = fieldSchema; + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } - while (newField instanceof ZodOptional) { - newField = newField._def.innerType; + finalMap.set(key.value, value.value); } - newShape[key] = newField; + return { + status: status.value, + value: finalMap + }; } - - return new ZodObject({ ...this._def, - shape: () => newShape - }); } } -exports.ZodObject = ZodObject; - -ZodObject.create = (shape, params) => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params) - }); -}; - -ZodObject.strictCreate = (shape, params) => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strict", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params) - }); -}; +exports.ZodMap = ZodMap; -ZodObject.lazycreate = (shape, params) => { - return new ZodObject({ - shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, +ZodMap.create = (keyType, valueType, params) => { + return new ZodMap({ + valueType, + keyType, + typeName: ZodFirstPartyTypeKind.ZodMap, ...processCreateParams(params) }); }; -class ZodUnion extends ZodType { +class ZodSet extends ZodType { _parse(input) { const { + status, ctx } = this._processInputParams(input); - const options = this._def.options; - - function handleResults(results) { - // return first issue-free validation if it exists - for (const result of results) { - if (result.result.status === "valid") { - return result.result; - } - } - - for (const result of results) { - if (result.result.status === "dirty") { - // add issues from dirty option - ctx.common.issues.push(...result.ctx.common.issues); - return result.result; - } - } // return invalid - - - const unionErrors = results.map(result => new ZodError_1.ZodError(result.ctx.common.issues)); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.set) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union, - unionErrors + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.set, + received: ctx.parsedType }); return parseUtil_1.INVALID; } - if (ctx.common.async) { - return Promise.all(options.map(async option => { - const childCtx = { ...ctx, - common: { ...ctx.common, - issues: [] - }, - parent: null - }; - return { - result: await option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: childCtx - }), - ctx: childCtx - }; - })).then(handleResults); - } else { - let dirty = undefined; - const issues = []; + const def = this._def; - for (const option of options) { - const childCtx = { ...ctx, - common: { ...ctx.common, - issues: [] - }, - parent: null - }; + if (def.minSize !== null) { + if (ctx.data.size < def.minSize.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: def.minSize.value, + type: "set", + inclusive: true, + message: def.minSize.message + }); + status.dirty(); + } + } - const result = option._parseSync({ - data: ctx.data, - path: ctx.path, - parent: childCtx + if (def.maxSize !== null) { + if (ctx.data.size > def.maxSize.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: def.maxSize.value, + type: "set", + inclusive: true, + message: def.maxSize.message }); + status.dirty(); + } + } + + const valueType = this._def.valueType; + + function finalizeSet(elements) { + const parsedSet = new Set(); + + for (const element of elements) { + if (element.status === "aborted") return parseUtil_1.INVALID; + if (element.status === "dirty") status.dirty(); + parsedSet.add(element.value); + } + + return { + status: status.value, + value: parsedSet + }; + } + + const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i))); - if (result.status === "valid") { - return result; - } else if (result.status === "dirty" && !dirty) { - dirty = { - result, - ctx: childCtx - }; - } + if (ctx.common.async) { + return Promise.all(elements).then(elements => finalizeSet(elements)); + } else { + return finalizeSet(elements); + } + } - if (childCtx.common.issues.length) { - issues.push(childCtx.common.issues); - } + min(minSize, message) { + return new ZodSet({ ...this._def, + minSize: { + value: minSize, + message: errorUtil_1.errorUtil.toString(message) } + }); + } - if (dirty) { - ctx.common.issues.push(...dirty.ctx.common.issues); - return dirty.result; + max(maxSize, message) { + return new ZodSet({ ...this._def, + maxSize: { + value: maxSize, + message: errorUtil_1.errorUtil.toString(message) } + }); + } - const unionErrors = issues.map(issues => new ZodError_1.ZodError(issues)); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union, - unionErrors - }); - return parseUtil_1.INVALID; - } + size(size, message) { + return this.min(size, message).max(size, message); } - get options() { - return this._def.options; + nonempty(message) { + return this.min(1, message); } } -exports.ZodUnion = ZodUnion; +exports.ZodSet = ZodSet; -ZodUnion.create = (types, params) => { - return new ZodUnion({ - options: types, - typeName: ZodFirstPartyTypeKind.ZodUnion, +ZodSet.create = (valueType, params) => { + return new ZodSet({ + valueType, + minSize: null, + maxSize: null, + typeName: ZodFirstPartyTypeKind.ZodSet, ...processCreateParams(params) }); }; -class ZodDiscriminatedUnion extends ZodType { +class ZodFunction extends ZodType { + constructor() { + super(...arguments); + this.validate = this.implement; + } + _parse(input) { + var _this = this; + const { ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { + if (ctx.parsedType !== parseUtil_1.ZodParsedType.function) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.object, + expected: parseUtil_1.ZodParsedType.function, received: ctx.parsedType }); return parseUtil_1.INVALID; } - const discriminator = this.discriminator; - const discriminatorValue = ctx.data[discriminator]; - const option = this.options.get(discriminatorValue); - - if (!option) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union_discriminator, - options: this.validDiscriminatorValues, - path: [discriminator] + function makeArgsIssue(args, error) { + return (0, parseUtil_1.makeIssue)({ + data: args, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), + issueData: { + code: ZodError_1.ZodIssueCode.invalid_arguments, + argumentsError: error + } }); - return parseUtil_1.INVALID; } - if (ctx.common.async) { - return option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); - } else { - return option._parseSync({ - data: ctx.data, + function makeReturnsIssue(returns, error) { + return (0, parseUtil_1.makeIssue)({ + data: returns, path: ctx.path, - parent: ctx + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), + issueData: { + code: ZodError_1.ZodIssueCode.invalid_return_type, + returnTypeError: error + } }); } - } - - get discriminator() { - return this._def.discriminator; - } - - get validDiscriminatorValues() { - return Array.from(this.options.keys()); - } - - get options() { - return this._def.options; - } - /** - * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. - * However, it only allows a union of objects, all of which need to share a discriminator property. This property must - * have a different value for each object in the union. - * @param discriminator the name of the discriminator property - * @param types an array of object schemas - * @param params - */ + const params = { + errorMap: ctx.common.contextualErrorMap + }; + const fn = ctx.data; - static create(discriminator, types, params) { - // Get all the valid discriminator values - const options = new Map(); + if (this._def.returns instanceof ZodPromise) { + return (0, parseUtil_1.OK)(async function () { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - try { - types.forEach(type => { - const discriminatorValue = type.shape[discriminator].value; - options.set(discriminatorValue, type); + const error = new ZodError_1.ZodError([]); + const parsedArgs = await _this._def.args.parseAsync(args, params).catch(e => { + error.addIssue(makeArgsIssue(args, e)); + throw error; + }); + const result = await fn(...parsedArgs); + const parsedReturns = await _this._def.returns._def.type.parseAsync(result, params).catch(e => { + error.addIssue(makeReturnsIssue(result, e)); + throw error; + }); + return parsedReturns; }); - } catch (e) { - throw new Error("The discriminator value could not be extracted from all the provided schemas"); - } // Assert that all the discriminator values are unique - + } else { + return (0, parseUtil_1.OK)(function () { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } - if (options.size !== types.length) { - throw new Error("Some of the discriminator values are not unique"); - } + const parsedArgs = _this._def.args.safeParse(args, params); - return new ZodDiscriminatedUnion({ - typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, - discriminator, - options, - ...processCreateParams(params) - }); - } + if (!parsedArgs.success) { + throw new ZodError_1.ZodError([makeArgsIssue(args, parsedArgs.error)]); + } -} + const result = fn(...parsedArgs.data); -exports.ZodDiscriminatedUnion = ZodDiscriminatedUnion; + const parsedReturns = _this._def.returns.safeParse(result, params); -function mergeValues(a, b) { - const aType = (0, parseUtil_1.getParsedType)(a); - const bType = (0, parseUtil_1.getParsedType)(b); + if (!parsedReturns.success) { + throw new ZodError_1.ZodError([makeReturnsIssue(result, parsedReturns.error)]); + } - if (a === b) { - return { - valid: true, - data: a - }; - } else if (aType === parseUtil_1.ZodParsedType.object && bType === parseUtil_1.ZodParsedType.object) { - const bKeys = util_1.util.objectKeys(b); - const sharedKeys = util_1.util.objectKeys(a).filter(key => bKeys.indexOf(key) !== -1); - const newObj = { ...a, - ...b - }; + return parsedReturns.data; + }); + } + } - for (const key of sharedKeys) { - const sharedValue = mergeValues(a[key], b[key]); + parameters() { + return this._def.args; + } - if (!sharedValue.valid) { - return { - valid: false - }; - } + returnType() { + return this._def.returns; + } - newObj[key] = sharedValue.data; + args() { + for (var _len3 = arguments.length, items = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + items[_key3] = arguments[_key3]; } - return { - valid: true, - data: newObj - }; - } else if (aType === parseUtil_1.ZodParsedType.array && bType === parseUtil_1.ZodParsedType.array) { - if (a.length !== b.length) { - return { - valid: false - }; - } + return new ZodFunction({ ...this._def, + args: ZodTuple.create(items).rest(ZodUnknown.create()) + }); + } - const newArray = []; + returns(returnType) { + return new ZodFunction({ ...this._def, + returns: returnType + }); + } - for (let index = 0; index < a.length; index++) { - const itemA = a[index]; - const itemB = b[index]; - const sharedValue = mergeValues(itemA, itemB); + implement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } + + strictImplement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } - if (!sharedValue.valid) { - return { - valid: false - }; - } +} - newArray.push(sharedValue.data); - } +exports.ZodFunction = ZodFunction; - return { - valid: true, - data: newArray - }; - } else if (aType === parseUtil_1.ZodParsedType.date && bType === parseUtil_1.ZodParsedType.date && +a === +b) { - return { - valid: true, - data: a - }; - } else { - return { - valid: false - }; +ZodFunction.create = (args, returns, params) => { + return new ZodFunction({ + args: args ? args.rest(ZodUnknown.create()) : ZodTuple.create([]).rest(ZodUnknown.create()), + returns: returns || ZodUnknown.create(), + typeName: ZodFirstPartyTypeKind.ZodFunction, + ...processCreateParams(params) + }); +}; + +class ZodLazy extends ZodType { + get schema() { + return this._def.getter(); } -} -class ZodIntersection extends ZodType { _parse(input) { const { - status, ctx } = this._processInputParams(input); - const handleParsed = (parsedLeft, parsedRight) => { - if ((0, parseUtil_1.isAborted)(parsedLeft) || (0, parseUtil_1.isAborted)(parsedRight)) { - return parseUtil_1.INVALID; - } + const lazySchema = this._def.getter(); - const merged = mergeValues(parsedLeft.value, parsedRight.value); + return lazySchema._parse({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } - if (!merged.valid) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_intersection_types - }); - return parseUtil_1.INVALID; - } +} - if ((0, parseUtil_1.isDirty)(parsedLeft) || (0, parseUtil_1.isDirty)(parsedRight)) { - status.dirty(); - } +exports.ZodLazy = ZodLazy; - return { - status: status.value, - value: merged.data - }; - }; +ZodLazy.create = (getter, params) => { + return new ZodLazy({ + getter: getter, + typeName: ZodFirstPartyTypeKind.ZodLazy, + ...processCreateParams(params) + }); +}; - if (ctx.common.async) { - return Promise.all([this._def.left._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }), this._def.right._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - })]).then(_ref => { - let [left, right] = _ref; - return handleParsed(left, right); +class ZodLiteral extends ZodType { + _parse(input) { + if (input.data !== this._def.value) { + const ctx = this._getOrReturnCtx(input); + + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_literal, + expected: this._def.value }); - } else { - return handleParsed(this._def.left._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }), this._def.right._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - })); + return parseUtil_1.INVALID; } + + return { + status: "valid", + value: input.data + }; + } + + get value() { + return this._def.value; } } -exports.ZodIntersection = ZodIntersection; +exports.ZodLiteral = ZodLiteral; -ZodIntersection.create = (left, right, params) => { - return new ZodIntersection({ - left: left, - right: right, - typeName: ZodFirstPartyTypeKind.ZodIntersection, +ZodLiteral.create = (value, params) => { + return new ZodLiteral({ + value: value, + typeName: ZodFirstPartyTypeKind.ZodLiteral, ...processCreateParams(params) }); }; -class ZodTuple extends ZodType { +function createZodEnum(values) { + return new ZodEnum({ + values: values, + typeName: ZodFirstPartyTypeKind.ZodEnum + }); +} + +class ZodEnum extends ZodType { _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); + if (typeof input.data !== "string") { + const ctx = this._getOrReturnCtx(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { + const expectedValues = this._def.values; (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.array, - received: ctx.parsedType + expected: util_1.util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodError_1.ZodIssueCode.invalid_type }); return parseUtil_1.INVALID; } - if (ctx.data.length < this._def.items.length) { + if (this._def.values.indexOf(input.data) === -1) { + const ctx = this._getOrReturnCtx(input); + + const expectedValues = this._def.values; (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: this._def.items.length, - inclusive: true, - type: "array" + received: ctx.data, + code: ZodError_1.ZodIssueCode.invalid_enum_value, + options: expectedValues }); return parseUtil_1.INVALID; } - const rest = this._def.rest; + return (0, parseUtil_1.OK)(input.data); + } - if (!rest && ctx.data.length > this._def.items.length) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: this._def.items.length, - inclusive: true, - type: "array" - }); - status.dirty(); - } + get options() { + return this._def.values; + } - const items = ctx.data.map((item, itemIndex) => { - const schema = this._def.items[itemIndex] || this._def.rest; - if (!schema) return null; - return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); - }).filter(x => !!x); // filter nulls + get enum() { + const enumValues = {}; - if (ctx.common.async) { - return Promise.all(items).then(results => { - return parseUtil_1.ParseStatus.mergeArray(status, results); - }); - } else { - return parseUtil_1.ParseStatus.mergeArray(status, items); + for (const val of this._def.values) { + enumValues[val] = val; } - } - get items() { - return this._def.items; + return enumValues; } - rest(rest) { - return new ZodTuple({ ...this._def, - rest - }); - } + get Values() { + const enumValues = {}; -} + for (const val of this._def.values) { + enumValues[val] = val; + } -exports.ZodTuple = ZodTuple; + return enumValues; + } -ZodTuple.create = (schemas, params) => { - return new ZodTuple({ - items: schemas, - typeName: ZodFirstPartyTypeKind.ZodTuple, - rest: null, - ...processCreateParams(params) - }); -}; + get Enum() { + const enumValues = {}; -class ZodRecord extends ZodType { - get keySchema() { - return this._def.keyType; - } + for (const val of this._def.values) { + enumValues[val] = val; + } - get valueSchema() { - return this._def.valueType; + return enumValues; } - _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); +} - if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.object, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } +exports.ZodEnum = ZodEnum; +ZodEnum.create = createZodEnum; - const pairs = []; - const keyType = this._def.keyType; - const valueType = this._def.valueType; +class ZodNativeEnum extends ZodType { + _parse(input) { + const nativeEnumValues = util_1.util.getValidEnumValues(this._def.values); - for (const key in ctx.data) { - pairs.push({ - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), - value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)) + const ctx = this._getOrReturnCtx(input); + + if (ctx.parsedType !== parseUtil_1.ZodParsedType.string && ctx.parsedType !== parseUtil_1.ZodParsedType.number) { + const expectedValues = util_1.util.objectValues(nativeEnumValues); + (0, parseUtil_1.addIssueToContext)(ctx, { + expected: util_1.util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodError_1.ZodIssueCode.invalid_type }); + return parseUtil_1.INVALID; } - if (ctx.common.async) { - return parseUtil_1.ParseStatus.mergeObjectAsync(status, pairs); - } else { - return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); + if (nativeEnumValues.indexOf(input.data) === -1) { + const expectedValues = util_1.util.objectValues(nativeEnumValues); + (0, parseUtil_1.addIssueToContext)(ctx, { + received: ctx.data, + code: ZodError_1.ZodIssueCode.invalid_enum_value, + options: expectedValues + }); + return parseUtil_1.INVALID; } - } - get element() { - return this._def.valueType; + return (0, parseUtil_1.OK)(input.data); } - static create(first, second, third) { - if (second instanceof ZodType) { - return new ZodRecord({ - keyType: first, - valueType: second, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(third) - }); - } - - return new ZodRecord({ - keyType: ZodString.create(), - valueType: first, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(second) - }); + get enum() { + return this._def.values; } } -exports.ZodRecord = ZodRecord; +exports.ZodNativeEnum = ZodNativeEnum; -class ZodMap extends ZodType { +ZodNativeEnum.create = (values, params) => { + return new ZodNativeEnum({ + values: values, + typeName: ZodFirstPartyTypeKind.ZodNativeEnum, + ...processCreateParams(params) + }); +}; + +class ZodPromise extends ZodType { _parse(input) { const { - status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.map) { + if (ctx.parsedType !== parseUtil_1.ZodParsedType.promise && ctx.common.async === false) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.map, + expected: parseUtil_1.ZodParsedType.promise, received: ctx.parsedType }); return parseUtil_1.INVALID; } - const keyType = this._def.keyType; - const valueType = this._def.valueType; - const pairs = [...ctx.data.entries()].map((_ref2, index) => { - let [key, value] = _ref2; - return { - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), - value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])) - }; - }); - - if (ctx.common.async) { - const finalMap = new Map(); - return Promise.resolve().then(async () => { - for (const pair of pairs) { - const key = await pair.key; - const value = await pair.value; - - if (key.status === "aborted" || value.status === "aborted") { - return parseUtil_1.INVALID; - } - - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - - return { - status: status.value, - value: finalMap - }; + const promisified = ctx.parsedType === parseUtil_1.ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); + return (0, parseUtil_1.OK)(promisified.then(data => { + return this._def.type.parseAsync(data, { + path: ctx.path, + errorMap: ctx.common.contextualErrorMap }); - } else { - const finalMap = new Map(); - - for (const pair of pairs) { - const key = pair.key; - const value = pair.value; - - if (key.status === "aborted" || value.status === "aborted") { - return parseUtil_1.INVALID; - } - - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - - return { - status: status.value, - value: finalMap - }; - } + })); } } -exports.ZodMap = ZodMap; +exports.ZodPromise = ZodPromise; -ZodMap.create = (keyType, valueType, params) => { - return new ZodMap({ - valueType, - keyType, - typeName: ZodFirstPartyTypeKind.ZodMap, +ZodPromise.create = (schema, params) => { + return new ZodPromise({ + type: schema, + typeName: ZodFirstPartyTypeKind.ZodPromise, ...processCreateParams(params) }); }; -class ZodSet extends ZodType { +class ZodEffects extends ZodType { + innerType() { + return this._def.schema; + } + _parse(input) { const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.set) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.set, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + const effect = this._def.effect || null; - const def = this._def; + if (effect.type === "preprocess") { + const processed = effect.transform(ctx.data); - if (def.minSize !== null) { - if (ctx.data.size < def.minSize.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: def.minSize.value, - type: "set", - inclusive: true, - message: def.minSize.message + if (ctx.common.async) { + return Promise.resolve(processed).then(processed => { + return this._def.schema._parseAsync({ + data: processed, + path: ctx.path, + parent: ctx + }); + }); + } else { + return this._def.schema._parseSync({ + data: processed, + path: ctx.path, + parent: ctx }); - status.dirty(); } } - if (def.maxSize !== null) { - if (ctx.data.size > def.maxSize.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: def.maxSize.value, - type: "set", - inclusive: true, - message: def.maxSize.message - }); - status.dirty(); + const checkCtx = { + addIssue: arg => { + (0, parseUtil_1.addIssueToContext)(ctx, arg); + + if (arg.fatal) { + status.abort(); + } else { + status.dirty(); + } + }, + + get path() { + return ctx.path; } - } - const valueType = this._def.valueType; + }; + checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); - function finalizeSet(elements) { - const parsedSet = new Set(); + if (effect.type === "refinement") { + const executeRefinement = (acc // effect: RefinementEffect + ) => { + const result = effect.refinement(acc, checkCtx); - for (const element of elements) { - if (element.status === "aborted") return parseUtil_1.INVALID; - if (element.status === "dirty") status.dirty(); - parsedSet.add(element.value); + if (ctx.common.async) { + return Promise.resolve(result); + } + + if (result instanceof Promise) { + throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); + } + + return acc; + }; + + if (ctx.common.async === false) { + const inner = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + + if (inner.status === "aborted") return parseUtil_1.INVALID; + if (inner.status === "dirty") status.dirty(); // return value is ignored + + executeRefinement(inner.value); + return { + status: status.value, + value: inner.value + }; + } else { + return this._def.schema._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }).then(inner => { + if (inner.status === "aborted") return parseUtil_1.INVALID; + if (inner.status === "dirty") status.dirty(); + return executeRefinement(inner.value).then(() => { + return { + status: status.value, + value: inner.value + }; + }); + }); } + } + + if (effect.type === "transform") { + if (ctx.common.async === false) { + const base = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); // if (base.status === "aborted") return INVALID; + // if (base.status === "dirty") { + // return { status: "dirty", value: base.value }; + // } - return { - status: status.value, - value: parsedSet - }; - } - const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i))); + if (!(0, parseUtil_1.isValid)(base)) return base; + const result = effect.transform(base.value, checkCtx); - if (ctx.common.async) { - return Promise.all(elements).then(elements => finalizeSet(elements)); - } else { - return finalizeSet(elements); - } - } + if (result instanceof Promise) { + throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead."); + } - min(minSize, message) { - return new ZodSet({ ...this._def, - minSize: { - value: minSize, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } + return { + status: status.value, + value: result + }; + } else { + return this._def.schema._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }).then(base => { + if (!(0, parseUtil_1.isValid)(base)) return base; // if (base.status === "aborted") return INVALID; + // if (base.status === "dirty") { + // return { status: "dirty", value: base.value }; + // } - max(maxSize, message) { - return new ZodSet({ ...this._def, - maxSize: { - value: maxSize, - message: errorUtil_1.errorUtil.toString(message) + return Promise.resolve(effect.transform(base.value, checkCtx)).then(result => ({ + status: status.value, + value: result + })); + }); } - }); - } - - size(size, message) { - return this.min(size, message).max(size, message); - } + } - nonempty(message) { - return this.min(1, message); + util_1.util.assertNever(effect); } } -exports.ZodSet = ZodSet; +exports.ZodEffects = ZodEffects; +exports.ZodTransformer = ZodEffects; -ZodSet.create = (valueType, params) => { - return new ZodSet({ - valueType, - minSize: null, - maxSize: null, - typeName: ZodFirstPartyTypeKind.ZodSet, +ZodEffects.create = (schema, effect, params) => { + return new ZodEffects({ + schema, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect, ...processCreateParams(params) }); }; -class ZodFunction extends ZodType { - constructor() { - super(...arguments); - this.validate = this.implement; - } +ZodEffects.createWithPreprocess = (preprocess, schema, params) => { + return new ZodEffects({ + schema, + effect: { + type: "preprocess", + transform: preprocess + }, + typeName: ZodFirstPartyTypeKind.ZodEffects, + ...processCreateParams(params) + }); +}; +class ZodOptional extends ZodType { _parse(input) { - var _this = this; - - const { - ctx - } = this._processInputParams(input); - - if (ctx.parsedType !== parseUtil_1.ZodParsedType.function) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.function, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } - - function makeArgsIssue(args, error) { - return (0, parseUtil_1.makeIssue)({ - data: args, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), - issueData: { - code: ZodError_1.ZodIssueCode.invalid_arguments, - argumentsError: error - } - }); - } + const parsedType = this._getType(input); - function makeReturnsIssue(returns, error) { - return (0, parseUtil_1.makeIssue)({ - data: returns, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), - issueData: { - code: ZodError_1.ZodIssueCode.invalid_return_type, - returnTypeError: error - } - }); + if (parsedType === parseUtil_1.ZodParsedType.undefined) { + return (0, parseUtil_1.OK)(undefined); } - const params = { - errorMap: ctx.common.contextualErrorMap - }; - const fn = ctx.data; - - if (this._def.returns instanceof ZodPromise) { - return (0, parseUtil_1.OK)(async function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - const error = new ZodError_1.ZodError([]); - const parsedArgs = await _this._def.args.parseAsync(args, params).catch(e => { - error.addIssue(makeArgsIssue(args, e)); - throw error; - }); - const result = await fn(...parsedArgs); - const parsedReturns = await _this._def.returns._def.type.parseAsync(result, params).catch(e => { - error.addIssue(makeReturnsIssue(result, e)); - throw error; - }); - return parsedReturns; - }); - } else { - return (0, parseUtil_1.OK)(function () { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - const parsedArgs = _this._def.args.safeParse(args, params); - - if (!parsedArgs.success) { - throw new ZodError_1.ZodError([makeArgsIssue(args, parsedArgs.error)]); - } - - const result = fn(...parsedArgs.data); - - const parsedReturns = _this._def.returns.safeParse(result, params); - - if (!parsedReturns.success) { - throw new ZodError_1.ZodError([makeReturnsIssue(result, parsedReturns.error)]); - } - - return parsedReturns.data; - }); - } + return this._def.innerType._parse(input); } - parameters() { - return this._def.args; + unwrap() { + return this._def.innerType; } - returnType() { - return this._def.returns; - } +} - args() { - for (var _len3 = arguments.length, items = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - items[_key3] = arguments[_key3]; - } +exports.ZodOptional = ZodOptional; - return new ZodFunction({ ...this._def, - args: ZodTuple.create(items).rest(ZodUnknown.create()) - }); - } +ZodOptional.create = (type, params) => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, + ...processCreateParams(params) + }); +}; - returns(returnType) { - return new ZodFunction({ ...this._def, - returns: returnType - }); - } +class ZodNullable extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - implement(func) { - const validatedFunc = this.parse(func); - return validatedFunc; + if (parsedType === parseUtil_1.ZodParsedType.null) { + return (0, parseUtil_1.OK)(null); + } + + return this._def.innerType._parse(input); } - strictImplement(func) { - const validatedFunc = this.parse(func); - return validatedFunc; + unwrap() { + return this._def.innerType; } } -exports.ZodFunction = ZodFunction; +exports.ZodNullable = ZodNullable; -ZodFunction.create = (args, returns, params) => { - return new ZodFunction({ - args: args ? args.rest(ZodUnknown.create()) : ZodTuple.create([]).rest(ZodUnknown.create()), - returns: returns || ZodUnknown.create(), - typeName: ZodFirstPartyTypeKind.ZodFunction, +ZodNullable.create = (type, params) => { + return new ZodNullable({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodNullable, ...processCreateParams(params) }); }; -class ZodLazy extends ZodType { - get schema() { - return this._def.getter(); - } - +class ZodDefault extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); - const lazySchema = this._def.getter(); + let data = ctx.data; - return lazySchema._parse({ - data: ctx.data, + if (ctx.parsedType === parseUtil_1.ZodParsedType.undefined) { + data = this._def.defaultValue(); + } + + return this._def.innerType._parse({ + data, path: ctx.path, parent: ctx }); } + removeDefault() { + return this._def.innerType; + } + } -exports.ZodLazy = ZodLazy; +exports.ZodDefault = ZodDefault; -ZodLazy.create = (getter, params) => { - return new ZodLazy({ - getter: getter, - typeName: ZodFirstPartyTypeKind.ZodLazy, +ZodDefault.create = (type, params) => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, ...processCreateParams(params) }); }; -class ZodLiteral extends ZodType { +class ZodNaN extends ZodType { _parse(input) { - if (input.data !== this._def.value) { + const parsedType = this._getType(input); + + if (parsedType !== parseUtil_1.ZodParsedType.nan) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_literal, - expected: this._def.value + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.nan, + received: ctx.parsedType }); return parseUtil_1.INVALID; } @@ -3842,1051 +3586,1206 @@ class ZodLiteral extends ZodType { }; } - get value() { - return this._def.value; - } - } -exports.ZodLiteral = ZodLiteral; +exports.ZodNaN = ZodNaN; -ZodLiteral.create = (value, params) => { - return new ZodLiteral({ - value: value, - typeName: ZodFirstPartyTypeKind.ZodLiteral, +ZodNaN.create = params => { + return new ZodNaN({ + typeName: ZodFirstPartyTypeKind.ZodNaN, ...processCreateParams(params) }); }; -function createZodEnum(values) { - return new ZodEnum({ - values: values, - typeName: ZodFirstPartyTypeKind.ZodEnum - }); -} +const custom = (check, params) => { + if (check) return ZodAny.create().refine(check, params); + return ZodAny.create(); +}; -class ZodEnum extends ZodType { - _parse(input) { - if (typeof input.data !== "string") { - const ctx = this._getOrReturnCtx(input); +exports.custom = custom; +exports.late = { + object: ZodObject.lazycreate +}; +var ZodFirstPartyTypeKind; - const expectedValues = this._def.values; - (0, parseUtil_1.addIssueToContext)(ctx, { - expected: util_1.util.joinValues(expectedValues), - received: ctx.parsedType, - code: ZodError_1.ZodIssueCode.invalid_type - }); - return parseUtil_1.INVALID; - } +(function (ZodFirstPartyTypeKind) { + ZodFirstPartyTypeKind["ZodString"] = "ZodString"; + ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber"; + ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN"; + ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt"; + ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean"; + ZodFirstPartyTypeKind["ZodDate"] = "ZodDate"; + ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined"; + ZodFirstPartyTypeKind["ZodNull"] = "ZodNull"; + ZodFirstPartyTypeKind["ZodAny"] = "ZodAny"; + ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown"; + ZodFirstPartyTypeKind["ZodNever"] = "ZodNever"; + ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid"; + ZodFirstPartyTypeKind["ZodArray"] = "ZodArray"; + ZodFirstPartyTypeKind["ZodObject"] = "ZodObject"; + ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion"; + ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; + ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection"; + ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple"; + ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord"; + ZodFirstPartyTypeKind["ZodMap"] = "ZodMap"; + ZodFirstPartyTypeKind["ZodSet"] = "ZodSet"; + ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction"; + ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy"; + ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral"; + ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum"; + ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects"; + ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum"; + ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional"; + ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable"; + ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault"; + ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise"; +})(ZodFirstPartyTypeKind = exports.ZodFirstPartyTypeKind || (exports.ZodFirstPartyTypeKind = {})); - if (this._def.values.indexOf(input.data) === -1) { - const ctx = this._getOrReturnCtx(input); +const instanceOfType = function (cls) { + let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + message: "Input not instance of ".concat(cls.name) + }; + return (0, exports.custom)(data => data instanceof cls, params); +}; - const expectedValues = this._def.values; - (0, parseUtil_1.addIssueToContext)(ctx, { - received: ctx.data, - code: ZodError_1.ZodIssueCode.invalid_enum_value, - options: expectedValues - }); - return parseUtil_1.INVALID; - } +exports.instanceof = instanceOfType; +const stringType = ZodString.create; +exports.string = stringType; +const numberType = ZodNumber.create; +exports.number = numberType; +const nanType = ZodNaN.create; +exports.nan = nanType; +const bigIntType = ZodBigInt.create; +exports.bigint = bigIntType; +const booleanType = ZodBoolean.create; +exports.boolean = booleanType; +const dateType = ZodDate.create; +exports.date = dateType; +const undefinedType = ZodUndefined.create; +exports.undefined = undefinedType; +const nullType = ZodNull.create; +exports.null = nullType; +const anyType = ZodAny.create; +exports.any = anyType; +const unknownType = ZodUnknown.create; +exports.unknown = unknownType; +const neverType = ZodNever.create; +exports.never = neverType; +const voidType = ZodVoid.create; +exports.void = voidType; +const arrayType = ZodArray.create; +exports.array = arrayType; +const objectType = ZodObject.create; +exports.object = objectType; +const strictObjectType = ZodObject.strictCreate; +exports.strictObject = strictObjectType; +const unionType = ZodUnion.create; +exports.union = unionType; +const discriminatedUnionType = ZodDiscriminatedUnion.create; +exports.discriminatedUnion = discriminatedUnionType; +const intersectionType = ZodIntersection.create; +exports.intersection = intersectionType; +const tupleType = ZodTuple.create; +exports.tuple = tupleType; +const recordType = ZodRecord.create; +exports.record = recordType; +const mapType = ZodMap.create; +exports.map = mapType; +const setType = ZodSet.create; +exports.set = setType; +const functionType = ZodFunction.create; +exports.function = functionType; +const lazyType = ZodLazy.create; +exports.lazy = lazyType; +const literalType = ZodLiteral.create; +exports.literal = literalType; +const enumType = ZodEnum.create; +exports.enum = enumType; +const nativeEnumType = ZodNativeEnum.create; +exports.nativeEnum = nativeEnumType; +const promiseType = ZodPromise.create; +exports.promise = promiseType; +const effectsType = ZodEffects.create; +exports.effect = effectsType; +exports.transformer = effectsType; +const optionalType = ZodOptional.create; +exports.optional = optionalType; +const nullableType = ZodNullable.create; +exports.nullable = nullableType; +const preprocessType = ZodEffects.createWithPreprocess; +exports.preprocess = preprocessType; - return (0, parseUtil_1.OK)(input.data); - } +const ostring = () => stringType().optional(); - get options() { - return this._def.values; - } +exports.ostring = ostring; - get enum() { - const enumValues = {}; +const onumber = () => numberType().optional(); - for (const val of this._def.values) { - enumValues[val] = val; - } +exports.onumber = onumber; - return enumValues; - } +const oboolean = () => booleanType().optional(); - get Values() { - const enumValues = {}; +exports.oboolean = oboolean; - for (const val of this._def.values) { - enumValues[val] = val; - } +},{"./ZodError":2,"./helpers/errorUtil":4,"./helpers/parseUtil":5,"./helpers/util":7}],10:[function(require,module,exports){ +"use strict"; - return enumValues; +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; + } +}); - get Enum() { - const enumValues = {}; +var _deviceApiCall = require("./lib/device-api-call.js"); - for (const val of this._def.values) { - enumValues[val] = val; - } +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; } - return enumValues; - } +/** + * 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} + */ -exports.ZodEnum = ZodEnum; -ZodEnum.create = createZodEnum; + /** @type {Params | null | undefined} */ -class ZodNativeEnum extends ZodType { - _parse(input) { - const nativeEnumValues = util_1.util.getValidEnumValues(this._def.values); + /** @type {Result | null | undefined} */ - const ctx = this._getOrReturnCtx(input); + /** @type {import("zod").infer} */ - if (ctx.parsedType !== parseUtil_1.ZodParsedType.string && ctx.parsedType !== parseUtil_1.ZodParsedType.number) { - const expectedValues = util_1.util.objectValues(nativeEnumValues); - (0, parseUtil_1.addIssueToContext)(ctx, { - expected: util_1.util.joinValues(expectedValues), - received: ctx.parsedType, - code: ZodError_1.ZodIssueCode.invalid_type - }); - return parseUtil_1.INVALID; - } + /** + * 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} + */ - if (nativeEnumValues.indexOf(input.data) === -1) { - const expectedValues = util_1.util.objectValues(nativeEnumValues); - (0, parseUtil_1.addIssueToContext)(ctx, { - received: ctx.data, - code: ZodError_1.ZodIssueCode.invalid_enum_value, - options: expectedValues - }); - return parseUtil_1.INVALID; - } + /** + * 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} + */ - return (0, parseUtil_1.OK)(input.data); - } + /** + * @param {import("zod").infer} data + */ + constructor(data) { + _defineProperty(this, "method", 'unknown'); - get enum() { - return this._def.values; - } + _defineProperty(this, "id", null); -} + _defineProperty(this, "paramsValidator", null); -exports.ZodNativeEnum = ZodNativeEnum; + _defineProperty(this, "resultValidator", null); -ZodNativeEnum.create = (values, params) => { - return new ZodNativeEnum({ - values: values, - typeName: ZodFirstPartyTypeKind.ZodNativeEnum, - ...processCreateParams(params) - }); -}; + _defineProperty(this, "params", void 0); -class ZodPromise extends ZodType { - _parse(input) { - const { - ctx - } = this._processInputParams(input); + _defineProperty(this, "throwOnResultKeysMissing", true); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.promise && ctx.common.async === false) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.promise, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + _defineProperty(this, "unwrapResult", true); - const promisified = ctx.parsedType === parseUtil_1.ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); - return (0, parseUtil_1.OK)(promisified.then(data => { - return this._def.type.parseAsync(data, { - path: ctx.path, - errorMap: ctx.common.contextualErrorMap - }); - })); + this.params = data; } + /** + * @returns {import("zod").infer|undefined} + */ -} -exports.ZodPromise = ZodPromise; + validateParams() { + if (this.params === undefined) { + return undefined; + } -ZodPromise.create = (schema, params) => { - return new ZodPromise({ - type: schema, - typeName: ZodFirstPartyTypeKind.ZodPromise, - ...processCreateParams(params) - }); -}; + this._validate(this.params, this.paramsValidator); -class ZodEffects extends ZodType { - innerType() { - return this._def.schema; + return this.params; } + /** + * @param {any|null} incoming + * @returns {import("zod").infer} + */ - _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); - const effect = this._def.effect || null; + validateResult(incoming) { + this._validate(incoming, this.resultValidator); - if (effect.type === "preprocess") { - const processed = effect.transform(ctx.data); + if (!incoming) { + return incoming; + } - if (ctx.common.async) { - return Promise.resolve(processed).then(processed => { - return this._def.schema._parseAsync({ - data: processed, - path: ctx.path, - parent: ctx - }); - }); - } else { - return this._def.schema._parseSync({ - data: processed, - path: ctx.path, - parent: ctx - }); - } + if (!this.unwrapResult) { + return incoming; } - const checkCtx = { - addIssue: arg => { - (0, parseUtil_1.addIssueToContext)(ctx, arg); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } - if (arg.fatal) { - status.abort(); - } else { - status.dirty(); - } - }, + if ('success' in incoming) { + return incoming.success; + } - get path() { - return ctx.path; + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); } + } - }; - checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); - - if (effect.type === "refinement") { - const executeRefinement = (acc // effect: RefinementEffect - ) => { - const result = effect.refinement(acc, checkCtx); - - if (ctx.common.async) { - return Promise.resolve(result); - } + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); + } - if (result instanceof Promise) { - throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); - } + return incoming; + } + /** + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private + */ - return acc; - }; - if (ctx.common.async === false) { - const inner = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); + _validate(data, validator) { + if (!validator) return data; - if (inner.status === "aborted") return parseUtil_1.INVALID; - if (inner.status === "dirty") status.dirty(); // return value is ignored + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); - executeRefinement(inner.value); - return { - status: status.value, - value: inner.value - }; - } else { - return this._def.schema._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }).then(inner => { - if (inner.status === "aborted") return parseUtil_1.INVALID; - if (inner.status === "dirty") status.dirty(); - return executeRefinement(inner.value).then(() => { - return { - status: status.value, - value: inner.value - }; - }); - }); + if (!result) { + throw new Error('unreachable, data failure', data); } - } - if (effect.type === "transform") { - if (ctx.common.async === false) { - const base = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); // if (base.status === "aborted") return INVALID; - // if (base.status === "dirty") { - // return { status: "dirty", value: base.value }; - // } + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } + } + } + } + /** + * @param {import('zod').ZodIssue[]} errors + */ - if (!(0, parseUtil_1.isValid)(base)) return base; - const result = effect.transform(base.value, checkCtx); + 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} + */ - if (result instanceof Promise) { - throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead."); - } - return { - status: status.value, - value: result - }; - } else { - return this._def.schema._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }).then(base => { - if (!(0, parseUtil_1.isValid)(base)) return base; // if (base.status === "aborted") return INVALID; - // if (base.status === "dirty") { - // return { status: "dirty", value: base.value }; - // } + result(response) { + return response; + } + /** + * @returns {import("zod").infer} + */ - return Promise.resolve(effect.transform(base.value, checkCtx)).then(result => ({ - status: status.value, - value: result - })); - }); - } - } - util_1.util.assertNever(effect); + preResultValidation(response) { + return response; } } -exports.ZodEffects = ZodEffects; -exports.ZodTransformer = ZodEffects; - -ZodEffects.create = (schema, effect, params) => { - return new ZodEffects({ - schema, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect, - ...processCreateParams(params) - }); -}; +exports.DeviceApiCall = DeviceApiCall; -ZodEffects.createWithPreprocess = (preprocess, schema, params) => { - return new ZodEffects({ - schema, - effect: { - type: "preprocess", - transform: preprocess - }, - typeName: ZodFirstPartyTypeKind.ZodEffects, - ...processCreateParams(params) - }); -}; +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ -class ZodOptional extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - if (parsedType === parseUtil_1.ZodParsedType.undefined) { - return (0, parseUtil_1.OK)(undefined); - } +exports.DeviceApiCallError = DeviceApiCallError; - return this._def.innerType._parse(input); - } +class SchemaValidationError extends Error { + constructor() { + super(...arguments); - unwrap() { - return this._def.innerType; + _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; -exports.ZodOptional = ZodOptional; + 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; + } -ZodOptional.create = (type, params) => { - return new ZodOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - ...processCreateParams(params) - }); -}; + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } -class ZodNullable extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + break; + } - if (parsedType === parseUtil_1.ZodParsedType.null) { - return (0, parseUtil_1.OK)(null); + default: + { + console.log(name, 'other issue:', issue); + } + } } - return this._def.innerType._parse(input); - } + for (let error of errors) { + log(error); + } - unwrap() { - return this._def.innerType; + 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.ZodNullable = ZodNullable; -ZodNullable.create = (type, params) => { - return new ZodNullable({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodNullable, - ...processCreateParams(params) - }); -}; +exports.SchemaValidationError = SchemaValidationError; -class ZodDefault extends ZodType { - _parse(input) { - const { - ctx - } = this._processInputParams(input); +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; - let data = ctx.data; + /** @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} + */ - if (ctx.parsedType === parseUtil_1.ZodParsedType.undefined) { - data = this._def.defaultValue(); - } - return this._def.innerType._parse({ - data, - path: ctx.path, - parent: ctx - }); - } +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; +} - removeDefault() { - return this._def.innerType; - } +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; -exports.ZodDefault = ZodDefault; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; -ZodDefault.create = (type, params) => { - return new ZodOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - ...processCreateParams(params) - }); -}; + if (validator) { + return validator.parse(data); + } + + return data; +} -class ZodNaN extends ZodType { - _parse(input) { - const parsedType = this._getType(input); +},{}],12:[function(require,module,exports){ +"use strict"; - if (parsedType !== parseUtil_1.ZodParsedType.nan) { - const ctx = this._getOrReturnCtx(input); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.nan, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } +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; } - return { - status: "valid", - value: input.data - }; +/** + * 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.ZodNaN = ZodNaN; - -ZodNaN.create = params => { - return new ZodNaN({ - typeName: ZodFirstPartyTypeKind.ZodNaN, - ...processCreateParams(params) - }); -}; - -const custom = (check, params) => { - if (check) return ZodAny.create().refine(check, params); - return ZodAny.create(); -}; -exports.custom = custom; -exports.late = { - object: ZodObject.lazycreate -}; -var ZodFirstPartyTypeKind; +exports.DeviceApiTransport = DeviceApiTransport; -(function (ZodFirstPartyTypeKind) { - ZodFirstPartyTypeKind["ZodString"] = "ZodString"; - ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber"; - ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN"; - ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt"; - ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean"; - ZodFirstPartyTypeKind["ZodDate"] = "ZodDate"; - ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined"; - ZodFirstPartyTypeKind["ZodNull"] = "ZodNull"; - ZodFirstPartyTypeKind["ZodAny"] = "ZodAny"; - ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown"; - ZodFirstPartyTypeKind["ZodNever"] = "ZodNever"; - ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid"; - ZodFirstPartyTypeKind["ZodArray"] = "ZodArray"; - ZodFirstPartyTypeKind["ZodObject"] = "ZodObject"; - ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion"; - ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; - ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection"; - ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple"; - ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord"; - ZodFirstPartyTypeKind["ZodMap"] = "ZodMap"; - ZodFirstPartyTypeKind["ZodSet"] = "ZodSet"; - ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction"; - ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy"; - ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral"; - ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum"; - ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects"; - ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum"; - ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional"; - ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable"; - ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault"; - ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise"; -})(ZodFirstPartyTypeKind = exports.ZodFirstPartyTypeKind || (exports.ZodFirstPartyTypeKind = {})); +class DeviceApi { + /** @type {DeviceApiTransport} */ -const instanceOfType = function (cls) { - let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { - message: "Input not instance of ".concat(cls.name) - }; - return (0, exports.custom)(data => data instanceof cls, params); -}; + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); -exports.instanceof = instanceOfType; -const stringType = ZodString.create; -exports.string = stringType; -const numberType = ZodNumber.create; -exports.number = numberType; -const nanType = ZodNaN.create; -exports.nan = nanType; -const bigIntType = ZodBigInt.create; -exports.bigint = bigIntType; -const booleanType = ZodBoolean.create; -exports.boolean = booleanType; -const dateType = ZodDate.create; -exports.date = dateType; -const undefinedType = ZodUndefined.create; -exports.undefined = undefinedType; -const nullType = ZodNull.create; -exports.null = nullType; -const anyType = ZodAny.create; -exports.any = anyType; -const unknownType = ZodUnknown.create; -exports.unknown = unknownType; -const neverType = ZodNever.create; -exports.never = neverType; -const voidType = ZodVoid.create; -exports.void = voidType; -const arrayType = ZodArray.create; -exports.array = arrayType; -const objectType = ZodObject.create; -exports.object = objectType; -const strictObjectType = ZodObject.strictCreate; -exports.strictObject = strictObjectType; -const unionType = ZodUnion.create; -exports.union = unionType; -const discriminatedUnionType = ZodDiscriminatedUnion.create; -exports.discriminatedUnion = discriminatedUnionType; -const intersectionType = ZodIntersection.create; -exports.intersection = intersectionType; -const tupleType = ZodTuple.create; -exports.tuple = tupleType; -const recordType = ZodRecord.create; -exports.record = recordType; -const mapType = ZodMap.create; -exports.map = mapType; -const setType = ZodSet.create; -exports.set = setType; -const functionType = ZodFunction.create; -exports.function = functionType; -const lazyType = ZodLazy.create; -exports.lazy = lazyType; -const literalType = ZodLiteral.create; -exports.literal = literalType; -const enumType = ZodEnum.create; -exports.enum = enumType; -const nativeEnumType = ZodNativeEnum.create; -exports.nativeEnum = nativeEnumType; -const promiseType = ZodPromise.create; -exports.promise = promiseType; -const effectsType = ZodEffects.create; -exports.effect = effectsType; -exports.transformer = effectsType; -const optionalType = ZodOptional.create; -exports.optional = optionalType; -const nullableType = ZodNullable.create; -exports.nullable = nullableType; -const preprocessType = ZodEffects.createWithPreprocess; -exports.preprocess = preprocessType; + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ -const ostring = () => stringType().optional(); -exports.ostring = ostring; + 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} + */ -const onumber = () => numberType().optional(); -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", { - 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", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.validate; + return _webkit.WebkitMessagingConfig; } }); -var _deviceApiCall = require("./lib/device-api-call.js"); +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); + } + /** + * 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] + */ -var _deviceApi = require("./lib/device-api.js"); -},{"./lib/device-api-call.js":15,"./lib/device-api.js":16}],15:[function(require,module,exports){ -"use strict"; + 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 {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} + */ -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; } + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); + } +} /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @interface */ -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} */ +exports.Messaging = Messaging; +class MessagingTransport { /** - * 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} + * @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'"); + } /** - * 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 {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 - /** - * @param {import("zod").infer} data - */ - 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} 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); + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ - this.params = data; - } + +class MissingHandler extends Error { /** - * @returns {import("zod").infer|undefined} + * @param {string} message + * @param {string} handlerName */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } +} +/** + * Some re-exports for convenience + */ - validateParams() { - if (this.params === undefined) { - return undefined; - } - this._validate(this.params, this.paramsValidator); +exports.MissingHandler = MissingHandler; - return this.params; - } - /** - * @param {any|null} incoming - * @returns {import("zod").infer} - */ +},{"./webkit.js":14}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; - validateResult(incoming) { - this._validate(incoming, this.resultValidator); +var _messaging = require("./messaging.js"); - if (!incoming) { - return incoming; - } +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 (!this.unwrapResult) { - return incoming; - } +/** + * @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); - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + _defineProperty(this, "globals", void 0); - if ('success' in incoming) { - return incoming.success; - } + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); - } - } + this.config = config; + this.globals = captureGlobals(); - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - return incoming; } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - _validate(data, validator) { - if (!validator) return data; + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); + } + + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } + }; - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + 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 (_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 {import('zod').ZodIssue[]} errors + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - 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} - */ + 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 || '{}'); + } - result(response) { - return 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 + }; + } + } } /** - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - 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", []); + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } - /** - * @param {import("zod").ZodIssue[]} errors * @param {string} name - * @returns {SchemaValidationError} + * @param {Record} [data] */ - 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); - } - } - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars - 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; + 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 + */ -} -/** - * 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} - */ + generateRandomMethod(randomMethodName, callback) { + var _this = this; -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; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -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} - */ + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -exports.createNotification = createNotification; + delete _this.globals.window[randomMethodName]; + } + }); + } -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } - if (validator) { - return validator.parse(data); + createRandMethodName() { + return '_' + this.randomString(); } + /** + * @type {{name: string, length: number}} + */ - return data; -} -},{}],16:[function(require,module,exports){ -"use strict"; + /** + * @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} + */ -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; } + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } + /** + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ -/** - * Platforms should only need to implement this `send` method - */ -class DeviceApiTransport { + + 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); + } /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - async send(_deviceApiCall, _options) { - return undefined; + + + 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; + + /** + * `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; + } + } } } /** - * This is the base Sender class that platforms can will implement. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * Note: The 'handle' method must be implemented, unless you also implement 'send' + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * @typedef CallOptions - * @property {AbortSignal} [signal] + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); + * + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -exports.DeviceApiTransport = DeviceApiTransport; - -class DeviceApi { - /** @type {DeviceApiTransport} */ - - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); +exports.WebkitMessagingTransport = WebkitMessagingTransport; - this.transport = transport; - } +class WebkitMessagingConfig { /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} + * @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 + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); + 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 + */ + + +exports.WebkitMessagingConfig = WebkitMessagingConfig; + +class SecureMessagingParams { /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} + * @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[] + */ - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); + 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 + */ -exports.DeviceApi = DeviceApi; -},{}],17:[function(require,module,exports){ +exports.SecureMessagingParams = SecureMessagingParams; + +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: {} + }; +} + +},{"./messaging.js":13}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5035,7 +4934,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 +5558,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 +5579,7 @@ const constants = { }; exports.constants = constants; -},{}],20:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6413,7 +6312,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 +7143,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 +7216,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 +7366,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 +7818,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 +7973,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 +8251,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 +9320,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 +9536,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 +9745,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 +9851,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 +9918,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 +9979,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],33:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11000,7 +10899,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 +11293,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 +11861,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 +12218,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 +12320,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 +12600,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 +12661,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 +12675,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 +18047,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 +18082,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 +18170,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],64:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18289,7 +18188,7 @@ const constants = { }; exports.constants = constants; -},{}],65:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18779,7 +18678,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 +19184,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 +19225,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 +19383,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 +19391,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 +19402,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 +19419,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 +19459,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 +19631,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 +19685,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 +19785,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 +19833,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..ab9bcf8e1 100644 --- a/dist/autofill.js +++ b/dist/autofill.js @@ -58,1159 +58,1058 @@ 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; + } + + this._validate(this.params, this.paramsValidator); -class MissingHandler extends Error { + 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 - */ + validateResult(incoming) { + this._validate(incoming, this.resultValidator); -exports.MissingHandler = MissingHandler; + if (!incoming) { + return incoming; + } -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + if (!this.unwrapResult) { + return incoming; + } -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; } - -/** - * @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); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); + if ('success' in incoming) { + return incoming.success; + } - 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} - */ - - - 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 _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + break; + } - /** - * `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; + 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; } } /** - * 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", - * }); + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. * - * 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 {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} */ -exports.WebkitMessagingTransport = WebkitMessagingTransport; - -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 - */ +exports.SchemaValidationError = SchemaValidationError; - this.secret = params.secret; - } +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; } /** - * 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 + * 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} */ -exports.WebkitMessagingConfig = WebkitMessagingConfig; - -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; - } - +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; /** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this + * 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; -exports.SecureMessagingParams = SecureMessagingParams; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; -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), + if (validator) { + return validator.parse(data); + } - /** @type {Record} */ - capturedWebkitHandlers: {} - }; + return data; } -},{"../messaging.js":3}],5:[function(require,module,exports){ +},{}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; - -var _messaging = require("../messaging.js"); +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; } /** - * @implements {MessagingTransport} + * Platforms should only need to implement this `send` method */ -class WindowsMessagingTransport { +class DeviceApiTransport { /** - * @param {WindowsMessagingConfig} config + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} */ - constructor(config) { - _defineProperty(this, "config", void 0); - - this.config = config; + async send(_deviceApiCall, _options) { + return undefined; } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars +} +/** + * 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] + */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); + +exports.DeviceApiTransport = DeviceApiTransport; + +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; } /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars - 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'); + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); } - -} - -exports.WindowsMessagingTransport = WindowsMessagingTransport; - -class WindowsMessagingConfig { /** - * @param {object} params - * @param {string} params.featureName + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} */ - constructor(params) { - this.featureName = params.featureName; + + + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); } } -exports.WindowsMessagingConfig = WindowsMessagingConfig; +exports.DeviceApi = DeviceApi; -},{"../messaging.js":3}],6:[function(require,module,exports){ +},{}],5:[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", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.validate; + return _webkit.WebkitMessagingConfig; } }); -var _deviceApiCall = require("./lib/device-api-call.js"); - -var _deviceApi = require("./lib/device-api.js"); - -},{"./lib/device-api-call.js":7,"./lib/device-api.js":8}],7:[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; } +var _webkit = require("./webkit.js"); /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @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() }) + * ``` */ -class DeviceApiCall { - /** @type {string} */ +/** + * @implements {MessagingTransport} + */ +class Messaging { /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} + * @param {WebkitMessagingConfig} config */ - - /** @type {Params | null | undefined} */ - - /** @type {Result | null | undefined} */ - - /** @type {import("zod").infer} */ - + constructor(config) { + this.transport = getTransport(config); + } /** - * 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} + * 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] */ - /** - * 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} - */ + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.transport.notify(name, data); + } /** - * @param {import("zod").infer} 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} */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - _defineProperty(this, "resultValidator", null); + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); + } - _defineProperty(this, "params", void 0); +} +/** + * @interface + */ - _defineProperty(this, "throwOnResultKeysMissing", true); - _defineProperty(this, "unwrapResult", true); +exports.Messaging = Messaging; - this.params = data; +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'"); } /** - * @returns {import("zod").infer|undefined} + * @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 - validateParams() { - if (this.params === undefined) { - return undefined; - } + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); + } - this._validate(this.params, this.paramsValidator); +} +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ - return this.params; - } - /** - * @param {any|null} incoming - * @returns {import("zod").infer} - */ +exports.MessagingTransport = MessagingTransport; - validateResult(incoming) { - this._validate(incoming, this.resultValidator); +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); + } - if (!incoming) { - return incoming; - } + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ - if (!this.unwrapResult) { - return incoming; - } - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } +class MissingHandler extends Error { + /** + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } - if ('success' in incoming) { - return incoming.success; - } +} +/** + * Some re-exports for convenience + */ - 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`'); - } +exports.MissingHandler = MissingHandler; - return incoming; - } - /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private - */ +},{"./webkit.js":6}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; - _validate(data, validator) { - if (!validator) return data; +var _messaging = require("./messaging.js"); - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(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 (!result) { - throw new Error('unreachable, data failure', data); - } +/** + * @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} */ - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } - } - } - } /** - * @param {import('zod').ZodIssue[]} errors + * @param {WebkitMessagingConfig} config */ + constructor(config) { + _defineProperty(this, "config", void 0); + _defineProperty(this, "globals", void 0); - 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} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - result(response) { - return response; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); + } } /** - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - preResultValidation(response) { - return response; - } - -} - -exports.DeviceApiCall = DeviceApiCall; + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); + } -exports.DeviceApiCallError = DeviceApiCallError; + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret + } + }; -class SchemaValidationError extends Error { - constructor() { - super(...arguments); + 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); + } + } - _defineProperty(this, "validationErrors", []); + 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 {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - 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); - } - } + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - break; - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - default: - { - console.log(name, 'other issue:', issue); - } + 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 {string} name + * @param {Record} [data] + */ - 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; + 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 -} -/** - * 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} - */ + 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 + */ -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; + generateRandomMethod(randomMethodName, callback) { + var _this = this; - /** @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} - */ + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -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; -} + delete _this.globals.window[randomMethodName]; + } + }); + } -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} - */ + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.createNotification = createNotification; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - if (validator) { - return validator.parse(data); + /** + * @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} + */ - return data; -} - -},{}],8:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } + /** + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ -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 { + 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); + } /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - async send(_deviceApiCall, _options) { - return undefined; + + + 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; + + /** + * `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; + } + } } } /** - * This is the base Sender class that platforms can will implement. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * Note: The 'handle' method must be implemented, unless you also implement 'send' + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * @typedef CallOptions - * @property {AbortSignal} [signal] + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); + * + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -exports.DeviceApiTransport = DeviceApiTransport; - -class DeviceApi { - /** @type {DeviceApiTransport} */ - - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); +exports.WebkitMessagingTransport = WebkitMessagingTransport; - this.transport = transport; - } +class WebkitMessagingConfig { /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} + * @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 + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); + 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 + */ + + +exports.WebkitMessagingConfig = WebkitMessagingConfig; + +class SecureMessagingParams { /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} + * @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[] + */ - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); + 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 + */ -exports.DeviceApi = DeviceApi; -},{}],9:[function(require,module,exports){ +exports.SecureMessagingParams = SecureMessagingParams; + +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: {} + }; +} + +},{"./messaging.js":5}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1359,7 +1258,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 +1882,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 +1903,7 @@ const constants = { }; exports.constants = constants; -},{}],12:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2737,7 +2636,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 +3467,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 +3540,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 +3690,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 +4142,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 +4297,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 +4575,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 +5644,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 +5860,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 +6069,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 +6175,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 +6242,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 +6303,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],25:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7324,7 +7223,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 +7617,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 +8185,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 +8542,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 +8644,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 +8924,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 +8985,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 +8999,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 +14371,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 +14406,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 +14494,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],56:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14613,7 +14512,7 @@ const constants = { }; exports.constants = constants; -},{}],57:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15103,7 +15002,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 +15086,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 +15127,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 +15285,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 +15293,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 +15304,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 +15321,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 +15361,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 +15533,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 +15587,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 +15687,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 +15735,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..2dafa7744 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; + } -exports.Messaging = Messaging; + format(_mapper) { + const mapper = _mapper || function (issue) { + return issue.message; + }; -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'"); - } - /** - * @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 + const fieldErrors = { + _errors: [] + }; + 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; - request(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('must implement'); - } + while (i < issue.path.length) { + const el = issue.path[i]; + const terminal = i === issue.path.length - 1; -} -/** - * @param {WebkitMessagingConfig | WindowsMessagingConfig} config - * @returns {MessagingTransport} - */ + 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)); + } -exports.MessagingTransport = MessagingTransport; + curr = curr[el]; + i++; + } + } + } + }; -function getTransport(config) { - if (config instanceof _webkit.WebkitMessagingConfig) { - return new _webkit.WebkitMessagingTransport(config); + processError(this); + return fieldErrors; } - if (config instanceof _windows.WindowsMessagingConfig) { - return new _windows.WindowsMessagingTransport(config); + toString() { + return this.message; } - throw new Error('unreachable'); -} -/** - * Thrown when a handler cannot be found - */ - + get message() { + return JSON.stringify(this.issues, null, 2); + } -class MissingHandler extends Error { - /** - * @param {string} message - * @param {string} handlerName - */ - constructor(message, handlerName) { - super(message); - this.handlerName = handlerName; + get isEmpty() { + return this.issues.length === 0; } -} -/** - * Some re-exports for convenience - */ - - -exports.MissingHandler = MissingHandler; - -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; - -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; } - -/** - * @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 (!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) { - var _this$globals$window$, _this$globals$window$2; - - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - - if (!(handler in this.globals.window.webkit.messageHandlers)) { - throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); - } - - const outgoing = { ...data, - messageHandling: { ...data.messageHandling, - secret: this.config.secret - } - }; + flatten() { + let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; + const fieldErrors = {}; + const formErrors = []; - 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); + 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 { - return this.globals.capturedWebkitHandlers[handler](outgoing); + formErrors.push(mapper(sub)); } } - 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 - */ - - - 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 - }; - } - } + return { + formErrors, + fieldErrors + }; } - /** - * @param {string} name - * @param {Record} [data] - */ - - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - this.wkSend(name, data); + get formErrors() { + return this.flatten(); } - /** - * @param {string} name - * @param {Record} [data] - */ - // 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); - } - /** - * 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 - */ +exports.ZodError = ZodError; +ZodError.create = issues => { + const error = new ZodError(issues); + return error; +}; - generateRandomMethod(randomMethodName, callback) { - var _this = this; +const defaultErrorMap = (issue, _ctx) => { + let message; - this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { - enumerable: false, - // configurable, To allow for deletion later - configurable: true, - writable: false, + 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); + } - /** - * @param {any[]} args - */ - value: function () { - callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. + break; - delete _this.globals.window[randomMethodName]; - } - }); - } + case exports.ZodIssueCode.invalid_literal: + message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); + break; - randomString() { - return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; - } + case exports.ZodIssueCode.unrecognized_keys: + message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); + break; - createRandMethodName() { - return '_' + this.randomString(); - } - /** - * @type {{name: string, length: number}} - */ + 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; - /** - * @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 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; - createRandIv() { - return this.globals.getRandomValues(new this.globals.Uint8Array(12)); - } - /** - * @param {BufferSource} ciphertext - * @param {BufferSource} key - * @param {Uint8Array} iv - * @returns {Promise} - */ + case exports.ZodIssueCode.invalid_return_type: + message = "Invalid function return type"; + break; + case exports.ZodIssueCode.invalid_date: + message = "Invalid date"; + break; - 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 - */ + 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; - captureWebkitHandlers(handlerNames) { - const handlers = window.webkit.messageHandlers; - if (!handlers) throw new _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); + 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; - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case exports.ZodIssueCode.custom: + message = "Invalid input"; + break; - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + case exports.ZodIssueCode.invalid_intersection_types: + message = "Intersection results could not be merged"; + break; - /** - * `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 exports.ZodIssueCode.not_multiple_of: + message = "Number must be a multiple of ".concat(issue.multipleOf); + break; + + default: + message = _ctx.defaultError; + util_1.util.assertNever(issue); } -} -/** - * 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") - * ``` - */ + return { + message + }; +}; +exports.defaultErrorMap = defaultErrorMap; +exports.overrideErrorMap = exports.defaultErrorMap; -exports.WebkitMessagingTransport = WebkitMessagingTransport; +const setErrorMap = map => { + exports.overrideErrorMap = map; +}; -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 - */ +exports.setErrorMap = setErrorMap; - this.webkitMessageHandlerNames = params.webkitMessageHandlerNames; - /** - * A string provided by native platforms to be sent with future outgoing - * messages - */ +},{"./helpers/parseUtil":5,"./helpers/util":7}],3:[function(require,module,exports){ +"use strict"; - this.secret = params.secret; - } +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); -} -/** - * 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 (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { + desc = { + enumerable: true, + get: function () { + return m[k]; + } + }; + } + Object.defineProperty(o, k2, desc); +} : function (o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +}); -exports.WebkitMessagingConfig = WebkitMessagingConfig; +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); +}; -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 - */ +Object.defineProperty(exports, "__esModule", { + value: true +}); - this.secret = params.secret; - /** - * The CipherKey as number[] - */ +__exportStar(require("./helpers/parseUtil"), exports); - this.key = params.key; - /** - * The Initial Vector as number[] - */ +__exportStar(require("./helpers/typeAliases"), exports); - this.iv = params.iv; - } +__exportStar(require("./types"), exports); -} -/** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this - */ +__exportStar(require("./ZodError"), exports); +},{"./ZodError":2,"./helpers/parseUtil":5,"./helpers/typeAliases":6,"./types":9}],4:[function(require,module,exports){ +"use strict"; -exports.SecureMessagingParams = SecureMessagingParams; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.errorUtil = void 0; +var errorUtil; -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), +(function (errorUtil) { + errorUtil.errToObj = message => typeof message === "string" ? { + message + } : message || {}; - /** @type {Record} */ - capturedWebkitHandlers: {} - }; -} + errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; +})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); -},{"../messaging.js":3}],5:[function(require,module,exports){ +},{}],5:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; - -var _messaging = require("../messaging.js"); +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; -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; } +const ZodError_1 = require("../ZodError"); -/** - * @implements {MessagingTransport} - */ -class WindowsMessagingTransport { - /** - * @param {WindowsMessagingConfig} config - */ - constructor(config) { - _defineProperty(this, "config", void 0); +const util_1 = require("./util"); - this.config = config; - } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars +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; - 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 + switch (t) { + case "undefined": + return exports.ZodParsedType.undefined; + case "string": + return exports.ZodParsedType.string; - 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'); - } + case "number": + return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; -} + case "boolean": + return exports.ZodParsedType.boolean; -exports.WindowsMessagingTransport = WindowsMessagingTransport; + case "function": + return exports.ZodParsedType.function; -class WindowsMessagingConfig { - /** - * @param {object} params - * @param {string} params.featureName - */ - constructor(params) { - this.featureName = params.featureName; - } + case "bigint": + return exports.ZodParsedType.bigint; -} + case "object": + if (Array.isArray(data)) { + return exports.ZodParsedType.array; + } -exports.WindowsMessagingConfig = WindowsMessagingConfig; + if (data === null) { + return exports.ZodParsedType.null; + } -},{"../messaging.js":3}],6:[function(require,module,exports){ -"use strict"; + if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { + return exports.ZodParsedType.promise; + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.setErrorMap = exports.overrideErrorMap = exports.defaultErrorMap = exports.ZodError = exports.quotelessJson = exports.ZodIssueCode = void 0; + if (typeof Map !== "undefined" && data instanceof Map) { + return exports.ZodParsedType.map; + } -const parseUtil_1 = require("./helpers/parseUtil"); + if (typeof Set !== "undefined" && data instanceof Set) { + return exports.ZodParsedType.set; + } -const util_1 = require("./helpers/util"); + if (typeof Date !== "undefined" && data instanceof Date) { + return exports.ZodParsedType.date; + } -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"]); + return exports.ZodParsedType.object; -const quotelessJson = obj => { - const json = JSON.stringify(obj, null, 2); - return json.replace(/"([^"]+)":/g, "$1:"); + default: + return exports.ZodParsedType.unknown; + } }; -exports.quotelessJson = quotelessJson; +exports.getParsedType = getParsedType; -class ZodError extends Error { - constructor(issues) { - var _this; +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(); - super(); - _this = this; - this.issues = []; + for (const map of maps) { + errorMessage = map(fullIssue, { + data, + defaultError: errorMessage + }).message; + } - this.addIssue = sub => { - this.issues = [...this.issues, sub]; - }; + return { ...issueData, + path: fullPath, + message: issueData.message || errorMessage + }; +}; - this.addIssues = function () { - let subs = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : []; - _this.issues = [..._this.issues, ...subs]; - }; +exports.makeIssue = makeIssue; +exports.EMPTY_PATH = []; - const actualProto = new.target.prototype; +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); +} - if (Object.setPrototypeOf) { - // eslint-disable-next-line ban/ban - Object.setPrototypeOf(this, actualProto); - } else { - this.__proto__ = actualProto; - } +exports.addIssueToContext = addIssueToContext; - this.name = "ZodError"; - this.issues = issues; +class ParseStatus { + constructor() { + this.value = "valid"; } - get errors() { - return this.issues; + dirty() { + if (this.value === "valid") this.value = "dirty"; } - format(_mapper) { - const mapper = _mapper || function (issue) { - return issue.message; - }; - - const fieldErrors = { - _errors: [] - }; - - 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; + abort() { + if (this.value !== "aborted") this.value = "aborted"; + } - 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: [] - }; + static mergeArray(status, results) { + const arrayValue = []; - curr[el]._errors.push(mapper(issue)); - } + for (const s of results) { + if (s.status === "aborted") return exports.INVALID; + if (s.status === "dirty") status.dirty(); + arrayValue.push(s.value); + } - curr = curr[el]; - i++; - } - } - } + return { + status: status.value, + value: arrayValue }; - - processError(this); - return fieldErrors; } - toString() { - return this.message; - } + static async mergeObjectAsync(status, pairs) { + const syncPairs = []; - get message() { - return JSON.stringify(this.issues, null, 2); - } + for (const pair of pairs) { + syncPairs.push({ + key: await pair.key, + value: await pair.value + }); + } - get isEmpty() { - return this.issues.length === 0; + return ParseStatus.mergeObjectSync(status, syncPairs); } - flatten() { - let mapper = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : issue => issue.message; - const fieldErrors = {}; - const formErrors = []; + static mergeObjectSync(status, pairs) { + const finalObject = {}; - 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 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; } } return { - formErrors, - fieldErrors + status: status.value, + value: finalObject }; } - get formErrors() { - return this.flatten(); - } - } -exports.ZodError = ZodError; +exports.ParseStatus = ParseStatus; +exports.INVALID = Object.freeze({ + status: "aborted" +}); -ZodError.create = issues => { - const error = new ZodError(issues); - return error; -}; +const DIRTY = value => ({ + status: "dirty", + value +}); -const defaultErrorMap = (issue, _ctx) => { - let message; +exports.DIRTY = DIRTY; - 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); - } +const OK = value => ({ + status: "valid", + value +}); - break; +exports.OK = OK; + +const isAborted = x => x.status === "aborted"; + +exports.isAborted = isAborted; + +const isDirty = x => x.status === "dirty"; + +exports.isDirty = isDirty; + +const isValid = x => x.status === "valid"; + +exports.isValid = isValid; + +const isAsync = x => typeof Promise !== undefined && x instanceof Promise; + +exports.isAsync = isAsync; + +},{"../ZodError":2,"./util":7}],6:[function(require,module,exports){ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); - case exports.ZodIssueCode.invalid_literal: - message = "Invalid literal value, expected ".concat(JSON.stringify(issue.expected)); - break; +},{}],7:[function(require,module,exports){ +"use strict"; - case exports.ZodIssueCode.unrecognized_keys: - message = "Unrecognized key(s) in object: ".concat(util_1.util.joinValues(issue.keys, ", ")); - break; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.util = void 0; +var util; - case exports.ZodIssueCode.invalid_union: - message = "Invalid input"; - break; +(function (util) { + function assertNever(_x) { + throw new Error(); + } - case exports.ZodIssueCode.invalid_union_discriminator: - message = "Invalid discriminator value. Expected ".concat(util_1.util.joinValues(issue.options)); - break; + util.assertNever = assertNever; - case exports.ZodIssueCode.invalid_enum_value: - message = "Invalid enum value. Expected ".concat(util_1.util.joinValues(issue.options), ", received '").concat(issue.received, "'"); - break; + util.arrayToEnum = items => { + const obj = {}; - case exports.ZodIssueCode.invalid_arguments: - message = "Invalid function arguments"; - break; + for (const item of items) { + obj[item] = item; + } - case exports.ZodIssueCode.invalid_return_type: - message = "Invalid function return type"; - break; + return obj; + }; - case exports.ZodIssueCode.invalid_date: - message = "Invalid date"; - break; + util.getValidEnumValues = obj => { + const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); + const filtered = {}; - case exports.ZodIssueCode.invalid_string: - if (issue.validation !== "regex") message = "Invalid ".concat(issue.validation);else message = "Invalid"; - break; + for (const k of validKeys) { + filtered[k] = obj[k]; + } - 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; + return util.objectValues(filtered); + }; - 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; + util.objectValues = obj => { + return util.objectKeys(obj).map(function (e) { + return obj[e]; + }); + }; - case exports.ZodIssueCode.custom: - message = "Invalid input"; - break; + util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban + ? obj => Object.keys(obj) // eslint-disable-line ban/ban + : object => { + const keys = []; - case exports.ZodIssueCode.invalid_intersection_types: - message = "Intersection results could not be merged"; - break; + for (const key in object) { + if (Object.prototype.hasOwnProperty.call(object, key)) { + keys.push(key); + } + } - 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,941 +671,1201 @@ 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); }; -Object.defineProperty(exports, "__esModule", { - value: true -}); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.z = void 0; + +const mod = __importStar(require("./external")); + +exports.z = mod; + +__exportStar(require("./external"), exports); + +exports.default = mod; + +},{"./external":3}],9:[function(require,module,exports){ +"use strict"; + +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"); + +const parseUtil_1 = require("./helpers/parseUtil"); + +const util_1 = require("./helpers/util"); + +const ZodError_1 = require("./ZodError"); + +class ParseInputLazyPath { + constructor(parent, value, path, key) { + this.parent = parent; + this.data = value; + this._path = path; + this._key = key; + } + + get path() { + return this._path.concat(this._key); + } + +} + +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."); + } + + const error = new ZodError_1.ZodError(ctx.common.issues); + return { + success: false, + error + }; + } +}; + +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."); + } + + if (errorMap) return { + errorMap: errorMap, + description + }; + + 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 + }; + }; + + return { + errorMap: customMap, + description + }; +} + +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); + } + + get description() { + return this._def.description; + } -__exportStar(require("./helpers/parseUtil"), exports); + _getType(input) { + return (0, parseUtil_1.getParsedType)(input.data); + } -__exportStar(require("./helpers/typeAliases"), exports); + _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 + }; + } -__exportStar(require("./types"), exports); + _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 + } + }; + } -__exportStar(require("./ZodError"), exports); + _parseSync(input) { + const result = this._parse(input); -},{"./ZodError":6,"./helpers/parseUtil":9,"./helpers/typeAliases":10,"./types":13}],8:[function(require,module,exports){ -"use strict"; + if ((0, parseUtil_1.isAsync)(result)) { + throw new Error("Synchronous parse encountered promise."); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.errorUtil = void 0; -var errorUtil; + return result; + } -(function (errorUtil) { - errorUtil.errToObj = message => typeof message === "string" ? { - message - } : message || {}; + _parseAsync(input) { + const result = this._parse(input); - errorUtil.toString = message => typeof message === "string" ? message : message === null || message === void 0 ? void 0 : message.message; -})(errorUtil = exports.errorUtil || (exports.errorUtil = {})); + return Promise.resolve(result); + } -},{}],9:[function(require,module,exports){ -"use strict"; + parse(data, params) { + const result = this.safeParse(data, params); + if (result.success) return result.data; + throw result.error; + } -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; + safeParse(data, params) { + var _a; -const ZodError_1 = require("../ZodError"); + 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 util_1 = require("./util"); + const result = this._parseSync({ + data, + path: ctx.path, + parent: ctx + }); -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"]); + return handleResult(ctx, result); + } -const getParsedType = data => { - const t = typeof data; + async parseAsync(data, params) { + const result = await this.safeParseAsync(data, params); + if (result.success) return result.data; + throw result.error; + } - switch (t) { - case "undefined": - return exports.ZodParsedType.undefined; + 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) + }; - case "string": - return exports.ZodParsedType.string; + const maybeAsyncResult = this._parse({ + data, + path: [], + parent: ctx + }); - case "number": - return isNaN(data) ? exports.ZodParsedType.nan : exports.ZodParsedType.number; + const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); + return handleResult(ctx, result); + } - case "boolean": - return exports.ZodParsedType.boolean; + 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; + } + }; - case "function": - return exports.ZodParsedType.function; + return this._refinement((val, ctx) => { + const result = check(val); - case "bigint": - return exports.ZodParsedType.bigint; + const setError = () => ctx.addIssue({ + code: ZodError_1.ZodIssueCode.custom, + ...getIssueProperties(val) + }); - case "object": - if (Array.isArray(data)) { - return exports.ZodParsedType.array; + if (typeof Promise !== "undefined" && result instanceof Promise) { + return result.then(data => { + if (!data) { + setError(); + return false; + } else { + return true; + } + }); } - if (data === null) { - return exports.ZodParsedType.null; + if (!result) { + setError(); + return false; + } else { + return true; } + }); + } - if (data.then && typeof data.then === "function" && data.catch && typeof data.catch === "function") { - return exports.ZodParsedType.promise; + 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; } + }); + } - if (typeof Map !== "undefined" && data instanceof Map) { - return exports.ZodParsedType.map; + _refinement(refinement) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "refinement", + refinement } + }); + } - if (typeof Set !== "undefined" && data instanceof Set) { - return exports.ZodParsedType.set; - } + optional() { + return ZodOptional.create(this); + } - if (typeof Date !== "undefined" && data instanceof Date) { - return exports.ZodParsedType.date; - } + nullable() { + return ZodNullable.create(this); + } - return exports.ZodParsedType.object; + nullish() { + return this.optional().nullable(); + } - default: - return exports.ZodParsedType.unknown; + array() { + return ZodArray.create(this); } -}; -exports.getParsedType = getParsedType; + promise() { + return ZodPromise.create(this); + } -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(); + or(option) { + return ZodUnion.create([this, option]); + } + + and(incoming) { + return ZodIntersection.create(this, incoming); + } + + transform(transform) { + return new ZodEffects({ + schema: this, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect: { + type: "transform", + transform + } + }); + } + + default(def) { + const defaultValueFunc = typeof def === "function" ? def : () => def; + return new ZodDefault({ + innerType: this, + defaultValue: defaultValueFunc, + typeName: ZodFirstPartyTypeKind.ZodDefault + }); + } - for (const map of maps) { - errorMessage = map(fullIssue, { - data, - defaultError: errorMessage - }).message; + describe(description) { + const This = this.constructor; + return new This({ ...this._def, + description + }); } - return { ...issueData, - path: fullPath, - message: issueData.message || errorMessage - }; -}; + isOptional() { + return this.safeParse(undefined).success; + } -exports.makeIssue = makeIssue; -exports.EMPTY_PATH = []; + isNullable() { + return this.safeParse(null).success; + } -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"; - } +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 - dirty() { - if (this.value === "valid") this.value = "dirty"; - } +const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; - abort() { - if (this.value !== "aborted") this.value = "aborted"; - } +class ZodString extends ZodType { + constructor() { + super(...arguments); - static mergeArray(status, results) { - const arrayValue = []; + 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. + */ - for (const s of results) { - if (s.status === "aborted") return exports.INVALID; - if (s.status === "dirty") status.dirty(); - arrayValue.push(s.value); - } - return { - status: status.value, - value: arrayValue - }; + this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); } - static async mergeObjectAsync(status, pairs) { - const syncPairs = []; + _parse(input) { + const parsedType = this._getType(input); - for (const pair of pairs) { - syncPairs.push({ - key: await pair.key, - value: await pair.value - }); - } + if (parsedType !== parseUtil_1.ZodParsedType.string) { + const ctx = this._getOrReturnCtx(input); - return ParseStatus.mergeObjectSync(status, syncPairs); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.string, + received: ctx.parsedType + } // + ); + return parseUtil_1.INVALID; + } - static mergeObjectSync(status, pairs) { - const finalObject = {}; + const status = new parseUtil_1.ParseStatus(); + let ctx = undefined; - 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(); + 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 (typeof value.value !== "undefined" || pair.alwaysSet) { - finalObject[key.value] = value.value; + 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: finalObject + value: input.data }; } -} - -exports.ParseStatus = ParseStatus; -exports.INVALID = Object.freeze({ - status: "aborted" -}); - -const DIRTY = value => ({ - status: "dirty", - value -}); - -exports.DIRTY = DIRTY; - -const OK = value => ({ - status: "valid", - value -}); - -exports.OK = OK; - -const isAborted = x => x.status === "aborted"; + _addCheck(check) { + return new ZodString({ ...this._def, + checks: [...this._def.checks, check] + }); + } -exports.isAborted = isAborted; + email(message) { + return this._addCheck({ + kind: "email", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isDirty = x => x.status === "dirty"; + url(message) { + return this._addCheck({ + kind: "url", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isDirty = isDirty; + uuid(message) { + return this._addCheck({ + kind: "uuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isValid = x => x.status === "valid"; + cuid(message) { + return this._addCheck({ + kind: "cuid", + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isValid = isValid; + regex(regex, message) { + return this._addCheck({ + kind: "regex", + regex: regex, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -const isAsync = x => typeof Promise !== undefined && x instanceof Promise; + min(minLength, message) { + return this._addCheck({ + kind: "min", + value: minLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -exports.isAsync = isAsync; + max(maxLength, message) { + return this._addCheck({ + kind: "max", + value: maxLength, + ...errorUtil_1.errorUtil.errToObj(message) + }); + } -},{"../ZodError":6,"./util":11}],10:[function(require,module,exports){ -"use strict"; + length(len, message) { + return this.min(len, message).max(len, message); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); + get isEmail() { + return !!this._def.checks.find(ch => ch.kind === "email"); + } -},{}],11:[function(require,module,exports){ -"use strict"; + get isURL() { + return !!this._def.checks.find(ch => ch.kind === "url"); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.util = void 0; -var util; + get isUUID() { + return !!this._def.checks.find(ch => ch.kind === "uuid"); + } -(function (util) { - function assertNever(_x) { - throw new Error(); + get isCUID() { + return !!this._def.checks.find(ch => ch.kind === "cuid"); } - util.assertNever = assertNever; + get minLength() { + let min = -Infinity; - util.arrayToEnum = items => { - const obj = {}; + this._def.checks.map(ch => { + if (ch.kind === "min") { + if (min === null || ch.value > min) { + min = ch.value; + } + } + }); - for (const item of items) { - obj[item] = item; - } + return min; + } - return obj; - }; + get maxLength() { + let max = null; - util.getValidEnumValues = obj => { - const validKeys = util.objectKeys(obj).filter(k => typeof obj[obj[k]] !== "number"); - const filtered = {}; + this._def.checks.map(ch => { + if (ch.kind === "max") { + if (max === null || ch.value < max) { + max = ch.value; + } + } + }); - for (const k of validKeys) { - filtered[k] = obj[k]; - } + return max; + } - return util.objectValues(filtered); - }; +} - util.objectValues = obj => { - return util.objectKeys(obj).map(function (e) { - return obj[e]; - }); - }; +exports.ZodString = ZodString; - util.objectKeys = typeof Object.keys === "function" // eslint-disable-line ban/ban - ? obj => Object.keys(obj) // eslint-disable-line ban/ban - : object => { - const keys = []; +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 - for (const key in object) { - if (Object.prototype.hasOwnProperty.call(object, key)) { - keys.push(key); - } - } - return keys; - }; +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); +} - util.find = (arr, checker) => { - for (const item of arr) { - if (checker(item)) return item; - } +class ZodNumber extends ZodType { + constructor() { + super(...arguments); + this.min = this.gte; + this.max = this.lte; + this.step = this.multipleOf; + } - return undefined; - }; + _parse(input) { + const parsedType = this._getType(input); - 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; + if (parsedType !== parseUtil_1.ZodParsedType.number) { + const ctx = this._getOrReturnCtx(input); - 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); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.number, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - util.joinValues = joinValues; -})(util = exports.util || (exports.util = {})); + let ctx = undefined; + const status = new parseUtil_1.ParseStatus(); -},{}],12:[function(require,module,exports){ -"use strict"; + for (const check of this._def.checks) { + if (check.kind === "int") { + if (!util_1.util.isInteger(input.data)) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: "integer", + received: "float", + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "min") { + const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; -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 (tooSmall) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: check.value, + type: "number", + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "max") { + const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; - if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { - desc = { - enumerable: true, - get: function () { - return m[k]; + if (tooBig) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: check.value, + type: "number", + inclusive: check.inclusive, + message: check.message + }); + status.dirty(); + } + } else if (check.kind === "multipleOf") { + if (floatSafeRemainder(input.data, check.value) !== 0) { + ctx = this._getOrReturnCtx(input, ctx); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.not_multiple_of, + multipleOf: check.value, + message: check.message + }); + status.dirty(); + } + } else { + util_1.util.assertNever(check); } + } + + return { + status: status.value, + value: input.data }; } - Object.defineProperty(o, k2, desc); -} : function (o, m, k, k2) { - if (k2 === undefined) k2 = k; - o[k2] = m[k]; -}); + gte(value, message) { + return this.setLimit("min", value, true, errorUtil_1.errorUtil.toString(message)); + } -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; -}); + gt(value, message) { + return this.setLimit("min", value, false, errorUtil_1.errorUtil.toString(message)); + } -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); + lte(value, message) { + return this.setLimit("max", value, true, errorUtil_1.errorUtil.toString(message)); + } - __setModuleDefault(result, mod); + lt(value, message) { + return this.setLimit("max", value, false, errorUtil_1.errorUtil.toString(message)); + } - return result; -}; + setLimit(kind, value, inclusive, message) { + return new ZodNumber({ ...this._def, + checks: [...this._def.checks, { + kind, + value, + inclusive, + message: errorUtil_1.errorUtil.toString(message) + }] + }); + } -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); -}; + _addCheck(check) { + return new ZodNumber({ ...this._def, + checks: [...this._def.checks, check] + }); + } -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.z = void 0; + int(message) { + return this._addCheck({ + kind: "int", + message: errorUtil_1.errorUtil.toString(message) + }); + } -const mod = __importStar(require("./external")); + positive(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: false, + message: errorUtil_1.errorUtil.toString(message) + }); + } -exports.z = mod; + negative(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: false, + message: errorUtil_1.errorUtil.toString(message) + }); + } -__exportStar(require("./external"), exports); + nonpositive(message) { + return this._addCheck({ + kind: "max", + value: 0, + inclusive: true, + message: errorUtil_1.errorUtil.toString(message) + }); + } -exports.default = mod; + nonnegative(message) { + return this._addCheck({ + kind: "min", + value: 0, + inclusive: true, + message: errorUtil_1.errorUtil.toString(message) + }); + } -},{"./external":7}],13:[function(require,module,exports){ -"use strict"; + multipleOf(value, message) { + return this._addCheck({ + kind: "multipleOf", + value: value, + message: errorUtil_1.errorUtil.toString(message) + }); + } -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; + get minValue() { + let min = null; -const errorUtil_1 = require("./helpers/errorUtil"); + for (const ch of this._def.checks) { + if (ch.kind === "min") { + if (min === null || ch.value > min) min = ch.value; + } + } -const parseUtil_1 = require("./helpers/parseUtil"); + return min; + } -const util_1 = require("./helpers/util"); + get maxValue() { + let max = null; -const ZodError_1 = require("./ZodError"); + for (const ch of this._def.checks) { + if (ch.kind === "max") { + if (max === null || ch.value < max) max = ch.value; + } + } -class ParseInputLazyPath { - constructor(parent, value, path, key) { - this.parent = parent; - this.data = value; - this._path = path; - this._key = key; + return max; } - get path() { - return this._path.concat(this._key); + get isInt() { + return !!this._def.checks.find(ch => ch.kind === "int"); } } -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."); - } +exports.ZodNumber = ZodNumber; - const error = new ZodError_1.ZodError(ctx.common.issues); - return { - success: false, - error - }; - } +ZodNumber.create = params => { + return new ZodNumber({ + checks: [], + typeName: ZodFirstPartyTypeKind.ZodNumber, + ...processCreateParams(params) + }); }; -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."); - } - - if (errorMap) return { - errorMap: errorMap, - description - }; +class ZodBigInt extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - 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 - }; - }; + if (parsedType !== parseUtil_1.ZodParsedType.bigint) { + const ctx = this._getOrReturnCtx(input); - return { - errorMap: customMap, - description - }; -} + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.bigint, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } -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); + return (0, parseUtil_1.OK)(input.data); } - get description() { - return this._def.description; - } +} - _getType(input) { - return (0, parseUtil_1.getParsedType)(input.data); - } +exports.ZodBigInt = ZodBigInt; - _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 - }; - } +ZodBigInt.create = params => { + return new ZodBigInt({ + typeName: ZodFirstPartyTypeKind.ZodBigInt, + ...processCreateParams(params) + }); +}; - _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 - } - }; - } +class ZodBoolean extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - _parseSync(input) { - const result = this._parse(input); + if (parsedType !== parseUtil_1.ZodParsedType.boolean) { + const ctx = this._getOrReturnCtx(input); - if ((0, parseUtil_1.isAsync)(result)) { - throw new Error("Synchronous parse encountered promise."); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.boolean, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; } - return result; + return (0, parseUtil_1.OK)(input.data); } - _parseAsync(input) { - const result = this._parse(input); +} - return Promise.resolve(result); - } +exports.ZodBoolean = ZodBoolean; - parse(data, params) { - const result = this.safeParse(data, params); - if (result.success) return result.data; - throw result.error; - } +ZodBoolean.create = params => { + return new ZodBoolean({ + typeName: ZodFirstPartyTypeKind.ZodBoolean, + ...processCreateParams(params) + }); +}; - safeParse(data, params) { - var _a; +class ZodDate extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - 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) - }; + if (parsedType !== parseUtil_1.ZodParsedType.date) { + const ctx = this._getOrReturnCtx(input); - const result = this._parseSync({ - data, - path: ctx.path, - parent: ctx - }); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.date, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - return handleResult(ctx, result); - } + if (isNaN(input.data.getTime())) { + const ctx = this._getOrReturnCtx(input); - async parseAsync(data, params) { - const result = await this.safeParseAsync(data, params); - if (result.success) return result.data; - throw result.error; - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_date + }); + return parseUtil_1.INVALID; + } - 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) + return { + status: "valid", + value: new Date(input.data.getTime()) }; + } - const maybeAsyncResult = this._parse({ - data, - path: [], - parent: ctx - }); +} - const result = await ((0, parseUtil_1.isAsync)(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)); - return handleResult(ctx, result); - } +exports.ZodDate = ZodDate; - 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; - } - }; +ZodDate.create = params => { + return new ZodDate({ + typeName: ZodFirstPartyTypeKind.ZodDate, + ...processCreateParams(params) + }); +}; - return this._refinement((val, ctx) => { - const result = check(val); +class ZodUndefined extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - const setError = () => ctx.addIssue({ - code: ZodError_1.ZodIssueCode.custom, - ...getIssueProperties(val) - }); + if (parsedType !== parseUtil_1.ZodParsedType.undefined) { + const ctx = this._getOrReturnCtx(input); - if (typeof Promise !== "undefined" && result instanceof Promise) { - return result.then(data => { - if (!data) { - setError(); - return false; - } else { - return true; - } - }); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.undefined, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - if (!result) { - setError(); - return false; - } else { - return true; - } - }); + return (0, parseUtil_1.OK)(input.data); } - 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; - } - }); - } +} - _refinement(refinement) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "refinement", - refinement - } - }); - } +exports.ZodUndefined = ZodUndefined; - optional() { - return ZodOptional.create(this); - } +ZodUndefined.create = params => { + return new ZodUndefined({ + typeName: ZodFirstPartyTypeKind.ZodUndefined, + ...processCreateParams(params) + }); +}; - nullable() { - return ZodNullable.create(this); - } +class ZodNull extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - nullish() { - return this.optional().nullable(); - } + if (parsedType !== parseUtil_1.ZodParsedType.null) { + const ctx = this._getOrReturnCtx(input); - array() { - return ZodArray.create(this); - } + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.null, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - promise() { - return ZodPromise.create(this); + return (0, parseUtil_1.OK)(input.data); } - or(option) { - return ZodUnion.create([this, option]); - } +} - and(incoming) { - return ZodIntersection.create(this, incoming); - } +exports.ZodNull = ZodNull; - transform(transform) { - return new ZodEffects({ - schema: this, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect: { - type: "transform", - transform - } - }); - } +ZodNull.create = params => { + return new ZodNull({ + typeName: ZodFirstPartyTypeKind.ZodNull, + ...processCreateParams(params) + }); +}; - default(def) { - const defaultValueFunc = typeof def === "function" ? def : () => def; - return new ZodDefault({ - innerType: this, - defaultValue: defaultValueFunc, - typeName: ZodFirstPartyTypeKind.ZodDefault - }); +class ZodAny extends ZodType { + constructor() { + super(...arguments); // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. + + this._any = true; } - describe(description) { - const This = this.constructor; - return new This({ ...this._def, - description - }); + _parse(input) { + return (0, parseUtil_1.OK)(input.data); } - isOptional() { - return this.safeParse(undefined).success; +} + +exports.ZodAny = ZodAny; + +ZodAny.create = params => { + return new ZodAny({ + typeName: ZodFirstPartyTypeKind.ZodAny, + ...processCreateParams(params) + }); +}; + +class ZodUnknown extends ZodType { + constructor() { + super(...arguments); // required + + this._unknown = true; } - isNullable() { - return this.safeParse(null).success; + _parse(input) { + return (0, parseUtil_1.OK)(input.data); } } -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 +exports.ZodUnknown = ZodUnknown; -const emailRegex = /^(([^<>()[\]\.,;:\s@\"]+(\.[^<>()[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i; +ZodUnknown.create = params => { + return new ZodUnknown({ + typeName: ZodFirstPartyTypeKind.ZodUnknown, + ...processCreateParams(params) + }); +}; -class ZodString extends ZodType { - constructor() { - super(...arguments); +class ZodNever extends ZodType { + _parse(input) { + const ctx = this._getOrReturnCtx(input); - this._regex = (regex, validation, message) => this.refinement(data => regex.test(data), { - validation, - code: ZodError_1.ZodIssueCode.invalid_string, - ...errorUtil_1.errorUtil.errToObj(message) + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.never, + received: ctx.parsedType }); - /** - * Deprecated. - * Use z.string().min(1) instead. - */ + return parseUtil_1.INVALID; + } +} - this.nonempty = message => this.min(1, errorUtil_1.errorUtil.errToObj(message)); - } +exports.ZodNever = ZodNever; +ZodNever.create = params => { + return new ZodNever({ + typeName: ZodFirstPartyTypeKind.ZodNever, + ...processCreateParams(params) + }); +}; + +class ZodVoid extends ZodType { _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.string) { + if (parsedType !== parseUtil_1.ZodParsedType.undefined) { 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.void, received: ctx.parsedType - } // - ); + }); return parseUtil_1.INVALID; } - const status = new parseUtil_1.ParseStatus(); - let ctx = undefined; + return (0, parseUtil_1.OK)(input.data); + } - 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(); - } - } - } +exports.ZodVoid = ZodVoid; - return { - status: status.value, - value: input.data - }; - } +ZodVoid.create = params => { + return new ZodVoid({ + typeName: ZodFirstPartyTypeKind.ZodVoid, + ...processCreateParams(params) + }); +}; - _addCheck(check) { - return new ZodString({ ...this._def, - checks: [...this._def.checks, check] - }); - } +class ZodArray extends ZodType { + _parse(input) { + const { + ctx, + status + } = this._processInputParams(input); - email(message) { - return this._addCheck({ - kind: "email", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + const def = this._def; - url(message) { - return this._addCheck({ - kind: "url", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.array, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } - uuid(message) { - return this._addCheck({ - kind: "uuid", - ...errorUtil_1.errorUtil.errToObj(message) - }); - } + if (def.minLength !== null) { + if (ctx.data.length < def.minLength.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: def.minLength.value, + type: "array", + inclusive: true, + message: def.minLength.message + }); + status.dirty(); + } + } - cuid(message) { - return this._addCheck({ - kind: "cuid", - ...errorUtil_1.errorUtil.errToObj(message) + if (def.maxLength !== null) { + if (ctx.data.length > def.maxLength.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: def.maxLength.value, + type: "array", + inclusive: true, + message: def.maxLength.message + }); + status.dirty(); + } + } + + if (ctx.common.async) { + return Promise.all(ctx.data.map((item, i) => { + return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); + })).then(result => { + return parseUtil_1.ParseStatus.mergeArray(status, result); + }); + } + + const result = ctx.data.map((item, i) => { + return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); }); + return parseUtil_1.ParseStatus.mergeArray(status, result); } - regex(regex, message) { - return this._addCheck({ - kind: "regex", - regex: regex, - ...errorUtil_1.errorUtil.errToObj(message) - }); + get element() { + return this._def.type; } min(minLength, message) { - return this._addCheck({ - kind: "min", - value: minLength, - ...errorUtil_1.errorUtil.errToObj(message) + return new ZodArray({ ...this._def, + minLength: { + value: minLength, + message: errorUtil_1.errorUtil.toString(message) + } }); } max(maxLength, message) { - return this._addCheck({ - kind: "max", - value: maxLength, - ...errorUtil_1.errorUtil.errToObj(message) + return new ZodArray({ ...this._def, + maxLength: { + value: maxLength, + message: errorUtil_1.errorUtil.toString(message) + } }); } @@ -1969,544 +1873,742 @@ class ZodString extends ZodType { return this.min(len, message).max(len, message); } - get isEmail() { - return !!this._def.checks.find(ch => ch.kind === "email"); + nonempty(message) { + return this.min(1, message); } - get isURL() { - return !!this._def.checks.find(ch => ch.kind === "url"); - } +} - get isUUID() { - return !!this._def.checks.find(ch => ch.kind === "uuid"); - } +exports.ZodArray = ZodArray; - get isCUID() { - return !!this._def.checks.find(ch => ch.kind === "cuid"); - } +ZodArray.create = (schema, params) => { + return new ZodArray({ + type: schema, + minLength: null, + maxLength: null, + typeName: ZodFirstPartyTypeKind.ZodArray, + ...processCreateParams(params) + }); +}; ///////////////////////////////////////// +///////////////////////////////////////// +////////// ////////// +////////// ZodObject ////////// +////////// ////////// +///////////////////////////////////////// +///////////////////////////////////////// - get minLength() { - let min = -Infinity; - this._def.checks.map(ch => { - if (ch.kind === "min") { - if (min === null || ch.value > min) { - min = ch.value; - } - } - }); +var objectUtil; - return min; - } +(function (objectUtil) { + objectUtil.mergeShapes = (first, second) => { + return { ...first, + ...second // second overwrites first - get maxLength() { - let max = null; + }; + }; +})(objectUtil = exports.objectUtil || (exports.objectUtil = {})); - this._def.checks.map(ch => { - if (ch.kind === "max") { - if (max === null || ch.value < max) { - max = ch.value; - } - } - }); +const AugmentFactory = def => augmentation => { + return new ZodObject({ ...def, + shape: () => ({ ...def.shape(), + ...augmentation + }) + }); +}; - return max; - } +function deepPartialify(schema) { + if (schema instanceof ZodObject) { + const newShape = {}; + + for (const key in schema.shape) { + const fieldSchema = schema.shape[key]; + newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + } + return new ZodObject({ ...schema._def, + shape: () => newShape + }); + } else if (schema instanceof ZodArray) { + return ZodArray.create(deepPartialify(schema.element)); + } else if (schema instanceof ZodOptional) { + return ZodOptional.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodNullable) { + return ZodNullable.create(deepPartialify(schema.unwrap())); + } else if (schema instanceof ZodTuple) { + return ZodTuple.create(schema.items.map(item => deepPartialify(item))); + } else { + return schema; + } } -exports.ZodString = ZodString; +class ZodObject extends ZodType { + constructor() { + super(...arguments); + this._cached = null; + /** + * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. + * If you want to pass through unknown properties, use `.passthrough()` instead. + */ -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 + this.nonstrict = this.passthrough; + this.augment = AugmentFactory(this._def); + this.extend = AugmentFactory(this._def); + } + _getCached() { + if (this._cached !== null) return this._cached; -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); -} + const shape = this._def.shape(); -class ZodNumber extends ZodType { - constructor() { - super(...arguments); - this.min = this.gte; - this.max = this.lte; - this.step = this.multipleOf; + const keys = util_1.util.objectKeys(shape); + return this._cached = { + shape, + keys + }; } _parse(input) { const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.number) { + if (parsedType !== parseUtil_1.ZodParsedType.object) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.number, + expected: parseUtil_1.ZodParsedType.object, received: ctx.parsedType }); return parseUtil_1.INVALID; } - let ctx = undefined; - const status = new parseUtil_1.ParseStatus(); + const { + status, + ctx + } = this._processInputParams(input); - for (const check of this._def.checks) { - if (check.kind === "int") { - if (!util_1.util.isInteger(input.data)) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: "integer", - received: "float", - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "min") { - const tooSmall = check.inclusive ? input.data < check.value : input.data <= check.value; + const { + shape, + keys: shapeKeys + } = this._getCached(); - if (tooSmall) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: check.value, - type: "number", - inclusive: check.inclusive, - message: check.message - }); - status.dirty(); - } - } else if (check.kind === "max") { - const tooBig = check.inclusive ? input.data > check.value : input.data >= check.value; + const extraKeys = []; - if (tooBig) { - ctx = this._getOrReturnCtx(input, ctx); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: check.value, - type: "number", - inclusive: check.inclusive, - message: check.message + for (const key in ctx.data) { + if (!shapeKeys.includes(key)) { + extraKeys.push(key); + } + } + + const pairs = []; + + for (const key of shapeKeys) { + const keyValidator = shape[key]; + const value = ctx.data[key]; + pairs.push({ + key: { + status: "valid", + value: key + }, + value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), + alwaysSet: key in ctx.data + }); + } + + if (this._def.catchall instanceof ZodNever) { + const unknownKeys = this._def.unknownKeys; + + if (unknownKeys === "passthrough") { + for (const key of extraKeys) { + pairs.push({ + key: { + status: "valid", + value: key + }, + value: { + status: "valid", + value: ctx.data[key] + } }); - status.dirty(); } - } else if (check.kind === "multipleOf") { - if (floatSafeRemainder(input.data, check.value) !== 0) { - ctx = this._getOrReturnCtx(input, ctx); + } else if (unknownKeys === "strict") { + if (extraKeys.length > 0) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.not_multiple_of, - multipleOf: check.value, - message: check.message + code: ZodError_1.ZodIssueCode.unrecognized_keys, + keys: extraKeys }); status.dirty(); } - } else { - util_1.util.assertNever(check); + } else if (unknownKeys === "strip") {} else { + throw new Error("Internal ZodObject error: invalid unknownKeys value."); + } + } else { + // run catchall validation + const catchall = this._def.catchall; + + for (const key of extraKeys) { + const value = ctx.data[key]; + pairs.push({ + key: { + status: "valid", + value: key + }, + value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) + ), + alwaysSet: key in ctx.data + }); } } - return { - status: status.value, - value: input.data - }; - } + if (ctx.common.async) { + return Promise.resolve().then(async () => { + const syncPairs = []; - gte(value, message) { - return this.setLimit("min", value, true, errorUtil_1.errorUtil.toString(message)); - } + for (const pair of pairs) { + const key = await pair.key; + syncPairs.push({ + key, + value: await pair.value, + alwaysSet: pair.alwaysSet + }); + } - gt(value, message) { - return this.setLimit("min", value, false, errorUtil_1.errorUtil.toString(message)); + return syncPairs; + }).then(syncPairs => { + return parseUtil_1.ParseStatus.mergeObjectSync(status, syncPairs); + }); + } else { + return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); + } } - lte(value, message) { - return this.setLimit("max", value, true, errorUtil_1.errorUtil.toString(message)); + get shape() { + return this._def.shape(); } - lt(value, message) { - return this.setLimit("max", value, false, errorUtil_1.errorUtil.toString(message)); - } + strict(message) { + errorUtil_1.errorUtil.errToObj; + return new ZodObject({ ...this._def, + unknownKeys: "strict", + ...(message !== undefined ? { + errorMap: (issue, ctx) => { + var _a, _b, _c, _d; - setLimit(kind, value, inclusive, message) { - return new ZodNumber({ ...this._def, - checks: [...this._def.checks, { - kind, - value, - inclusive, - message: errorUtil_1.errorUtil.toString(message) - }] + const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError; + if (issue.code === "unrecognized_keys") return { + message: (_d = errorUtil_1.errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError + }; + return { + message: defaultError + }; + } + } : {}) }); } - _addCheck(check) { - return new ZodNumber({ ...this._def, - checks: [...this._def.checks, check] + strip() { + return new ZodObject({ ...this._def, + unknownKeys: "strip" }); } - int(message) { - return this._addCheck({ - kind: "int", - message: errorUtil_1.errorUtil.toString(message) + passthrough() { + return new ZodObject({ ...this._def, + unknownKeys: "passthrough" }); } - positive(message) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: false, - message: errorUtil_1.errorUtil.toString(message) + setKey(key, schema) { + return this.augment({ + [key]: schema }); } + /** + * Prior to zod@1.0.12 there was a bug in the + * inferred type of merged objects. Please + * upgrade if you are experiencing issues. + */ - negative(message) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: false, - message: errorUtil_1.errorUtil.toString(message) + + merge(merging) { + // const mergedShape = objectUtil.mergeShapes( + // this._def.shape(), + // merging._def.shape() + // ); + const merged = new ZodObject({ + unknownKeys: merging._def.unknownKeys, + catchall: merging._def.catchall, + shape: () => objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), + typeName: ZodFirstPartyTypeKind.ZodObject }); + return merged; } - nonpositive(message) { - return this._addCheck({ - kind: "max", - value: 0, - inclusive: true, - message: errorUtil_1.errorUtil.toString(message) + catchall(index) { + return new ZodObject({ ...this._def, + catchall: index }); } - nonnegative(message) { - return this._addCheck({ - kind: "min", - value: 0, - inclusive: true, - message: errorUtil_1.errorUtil.toString(message) + pick(mask) { + const shape = {}; + util_1.util.objectKeys(mask).map(key => { + shape[key] = this.shape[key]; + }); + return new ZodObject({ ...this._def, + shape: () => shape }); } - multipleOf(value, message) { - return this._addCheck({ - kind: "multipleOf", - value: value, - message: errorUtil_1.errorUtil.toString(message) + omit(mask) { + const shape = {}; + util_1.util.objectKeys(this.shape).map(key => { + if (util_1.util.objectKeys(mask).indexOf(key) === -1) { + shape[key] = this.shape[key]; + } + }); + return new ZodObject({ ...this._def, + shape: () => shape }); } - get minValue() { - let min = null; + deepPartial() { + return deepPartialify(this); + } - for (const ch of this._def.checks) { - if (ch.kind === "min") { - if (min === null || ch.value > min) min = ch.value; + partial(mask) { + const newShape = {}; + + if (mask) { + util_1.util.objectKeys(this.shape).map(key => { + if (util_1.util.objectKeys(mask).indexOf(key) === -1) { + newShape[key] = this.shape[key]; + } else { + newShape[key] = this.shape[key].optional(); + } + }); + return new ZodObject({ ...this._def, + shape: () => newShape + }); + } else { + for (const key in this.shape) { + const fieldSchema = this.shape[key]; + newShape[key] = fieldSchema.optional(); } } - return min; + return new ZodObject({ ...this._def, + shape: () => newShape + }); } - get maxValue() { - let max = null; + required() { + const newShape = {}; - for (const ch of this._def.checks) { - if (ch.kind === "max") { - if (max === null || ch.value < max) max = ch.value; + for (const key in this.shape) { + const fieldSchema = this.shape[key]; + let newField = fieldSchema; + + while (newField instanceof ZodOptional) { + newField = newField._def.innerType; } - } - return max; - } + newShape[key] = newField; + } - get isInt() { - return !!this._def.checks.find(ch => ch.kind === "int"); + return new ZodObject({ ...this._def, + shape: () => newShape + }); } } -exports.ZodNumber = ZodNumber; +exports.ZodObject = ZodObject; -ZodNumber.create = params => { - return new ZodNumber({ - checks: [], - typeName: ZodFirstPartyTypeKind.ZodNumber, +ZodObject.create = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, ...processCreateParams(params) }); }; -class ZodBigInt extends ZodType { +ZodObject.strictCreate = (shape, params) => { + return new ZodObject({ + shape: () => shape, + unknownKeys: "strict", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; + +ZodObject.lazycreate = (shape, params) => { + return new ZodObject({ + shape, + unknownKeys: "strip", + catchall: ZodNever.create(), + typeName: ZodFirstPartyTypeKind.ZodObject, + ...processCreateParams(params) + }); +}; + +class ZodUnion extends ZodType { _parse(input) { - const parsedType = this._getType(input); + const { + ctx + } = this._processInputParams(input); - if (parsedType !== parseUtil_1.ZodParsedType.bigint) { - const ctx = this._getOrReturnCtx(input); + const options = this._def.options; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.bigint, - received: ctx.parsedType + function handleResults(results) { + // return first issue-free validation if it exists + for (const result of results) { + if (result.result.status === "valid") { + return result.result; + } + } + + for (const result of results) { + if (result.result.status === "dirty") { + // add issues from dirty option + ctx.common.issues.push(...result.ctx.common.issues); + return result.result; + } + } // return invalid + + + const unionErrors = results.map(result => new ZodError_1.ZodError(result.ctx.common.issues)); + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_union, + unionErrors }); return parseUtil_1.INVALID; } - return (0, parseUtil_1.OK)(input.data); - } + if (ctx.common.async) { + return Promise.all(options.map(async option => { + const childCtx = { ...ctx, + common: { ...ctx.common, + issues: [] + }, + parent: null + }; + return { + result: await option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }), + ctx: childCtx + }; + })).then(handleResults); + } else { + let dirty = undefined; + const issues = []; -} + for (const option of options) { + const childCtx = { ...ctx, + common: { ...ctx.common, + issues: [] + }, + parent: null + }; -exports.ZodBigInt = ZodBigInt; + const result = option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: childCtx + }); -ZodBigInt.create = params => { - return new ZodBigInt({ - typeName: ZodFirstPartyTypeKind.ZodBigInt, - ...processCreateParams(params) - }); -}; + if (result.status === "valid") { + return result; + } else if (result.status === "dirty" && !dirty) { + dirty = { + result, + ctx: childCtx + }; + } -class ZodBoolean extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + if (childCtx.common.issues.length) { + issues.push(childCtx.common.issues); + } + } - if (parsedType !== parseUtil_1.ZodParsedType.boolean) { - const ctx = this._getOrReturnCtx(input); + if (dirty) { + ctx.common.issues.push(...dirty.ctx.common.issues); + return dirty.result; + } + const unionErrors = issues.map(issues => new ZodError_1.ZodError(issues)); (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.boolean, - received: ctx.parsedType + code: ZodError_1.ZodIssueCode.invalid_union, + unionErrors }); return parseUtil_1.INVALID; } + } - return (0, parseUtil_1.OK)(input.data); + get options() { + return this._def.options; } } -exports.ZodBoolean = ZodBoolean; +exports.ZodUnion = ZodUnion; -ZodBoolean.create = params => { - return new ZodBoolean({ - typeName: ZodFirstPartyTypeKind.ZodBoolean, +ZodUnion.create = (types, params) => { + return new ZodUnion({ + options: types, + typeName: ZodFirstPartyTypeKind.ZodUnion, ...processCreateParams(params) }); }; -class ZodDate extends ZodType { +class ZodDiscriminatedUnion extends ZodType { _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.date) { - const ctx = this._getOrReturnCtx(input); + const { + ctx + } = this._processInputParams(input); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.date, + expected: parseUtil_1.ZodParsedType.object, received: ctx.parsedType }); return parseUtil_1.INVALID; } - if (isNaN(input.data.getTime())) { - const ctx = this._getOrReturnCtx(input); + const discriminator = this.discriminator; + const discriminatorValue = ctx.data[discriminator]; + const option = this.options.get(discriminatorValue); + if (!option) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_date + code: ZodError_1.ZodIssueCode.invalid_union_discriminator, + options: this.validDiscriminatorValues, + path: [discriminator] }); return parseUtil_1.INVALID; } - return { - status: "valid", - value: new Date(input.data.getTime()) - }; - } - -} - -exports.ZodDate = ZodDate; - -ZodDate.create = params => { - return new ZodDate({ - typeName: ZodFirstPartyTypeKind.ZodDate, - ...processCreateParams(params) - }); -}; - -class ZodUndefined extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.undefined, - received: ctx.parsedType + if (ctx.common.async) { + return option._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } else { + return option._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx }); - return parseUtil_1.INVALID; } - - return (0, parseUtil_1.OK)(input.data); } -} + get discriminator() { + return this._def.discriminator; + } -exports.ZodUndefined = ZodUndefined; + get validDiscriminatorValues() { + return Array.from(this.options.keys()); + } -ZodUndefined.create = params => { - return new ZodUndefined({ - typeName: ZodFirstPartyTypeKind.ZodUndefined, - ...processCreateParams(params) - }); -}; + get options() { + return this._def.options; + } + /** + * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. + * However, it only allows a union of objects, all of which need to share a discriminator property. This property must + * have a different value for each object in the union. + * @param discriminator the name of the discriminator property + * @param types an array of object schemas + * @param params + */ -class ZodNull extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - if (parsedType !== parseUtil_1.ZodParsedType.null) { - const ctx = this._getOrReturnCtx(input); + static create(discriminator, types, params) { + // Get all the valid discriminator values + const options = new Map(); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.null, - received: ctx.parsedType + try { + types.forEach(type => { + const discriminatorValue = type.shape[discriminator].value; + options.set(discriminatorValue, type); }); - return parseUtil_1.INVALID; + } catch (e) { + throw new Error("The discriminator value could not be extracted from all the provided schemas"); + } // Assert that all the discriminator values are unique + + + if (options.size !== types.length) { + throw new Error("Some of the discriminator values are not unique"); } - return (0, parseUtil_1.OK)(input.data); + return new ZodDiscriminatedUnion({ + typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, + discriminator, + options, + ...processCreateParams(params) + }); } } -exports.ZodNull = ZodNull; +exports.ZodDiscriminatedUnion = ZodDiscriminatedUnion; -ZodNull.create = params => { - return new ZodNull({ - typeName: ZodFirstPartyTypeKind.ZodNull, - ...processCreateParams(params) - }); -}; +function mergeValues(a, b) { + const aType = (0, parseUtil_1.getParsedType)(a); + const bType = (0, parseUtil_1.getParsedType)(b); -class ZodAny extends ZodType { - constructor() { - super(...arguments); // to prevent instances of other classes from extending ZodAny. this causes issues with catchall in ZodObject. + if (a === b) { + return { + valid: true, + data: a + }; + } else if (aType === parseUtil_1.ZodParsedType.object && bType === parseUtil_1.ZodParsedType.object) { + const bKeys = util_1.util.objectKeys(b); + const sharedKeys = util_1.util.objectKeys(a).filter(key => bKeys.indexOf(key) !== -1); + const newObj = { ...a, + ...b + }; - this._any = true; - } + for (const key of sharedKeys) { + const sharedValue = mergeValues(a[key], b[key]); - _parse(input) { - return (0, parseUtil_1.OK)(input.data); - } + if (!sharedValue.valid) { + return { + valid: false + }; + } -} + newObj[key] = sharedValue.data; + } + + return { + valid: true, + data: newObj + }; + } else if (aType === parseUtil_1.ZodParsedType.array && bType === parseUtil_1.ZodParsedType.array) { + if (a.length !== b.length) { + return { + valid: false + }; + } -exports.ZodAny = ZodAny; + const newArray = []; -ZodAny.create = params => { - return new ZodAny({ - typeName: ZodFirstPartyTypeKind.ZodAny, - ...processCreateParams(params) - }); -}; + for (let index = 0; index < a.length; index++) { + const itemA = a[index]; + const itemB = b[index]; + const sharedValue = mergeValues(itemA, itemB); -class ZodUnknown extends ZodType { - constructor() { - super(...arguments); // required + if (!sharedValue.valid) { + return { + valid: false + }; + } - this._unknown = true; - } + newArray.push(sharedValue.data); + } - _parse(input) { - return (0, parseUtil_1.OK)(input.data); + return { + valid: true, + data: newArray + }; + } else if (aType === parseUtil_1.ZodParsedType.date && bType === parseUtil_1.ZodParsedType.date && +a === +b) { + return { + valid: true, + data: a + }; + } else { + return { + valid: false + }; } - } -exports.ZodUnknown = ZodUnknown; - -ZodUnknown.create = params => { - return new ZodUnknown({ - typeName: ZodFirstPartyTypeKind.ZodUnknown, - ...processCreateParams(params) - }); -}; - -class ZodNever extends ZodType { +class ZodIntersection extends ZodType { _parse(input) { - const ctx = this._getOrReturnCtx(input); - - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.never, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + const { + status, + ctx + } = this._processInputParams(input); -} + const handleParsed = (parsedLeft, parsedRight) => { + if ((0, parseUtil_1.isAborted)(parsedLeft) || (0, parseUtil_1.isAborted)(parsedRight)) { + return parseUtil_1.INVALID; + } -exports.ZodNever = ZodNever; + const merged = mergeValues(parsedLeft.value, parsedRight.value); -ZodNever.create = params => { - return new ZodNever({ - typeName: ZodFirstPartyTypeKind.ZodNever, - ...processCreateParams(params) - }); -}; + if (!merged.valid) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_intersection_types + }); + return parseUtil_1.INVALID; + } -class ZodVoid extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + if ((0, parseUtil_1.isDirty)(parsedLeft) || (0, parseUtil_1.isDirty)(parsedRight)) { + status.dirty(); + } - if (parsedType !== parseUtil_1.ZodParsedType.undefined) { - const ctx = this._getOrReturnCtx(input); + return { + status: status.value, + value: merged.data + }; + }; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.void, - received: ctx.parsedType + if (ctx.common.async) { + return Promise.all([this._def.left._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), this._def.right._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + })]).then(_ref => { + let [left, right] = _ref; + return handleParsed(left, right); }); - return parseUtil_1.INVALID; + } else { + return handleParsed(this._def.left._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }), this._def.right._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + })); } - - return (0, parseUtil_1.OK)(input.data); } } -exports.ZodVoid = ZodVoid; +exports.ZodIntersection = ZodIntersection; -ZodVoid.create = params => { - return new ZodVoid({ - typeName: ZodFirstPartyTypeKind.ZodVoid, +ZodIntersection.create = (left, right, params) => { + return new ZodIntersection({ + left: left, + right: right, + typeName: ZodFirstPartyTypeKind.ZodIntersection, ...processCreateParams(params) }); }; -class ZodArray extends ZodType { +class ZodTuple extends ZodType { _parse(input) { const { - ctx, - status + status, + ctx } = this._processInputParams(input); - const def = this._def; - if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, @@ -2516,173 +2618,82 @@ class ZodArray extends ZodType { return parseUtil_1.INVALID; } - if (def.minLength !== null) { - if (ctx.data.length < def.minLength.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: def.minLength.value, - type: "array", - inclusive: true, - message: def.minLength.message - }); - status.dirty(); - } - } - - if (def.maxLength !== null) { - if (ctx.data.length > def.maxLength.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: def.maxLength.value, - type: "array", - inclusive: true, - message: def.maxLength.message - }); - status.dirty(); - } - } - - if (ctx.common.async) { - return Promise.all(ctx.data.map((item, i) => { - return def.type._parseAsync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - })).then(result => { - return parseUtil_1.ParseStatus.mergeArray(status, result); + if (ctx.data.length < this._def.items.length) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: this._def.items.length, + inclusive: true, + type: "array" }); + return parseUtil_1.INVALID; } - const result = ctx.data.map((item, i) => { - return def.type._parseSync(new ParseInputLazyPath(ctx, item, ctx.path, i)); - }); - return parseUtil_1.ParseStatus.mergeArray(status, result); - } - - get element() { - return this._def.type; - } - - min(minLength, message) { - return new ZodArray({ ...this._def, - minLength: { - value: minLength, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } - - max(maxLength, message) { - return new ZodArray({ ...this._def, - maxLength: { - value: maxLength, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } - - length(len, message) { - return this.min(len, message).max(len, message); - } - - nonempty(message) { - return this.min(1, message); - } - -} - -exports.ZodArray = ZodArray; - -ZodArray.create = (schema, params) => { - return new ZodArray({ - type: schema, - minLength: null, - maxLength: null, - typeName: ZodFirstPartyTypeKind.ZodArray, - ...processCreateParams(params) - }); -}; ///////////////////////////////////////// -///////////////////////////////////////// -////////// ////////// -////////// ZodObject ////////// -////////// ////////// -///////////////////////////////////////// -///////////////////////////////////////// - - -var objectUtil; - -(function (objectUtil) { - objectUtil.mergeShapes = (first, second) => { - return { ...first, - ...second // second overwrites first - - }; - }; -})(objectUtil = exports.objectUtil || (exports.objectUtil = {})); + const rest = this._def.rest; -const AugmentFactory = def => augmentation => { - return new ZodObject({ ...def, - shape: () => ({ ...def.shape(), - ...augmentation - }) - }); -}; + if (!rest && ctx.data.length > this._def.items.length) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: this._def.items.length, + inclusive: true, + type: "array" + }); + status.dirty(); + } -function deepPartialify(schema) { - if (schema instanceof ZodObject) { - const newShape = {}; + const items = ctx.data.map((item, itemIndex) => { + const schema = this._def.items[itemIndex] || this._def.rest; + if (!schema) return null; + return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); + }).filter(x => !!x); // filter nulls - for (const key in schema.shape) { - const fieldSchema = schema.shape[key]; - newShape[key] = ZodOptional.create(deepPartialify(fieldSchema)); + if (ctx.common.async) { + return Promise.all(items).then(results => { + return parseUtil_1.ParseStatus.mergeArray(status, results); + }); + } else { + return parseUtil_1.ParseStatus.mergeArray(status, items); } + } - return new ZodObject({ ...schema._def, - shape: () => newShape + get items() { + return this._def.items; + } + + rest(rest) { + return new ZodTuple({ ...this._def, + rest }); - } else if (schema instanceof ZodArray) { - return ZodArray.create(deepPartialify(schema.element)); - } else if (schema instanceof ZodOptional) { - return ZodOptional.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodNullable) { - return ZodNullable.create(deepPartialify(schema.unwrap())); - } else if (schema instanceof ZodTuple) { - return ZodTuple.create(schema.items.map(item => deepPartialify(item))); - } else { - return schema; } -} -class ZodObject extends ZodType { - constructor() { - super(...arguments); - this._cached = null; - /** - * @deprecated In most cases, this is no longer needed - unknown properties are now silently stripped. - * If you want to pass through unknown properties, use `.passthrough()` instead. - */ +} - this.nonstrict = this.passthrough; - this.augment = AugmentFactory(this._def); - this.extend = AugmentFactory(this._def); - } +exports.ZodTuple = ZodTuple; - _getCached() { - if (this._cached !== null) return this._cached; +ZodTuple.create = (schemas, params) => { + return new ZodTuple({ + items: schemas, + typeName: ZodFirstPartyTypeKind.ZodTuple, + rest: null, + ...processCreateParams(params) + }); +}; - const shape = this._def.shape(); +class ZodRecord extends ZodType { + get keySchema() { + return this._def.keyType; + } - const keys = util_1.util.objectKeys(shape); - return this._cached = { - shape, - keys - }; + get valueSchema() { + return this._def.valueType; } _parse(input) { - const parsedType = this._getType(input); - - if (parsedType !== parseUtil_1.ZodParsedType.object) { - const ctx = this._getOrReturnCtx(input); + const { + status, + ctx + } = this._processInputParams(input); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, expected: parseUtil_1.ZodParsedType.object, @@ -2691,1147 +2702,880 @@ class ZodObject extends ZodType { return parseUtil_1.INVALID; } - const { - status, - ctx - } = this._processInputParams(input); - - const { - shape, - keys: shapeKeys - } = this._getCached(); - - const extraKeys = []; - - for (const key in ctx.data) { - if (!shapeKeys.includes(key)) { - extraKeys.push(key); - } - } - const pairs = []; + const keyType = this._def.keyType; + const valueType = this._def.valueType; - for (const key of shapeKeys) { - const keyValidator = shape[key]; - const value = ctx.data[key]; + for (const key in ctx.data) { pairs.push({ - key: { - status: "valid", - value: key - }, - value: keyValidator._parse(new ParseInputLazyPath(ctx, value, ctx.path, key)), - alwaysSet: key in ctx.data + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), + value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)) }); } - if (this._def.catchall instanceof ZodNever) { - const unknownKeys = this._def.unknownKeys; - - if (unknownKeys === "passthrough") { - for (const key of extraKeys) { - pairs.push({ - key: { - status: "valid", - value: key - }, - value: { - status: "valid", - value: ctx.data[key] - } - }); - } - } else if (unknownKeys === "strict") { - if (extraKeys.length > 0) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.unrecognized_keys, - keys: extraKeys - }); - status.dirty(); - } - } else if (unknownKeys === "strip") {} else { - throw new Error("Internal ZodObject error: invalid unknownKeys value."); - } - } else { - // run catchall validation - const catchall = this._def.catchall; - - for (const key of extraKeys) { - const value = ctx.data[key]; - pairs.push({ - key: { - status: "valid", - value: key - }, - value: catchall._parse(new ParseInputLazyPath(ctx, value, ctx.path, key) //, ctx.child(key), value, getParsedType(value) - ), - alwaysSet: key in ctx.data - }); - } - } - if (ctx.common.async) { - return Promise.resolve().then(async () => { - const syncPairs = []; - - for (const pair of pairs) { - const key = await pair.key; - syncPairs.push({ - key, - value: await pair.value, - alwaysSet: pair.alwaysSet - }); - } - - return syncPairs; - }).then(syncPairs => { - return parseUtil_1.ParseStatus.mergeObjectSync(status, syncPairs); - }); + return parseUtil_1.ParseStatus.mergeObjectAsync(status, pairs); } else { return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); } } - get shape() { - return this._def.shape(); - } - - strict(message) { - errorUtil_1.errorUtil.errToObj; - return new ZodObject({ ...this._def, - unknownKeys: "strict", - ...(message !== undefined ? { - errorMap: (issue, ctx) => { - var _a, _b, _c, _d; - - const defaultError = (_c = (_b = (_a = this._def).errorMap) === null || _b === void 0 ? void 0 : _b.call(_a, issue, ctx).message) !== null && _c !== void 0 ? _c : ctx.defaultError; - if (issue.code === "unrecognized_keys") return { - message: (_d = errorUtil_1.errorUtil.errToObj(message).message) !== null && _d !== void 0 ? _d : defaultError - }; - return { - message: defaultError - }; - } - } : {}) - }); - } - - strip() { - return new ZodObject({ ...this._def, - unknownKeys: "strip" - }); - } - - passthrough() { - return new ZodObject({ ...this._def, - unknownKeys: "passthrough" - }); - } - - setKey(key, schema) { - return this.augment({ - [key]: schema - }); + get element() { + return this._def.valueType; } - /** - * Prior to zod@1.0.12 there was a bug in the - * inferred type of merged objects. Please - * upgrade if you are experiencing issues. - */ + static create(first, second, third) { + if (second instanceof ZodType) { + return new ZodRecord({ + keyType: first, + valueType: second, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(third) + }); + } - merge(merging) { - // const mergedShape = objectUtil.mergeShapes( - // this._def.shape(), - // merging._def.shape() - // ); - const merged = new ZodObject({ - unknownKeys: merging._def.unknownKeys, - catchall: merging._def.catchall, - shape: () => objectUtil.mergeShapes(this._def.shape(), merging._def.shape()), - typeName: ZodFirstPartyTypeKind.ZodObject + return new ZodRecord({ + keyType: ZodString.create(), + valueType: first, + typeName: ZodFirstPartyTypeKind.ZodRecord, + ...processCreateParams(second) }); - return merged; } - catchall(index) { - return new ZodObject({ ...this._def, - catchall: index - }); - } +} - pick(mask) { - const shape = {}; - util_1.util.objectKeys(mask).map(key => { - shape[key] = this.shape[key]; - }); - return new ZodObject({ ...this._def, - shape: () => shape - }); - } +exports.ZodRecord = ZodRecord; - omit(mask) { - const shape = {}; - util_1.util.objectKeys(this.shape).map(key => { - if (util_1.util.objectKeys(mask).indexOf(key) === -1) { - shape[key] = this.shape[key]; - } - }); - return new ZodObject({ ...this._def, - shape: () => shape +class ZodMap extends ZodType { + _parse(input) { + const { + status, + ctx + } = this._processInputParams(input); + + if (ctx.parsedType !== parseUtil_1.ZodParsedType.map) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.map, + received: ctx.parsedType + }); + return parseUtil_1.INVALID; + } + + const keyType = this._def.keyType; + const valueType = this._def.valueType; + const pairs = [...ctx.data.entries()].map((_ref2, index) => { + let [key, value] = _ref2; + return { + key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), + value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])) + }; }); - } - deepPartial() { - return deepPartialify(this); - } + if (ctx.common.async) { + const finalMap = new Map(); + return Promise.resolve().then(async () => { + for (const pair of pairs) { + const key = await pair.key; + const value = await pair.value; - partial(mask) { - const newShape = {}; + if (key.status === "aborted" || value.status === "aborted") { + return parseUtil_1.INVALID; + } - if (mask) { - util_1.util.objectKeys(this.shape).map(key => { - if (util_1.util.objectKeys(mask).indexOf(key) === -1) { - newShape[key] = this.shape[key]; - } else { - newShape[key] = this.shape[key].optional(); + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } + + finalMap.set(key.value, value.value); } - }); - return new ZodObject({ ...this._def, - shape: () => newShape + + return { + status: status.value, + value: finalMap + }; }); } else { - for (const key in this.shape) { - const fieldSchema = this.shape[key]; - newShape[key] = fieldSchema.optional(); - } - } + const finalMap = new Map(); - return new ZodObject({ ...this._def, - shape: () => newShape - }); - } + for (const pair of pairs) { + const key = pair.key; + const value = pair.value; - required() { - const newShape = {}; + if (key.status === "aborted" || value.status === "aborted") { + return parseUtil_1.INVALID; + } - for (const key in this.shape) { - const fieldSchema = this.shape[key]; - let newField = fieldSchema; + if (key.status === "dirty" || value.status === "dirty") { + status.dirty(); + } - while (newField instanceof ZodOptional) { - newField = newField._def.innerType; + finalMap.set(key.value, value.value); } - newShape[key] = newField; + return { + status: status.value, + value: finalMap + }; } - - return new ZodObject({ ...this._def, - shape: () => newShape - }); } } -exports.ZodObject = ZodObject; - -ZodObject.create = (shape, params) => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params) - }); -}; - -ZodObject.strictCreate = (shape, params) => { - return new ZodObject({ - shape: () => shape, - unknownKeys: "strict", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, - ...processCreateParams(params) - }); -}; +exports.ZodMap = ZodMap; -ZodObject.lazycreate = (shape, params) => { - return new ZodObject({ - shape, - unknownKeys: "strip", - catchall: ZodNever.create(), - typeName: ZodFirstPartyTypeKind.ZodObject, +ZodMap.create = (keyType, valueType, params) => { + return new ZodMap({ + valueType, + keyType, + typeName: ZodFirstPartyTypeKind.ZodMap, ...processCreateParams(params) }); }; -class ZodUnion extends ZodType { +class ZodSet extends ZodType { _parse(input) { const { + status, ctx } = this._processInputParams(input); - const options = this._def.options; - - function handleResults(results) { - // return first issue-free validation if it exists - for (const result of results) { - if (result.result.status === "valid") { - return result.result; - } - } - - for (const result of results) { - if (result.result.status === "dirty") { - // add issues from dirty option - ctx.common.issues.push(...result.ctx.common.issues); - return result.result; - } - } // return invalid - - - const unionErrors = results.map(result => new ZodError_1.ZodError(result.ctx.common.issues)); + if (ctx.parsedType !== parseUtil_1.ZodParsedType.set) { (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union, - unionErrors + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.set, + received: ctx.parsedType }); return parseUtil_1.INVALID; } - if (ctx.common.async) { - return Promise.all(options.map(async option => { - const childCtx = { ...ctx, - common: { ...ctx.common, - issues: [] - }, - parent: null - }; - return { - result: await option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: childCtx - }), - ctx: childCtx - }; - })).then(handleResults); - } else { - let dirty = undefined; - const issues = []; + const def = this._def; - for (const option of options) { - const childCtx = { ...ctx, - common: { ...ctx.common, - issues: [] - }, - parent: null - }; + if (def.minSize !== null) { + if (ctx.data.size < def.minSize.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_small, + minimum: def.minSize.value, + type: "set", + inclusive: true, + message: def.minSize.message + }); + status.dirty(); + } + } - const result = option._parseSync({ - data: ctx.data, - path: ctx.path, - parent: childCtx + if (def.maxSize !== null) { + if (ctx.data.size > def.maxSize.value) { + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.too_big, + maximum: def.maxSize.value, + type: "set", + inclusive: true, + message: def.maxSize.message }); + status.dirty(); + } + } + + const valueType = this._def.valueType; + + function finalizeSet(elements) { + const parsedSet = new Set(); + + for (const element of elements) { + if (element.status === "aborted") return parseUtil_1.INVALID; + if (element.status === "dirty") status.dirty(); + parsedSet.add(element.value); + } + + return { + status: status.value, + value: parsedSet + }; + } + + const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i))); - if (result.status === "valid") { - return result; - } else if (result.status === "dirty" && !dirty) { - dirty = { - result, - ctx: childCtx - }; - } + if (ctx.common.async) { + return Promise.all(elements).then(elements => finalizeSet(elements)); + } else { + return finalizeSet(elements); + } + } - if (childCtx.common.issues.length) { - issues.push(childCtx.common.issues); - } + min(minSize, message) { + return new ZodSet({ ...this._def, + minSize: { + value: minSize, + message: errorUtil_1.errorUtil.toString(message) } + }); + } - if (dirty) { - ctx.common.issues.push(...dirty.ctx.common.issues); - return dirty.result; + max(maxSize, message) { + return new ZodSet({ ...this._def, + maxSize: { + value: maxSize, + message: errorUtil_1.errorUtil.toString(message) } + }); + } - const unionErrors = issues.map(issues => new ZodError_1.ZodError(issues)); - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union, - unionErrors - }); - return parseUtil_1.INVALID; - } + size(size, message) { + return this.min(size, message).max(size, message); } - get options() { - return this._def.options; + nonempty(message) { + return this.min(1, message); } } -exports.ZodUnion = ZodUnion; +exports.ZodSet = ZodSet; -ZodUnion.create = (types, params) => { - return new ZodUnion({ - options: types, - typeName: ZodFirstPartyTypeKind.ZodUnion, +ZodSet.create = (valueType, params) => { + return new ZodSet({ + valueType, + minSize: null, + maxSize: null, + typeName: ZodFirstPartyTypeKind.ZodSet, ...processCreateParams(params) }); }; -class ZodDiscriminatedUnion extends ZodType { +class ZodFunction extends ZodType { + constructor() { + super(...arguments); + this.validate = this.implement; + } + _parse(input) { + var _this = this; + const { ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { + if (ctx.parsedType !== parseUtil_1.ZodParsedType.function) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.object, + expected: parseUtil_1.ZodParsedType.function, received: ctx.parsedType }); return parseUtil_1.INVALID; } - const discriminator = this.discriminator; - const discriminatorValue = ctx.data[discriminator]; - const option = this.options.get(discriminatorValue); - - if (!option) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_union_discriminator, - options: this.validDiscriminatorValues, - path: [discriminator] + function makeArgsIssue(args, error) { + return (0, parseUtil_1.makeIssue)({ + data: args, + path: ctx.path, + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), + issueData: { + code: ZodError_1.ZodIssueCode.invalid_arguments, + argumentsError: error + } }); - return parseUtil_1.INVALID; } - if (ctx.common.async) { - return option._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); - } else { - return option._parseSync({ - data: ctx.data, + function makeReturnsIssue(returns, error) { + return (0, parseUtil_1.makeIssue)({ + data: returns, path: ctx.path, - parent: ctx + errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), + issueData: { + code: ZodError_1.ZodIssueCode.invalid_return_type, + returnTypeError: error + } }); } - } - - get discriminator() { - return this._def.discriminator; - } - - get validDiscriminatorValues() { - return Array.from(this.options.keys()); - } - - get options() { - return this._def.options; - } - /** - * The constructor of the discriminated union schema. Its behaviour is very similar to that of the normal z.union() constructor. - * However, it only allows a union of objects, all of which need to share a discriminator property. This property must - * have a different value for each object in the union. - * @param discriminator the name of the discriminator property - * @param types an array of object schemas - * @param params - */ + const params = { + errorMap: ctx.common.contextualErrorMap + }; + const fn = ctx.data; - static create(discriminator, types, params) { - // Get all the valid discriminator values - const options = new Map(); + if (this._def.returns instanceof ZodPromise) { + return (0, parseUtil_1.OK)(async function () { + for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { + args[_key] = arguments[_key]; + } - try { - types.forEach(type => { - const discriminatorValue = type.shape[discriminator].value; - options.set(discriminatorValue, type); + const error = new ZodError_1.ZodError([]); + const parsedArgs = await _this._def.args.parseAsync(args, params).catch(e => { + error.addIssue(makeArgsIssue(args, e)); + throw error; + }); + const result = await fn(...parsedArgs); + const parsedReturns = await _this._def.returns._def.type.parseAsync(result, params).catch(e => { + error.addIssue(makeReturnsIssue(result, e)); + throw error; + }); + return parsedReturns; }); - } catch (e) { - throw new Error("The discriminator value could not be extracted from all the provided schemas"); - } // Assert that all the discriminator values are unique - + } else { + return (0, parseUtil_1.OK)(function () { + for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { + args[_key2] = arguments[_key2]; + } - if (options.size !== types.length) { - throw new Error("Some of the discriminator values are not unique"); - } + const parsedArgs = _this._def.args.safeParse(args, params); - return new ZodDiscriminatedUnion({ - typeName: ZodFirstPartyTypeKind.ZodDiscriminatedUnion, - discriminator, - options, - ...processCreateParams(params) - }); - } + if (!parsedArgs.success) { + throw new ZodError_1.ZodError([makeArgsIssue(args, parsedArgs.error)]); + } -} + const result = fn(...parsedArgs.data); -exports.ZodDiscriminatedUnion = ZodDiscriminatedUnion; + const parsedReturns = _this._def.returns.safeParse(result, params); -function mergeValues(a, b) { - const aType = (0, parseUtil_1.getParsedType)(a); - const bType = (0, parseUtil_1.getParsedType)(b); + if (!parsedReturns.success) { + throw new ZodError_1.ZodError([makeReturnsIssue(result, parsedReturns.error)]); + } - if (a === b) { - return { - valid: true, - data: a - }; - } else if (aType === parseUtil_1.ZodParsedType.object && bType === parseUtil_1.ZodParsedType.object) { - const bKeys = util_1.util.objectKeys(b); - const sharedKeys = util_1.util.objectKeys(a).filter(key => bKeys.indexOf(key) !== -1); - const newObj = { ...a, - ...b - }; + return parsedReturns.data; + }); + } + } - for (const key of sharedKeys) { - const sharedValue = mergeValues(a[key], b[key]); + parameters() { + return this._def.args; + } - if (!sharedValue.valid) { - return { - valid: false - }; - } + returnType() { + return this._def.returns; + } - newObj[key] = sharedValue.data; + args() { + for (var _len3 = arguments.length, items = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { + items[_key3] = arguments[_key3]; } - return { - valid: true, - data: newObj - }; - } else if (aType === parseUtil_1.ZodParsedType.array && bType === parseUtil_1.ZodParsedType.array) { - if (a.length !== b.length) { - return { - valid: false - }; - } + return new ZodFunction({ ...this._def, + args: ZodTuple.create(items).rest(ZodUnknown.create()) + }); + } - const newArray = []; + returns(returnType) { + return new ZodFunction({ ...this._def, + returns: returnType + }); + } - for (let index = 0; index < a.length; index++) { - const itemA = a[index]; - const itemB = b[index]; - const sharedValue = mergeValues(itemA, itemB); + implement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } + + strictImplement(func) { + const validatedFunc = this.parse(func); + return validatedFunc; + } - if (!sharedValue.valid) { - return { - valid: false - }; - } +} - newArray.push(sharedValue.data); - } +exports.ZodFunction = ZodFunction; - return { - valid: true, - data: newArray - }; - } else if (aType === parseUtil_1.ZodParsedType.date && bType === parseUtil_1.ZodParsedType.date && +a === +b) { - return { - valid: true, - data: a - }; - } else { - return { - valid: false - }; +ZodFunction.create = (args, returns, params) => { + return new ZodFunction({ + args: args ? args.rest(ZodUnknown.create()) : ZodTuple.create([]).rest(ZodUnknown.create()), + returns: returns || ZodUnknown.create(), + typeName: ZodFirstPartyTypeKind.ZodFunction, + ...processCreateParams(params) + }); +}; + +class ZodLazy extends ZodType { + get schema() { + return this._def.getter(); } -} -class ZodIntersection extends ZodType { _parse(input) { const { - status, ctx } = this._processInputParams(input); - const handleParsed = (parsedLeft, parsedRight) => { - if ((0, parseUtil_1.isAborted)(parsedLeft) || (0, parseUtil_1.isAborted)(parsedRight)) { - return parseUtil_1.INVALID; - } + const lazySchema = this._def.getter(); - const merged = mergeValues(parsedLeft.value, parsedRight.value); + return lazySchema._parse({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + } - if (!merged.valid) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_intersection_types - }); - return parseUtil_1.INVALID; - } +} - if ((0, parseUtil_1.isDirty)(parsedLeft) || (0, parseUtil_1.isDirty)(parsedRight)) { - status.dirty(); - } +exports.ZodLazy = ZodLazy; - return { - status: status.value, - value: merged.data - }; - }; +ZodLazy.create = (getter, params) => { + return new ZodLazy({ + getter: getter, + typeName: ZodFirstPartyTypeKind.ZodLazy, + ...processCreateParams(params) + }); +}; - if (ctx.common.async) { - return Promise.all([this._def.left._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }), this._def.right._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - })]).then(_ref => { - let [left, right] = _ref; - return handleParsed(left, right); +class ZodLiteral extends ZodType { + _parse(input) { + if (input.data !== this._def.value) { + const ctx = this._getOrReturnCtx(input); + + (0, parseUtil_1.addIssueToContext)(ctx, { + code: ZodError_1.ZodIssueCode.invalid_literal, + expected: this._def.value }); - } else { - return handleParsed(this._def.left._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }), this._def.right._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - })); + return parseUtil_1.INVALID; } + + return { + status: "valid", + value: input.data + }; + } + + get value() { + return this._def.value; } } -exports.ZodIntersection = ZodIntersection; +exports.ZodLiteral = ZodLiteral; -ZodIntersection.create = (left, right, params) => { - return new ZodIntersection({ - left: left, - right: right, - typeName: ZodFirstPartyTypeKind.ZodIntersection, +ZodLiteral.create = (value, params) => { + return new ZodLiteral({ + value: value, + typeName: ZodFirstPartyTypeKind.ZodLiteral, ...processCreateParams(params) }); }; -class ZodTuple extends ZodType { +function createZodEnum(values) { + return new ZodEnum({ + values: values, + typeName: ZodFirstPartyTypeKind.ZodEnum + }); +} + +class ZodEnum extends ZodType { _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); + if (typeof input.data !== "string") { + const ctx = this._getOrReturnCtx(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.array) { + const expectedValues = this._def.values; (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.array, - received: ctx.parsedType + expected: util_1.util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodError_1.ZodIssueCode.invalid_type }); return parseUtil_1.INVALID; } - if (ctx.data.length < this._def.items.length) { + if (this._def.values.indexOf(input.data) === -1) { + const ctx = this._getOrReturnCtx(input); + + const expectedValues = this._def.values; (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: this._def.items.length, - inclusive: true, - type: "array" + received: ctx.data, + code: ZodError_1.ZodIssueCode.invalid_enum_value, + options: expectedValues }); return parseUtil_1.INVALID; } - const rest = this._def.rest; + return (0, parseUtil_1.OK)(input.data); + } - if (!rest && ctx.data.length > this._def.items.length) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: this._def.items.length, - inclusive: true, - type: "array" - }); - status.dirty(); - } + get options() { + return this._def.values; + } - const items = ctx.data.map((item, itemIndex) => { - const schema = this._def.items[itemIndex] || this._def.rest; - if (!schema) return null; - return schema._parse(new ParseInputLazyPath(ctx, item, ctx.path, itemIndex)); - }).filter(x => !!x); // filter nulls + get enum() { + const enumValues = {}; - if (ctx.common.async) { - return Promise.all(items).then(results => { - return parseUtil_1.ParseStatus.mergeArray(status, results); - }); - } else { - return parseUtil_1.ParseStatus.mergeArray(status, items); + for (const val of this._def.values) { + enumValues[val] = val; } - } - get items() { - return this._def.items; + return enumValues; } - rest(rest) { - return new ZodTuple({ ...this._def, - rest - }); - } + get Values() { + const enumValues = {}; -} + for (const val of this._def.values) { + enumValues[val] = val; + } -exports.ZodTuple = ZodTuple; + return enumValues; + } -ZodTuple.create = (schemas, params) => { - return new ZodTuple({ - items: schemas, - typeName: ZodFirstPartyTypeKind.ZodTuple, - rest: null, - ...processCreateParams(params) - }); -}; + get Enum() { + const enumValues = {}; -class ZodRecord extends ZodType { - get keySchema() { - return this._def.keyType; - } + for (const val of this._def.values) { + enumValues[val] = val; + } - get valueSchema() { - return this._def.valueType; + return enumValues; } - _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); +} - if (ctx.parsedType !== parseUtil_1.ZodParsedType.object) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.object, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } +exports.ZodEnum = ZodEnum; +ZodEnum.create = createZodEnum; - const pairs = []; - const keyType = this._def.keyType; - const valueType = this._def.valueType; +class ZodNativeEnum extends ZodType { + _parse(input) { + const nativeEnumValues = util_1.util.getValidEnumValues(this._def.values); - for (const key in ctx.data) { - pairs.push({ - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, key)), - value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key], ctx.path, key)) + const ctx = this._getOrReturnCtx(input); + + if (ctx.parsedType !== parseUtil_1.ZodParsedType.string && ctx.parsedType !== parseUtil_1.ZodParsedType.number) { + const expectedValues = util_1.util.objectValues(nativeEnumValues); + (0, parseUtil_1.addIssueToContext)(ctx, { + expected: util_1.util.joinValues(expectedValues), + received: ctx.parsedType, + code: ZodError_1.ZodIssueCode.invalid_type }); + return parseUtil_1.INVALID; } - if (ctx.common.async) { - return parseUtil_1.ParseStatus.mergeObjectAsync(status, pairs); - } else { - return parseUtil_1.ParseStatus.mergeObjectSync(status, pairs); + if (nativeEnumValues.indexOf(input.data) === -1) { + const expectedValues = util_1.util.objectValues(nativeEnumValues); + (0, parseUtil_1.addIssueToContext)(ctx, { + received: ctx.data, + code: ZodError_1.ZodIssueCode.invalid_enum_value, + options: expectedValues + }); + return parseUtil_1.INVALID; } - } - get element() { - return this._def.valueType; + return (0, parseUtil_1.OK)(input.data); } - static create(first, second, third) { - if (second instanceof ZodType) { - return new ZodRecord({ - keyType: first, - valueType: second, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(third) - }); - } - - return new ZodRecord({ - keyType: ZodString.create(), - valueType: first, - typeName: ZodFirstPartyTypeKind.ZodRecord, - ...processCreateParams(second) - }); + get enum() { + return this._def.values; } } -exports.ZodRecord = ZodRecord; +exports.ZodNativeEnum = ZodNativeEnum; -class ZodMap extends ZodType { +ZodNativeEnum.create = (values, params) => { + return new ZodNativeEnum({ + values: values, + typeName: ZodFirstPartyTypeKind.ZodNativeEnum, + ...processCreateParams(params) + }); +}; + +class ZodPromise extends ZodType { _parse(input) { const { - status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.map) { + if (ctx.parsedType !== parseUtil_1.ZodParsedType.promise && ctx.common.async === false) { (0, parseUtil_1.addIssueToContext)(ctx, { code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.map, + expected: parseUtil_1.ZodParsedType.promise, received: ctx.parsedType }); return parseUtil_1.INVALID; } - const keyType = this._def.keyType; - const valueType = this._def.valueType; - const pairs = [...ctx.data.entries()].map((_ref2, index) => { - let [key, value] = _ref2; - return { - key: keyType._parse(new ParseInputLazyPath(ctx, key, ctx.path, [index, "key"])), - value: valueType._parse(new ParseInputLazyPath(ctx, value, ctx.path, [index, "value"])) - }; - }); - - if (ctx.common.async) { - const finalMap = new Map(); - return Promise.resolve().then(async () => { - for (const pair of pairs) { - const key = await pair.key; - const value = await pair.value; - - if (key.status === "aborted" || value.status === "aborted") { - return parseUtil_1.INVALID; - } - - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - - return { - status: status.value, - value: finalMap - }; + const promisified = ctx.parsedType === parseUtil_1.ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); + return (0, parseUtil_1.OK)(promisified.then(data => { + return this._def.type.parseAsync(data, { + path: ctx.path, + errorMap: ctx.common.contextualErrorMap }); - } else { - const finalMap = new Map(); - - for (const pair of pairs) { - const key = pair.key; - const value = pair.value; - - if (key.status === "aborted" || value.status === "aborted") { - return parseUtil_1.INVALID; - } - - if (key.status === "dirty" || value.status === "dirty") { - status.dirty(); - } - - finalMap.set(key.value, value.value); - } - - return { - status: status.value, - value: finalMap - }; - } + })); } } -exports.ZodMap = ZodMap; +exports.ZodPromise = ZodPromise; -ZodMap.create = (keyType, valueType, params) => { - return new ZodMap({ - valueType, - keyType, - typeName: ZodFirstPartyTypeKind.ZodMap, +ZodPromise.create = (schema, params) => { + return new ZodPromise({ + type: schema, + typeName: ZodFirstPartyTypeKind.ZodPromise, ...processCreateParams(params) }); }; -class ZodSet extends ZodType { +class ZodEffects extends ZodType { + innerType() { + return this._def.schema; + } + _parse(input) { const { status, ctx } = this._processInputParams(input); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.set) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.set, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + const effect = this._def.effect || null; - const def = this._def; + if (effect.type === "preprocess") { + const processed = effect.transform(ctx.data); - if (def.minSize !== null) { - if (ctx.data.size < def.minSize.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_small, - minimum: def.minSize.value, - type: "set", - inclusive: true, - message: def.minSize.message + if (ctx.common.async) { + return Promise.resolve(processed).then(processed => { + return this._def.schema._parseAsync({ + data: processed, + path: ctx.path, + parent: ctx + }); + }); + } else { + return this._def.schema._parseSync({ + data: processed, + path: ctx.path, + parent: ctx }); - status.dirty(); } } - if (def.maxSize !== null) { - if (ctx.data.size > def.maxSize.value) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.too_big, - maximum: def.maxSize.value, - type: "set", - inclusive: true, - message: def.maxSize.message - }); - status.dirty(); + const checkCtx = { + addIssue: arg => { + (0, parseUtil_1.addIssueToContext)(ctx, arg); + + if (arg.fatal) { + status.abort(); + } else { + status.dirty(); + } + }, + + get path() { + return ctx.path; } - } - const valueType = this._def.valueType; + }; + checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); - function finalizeSet(elements) { - const parsedSet = new Set(); + if (effect.type === "refinement") { + const executeRefinement = (acc // effect: RefinementEffect + ) => { + const result = effect.refinement(acc, checkCtx); - for (const element of elements) { - if (element.status === "aborted") return parseUtil_1.INVALID; - if (element.status === "dirty") status.dirty(); - parsedSet.add(element.value); + if (ctx.common.async) { + return Promise.resolve(result); + } + + if (result instanceof Promise) { + throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); + } + + return acc; + }; + + if (ctx.common.async === false) { + const inner = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); + + if (inner.status === "aborted") return parseUtil_1.INVALID; + if (inner.status === "dirty") status.dirty(); // return value is ignored + + executeRefinement(inner.value); + return { + status: status.value, + value: inner.value + }; + } else { + return this._def.schema._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }).then(inner => { + if (inner.status === "aborted") return parseUtil_1.INVALID; + if (inner.status === "dirty") status.dirty(); + return executeRefinement(inner.value).then(() => { + return { + status: status.value, + value: inner.value + }; + }); + }); } + } + + if (effect.type === "transform") { + if (ctx.common.async === false) { + const base = this._def.schema._parseSync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }); // if (base.status === "aborted") return INVALID; + // if (base.status === "dirty") { + // return { status: "dirty", value: base.value }; + // } - return { - status: status.value, - value: parsedSet - }; - } - const elements = [...ctx.data.values()].map((item, i) => valueType._parse(new ParseInputLazyPath(ctx, item, ctx.path, i))); + if (!(0, parseUtil_1.isValid)(base)) return base; + const result = effect.transform(base.value, checkCtx); - if (ctx.common.async) { - return Promise.all(elements).then(elements => finalizeSet(elements)); - } else { - return finalizeSet(elements); - } - } + if (result instanceof Promise) { + throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead."); + } - min(minSize, message) { - return new ZodSet({ ...this._def, - minSize: { - value: minSize, - message: errorUtil_1.errorUtil.toString(message) - } - }); - } + return { + status: status.value, + value: result + }; + } else { + return this._def.schema._parseAsync({ + data: ctx.data, + path: ctx.path, + parent: ctx + }).then(base => { + if (!(0, parseUtil_1.isValid)(base)) return base; // if (base.status === "aborted") return INVALID; + // if (base.status === "dirty") { + // return { status: "dirty", value: base.value }; + // } - max(maxSize, message) { - return new ZodSet({ ...this._def, - maxSize: { - value: maxSize, - message: errorUtil_1.errorUtil.toString(message) + return Promise.resolve(effect.transform(base.value, checkCtx)).then(result => ({ + status: status.value, + value: result + })); + }); } - }); - } - - size(size, message) { - return this.min(size, message).max(size, message); - } + } - nonempty(message) { - return this.min(1, message); + util_1.util.assertNever(effect); } } -exports.ZodSet = ZodSet; +exports.ZodEffects = ZodEffects; +exports.ZodTransformer = ZodEffects; -ZodSet.create = (valueType, params) => { - return new ZodSet({ - valueType, - minSize: null, - maxSize: null, - typeName: ZodFirstPartyTypeKind.ZodSet, +ZodEffects.create = (schema, effect, params) => { + return new ZodEffects({ + schema, + typeName: ZodFirstPartyTypeKind.ZodEffects, + effect, ...processCreateParams(params) }); }; -class ZodFunction extends ZodType { - constructor() { - super(...arguments); - this.validate = this.implement; - } +ZodEffects.createWithPreprocess = (preprocess, schema, params) => { + return new ZodEffects({ + schema, + effect: { + type: "preprocess", + transform: preprocess + }, + typeName: ZodFirstPartyTypeKind.ZodEffects, + ...processCreateParams(params) + }); +}; +class ZodOptional extends ZodType { _parse(input) { - var _this = this; - - const { - ctx - } = this._processInputParams(input); - - if (ctx.parsedType !== parseUtil_1.ZodParsedType.function) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.function, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } - - function makeArgsIssue(args, error) { - return (0, parseUtil_1.makeIssue)({ - data: args, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), - issueData: { - code: ZodError_1.ZodIssueCode.invalid_arguments, - argumentsError: error - } - }); - } + const parsedType = this._getType(input); - function makeReturnsIssue(returns, error) { - return (0, parseUtil_1.makeIssue)({ - data: returns, - path: ctx.path, - errorMaps: [ctx.common.contextualErrorMap, ctx.schemaErrorMap, ZodError_1.overrideErrorMap, ZodError_1.defaultErrorMap].filter(x => !!x), - issueData: { - code: ZodError_1.ZodIssueCode.invalid_return_type, - returnTypeError: error - } - }); + if (parsedType === parseUtil_1.ZodParsedType.undefined) { + return (0, parseUtil_1.OK)(undefined); } - const params = { - errorMap: ctx.common.contextualErrorMap - }; - const fn = ctx.data; - - if (this._def.returns instanceof ZodPromise) { - return (0, parseUtil_1.OK)(async function () { - for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { - args[_key] = arguments[_key]; - } - - const error = new ZodError_1.ZodError([]); - const parsedArgs = await _this._def.args.parseAsync(args, params).catch(e => { - error.addIssue(makeArgsIssue(args, e)); - throw error; - }); - const result = await fn(...parsedArgs); - const parsedReturns = await _this._def.returns._def.type.parseAsync(result, params).catch(e => { - error.addIssue(makeReturnsIssue(result, e)); - throw error; - }); - return parsedReturns; - }); - } else { - return (0, parseUtil_1.OK)(function () { - for (var _len2 = arguments.length, args = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { - args[_key2] = arguments[_key2]; - } - - const parsedArgs = _this._def.args.safeParse(args, params); - - if (!parsedArgs.success) { - throw new ZodError_1.ZodError([makeArgsIssue(args, parsedArgs.error)]); - } - - const result = fn(...parsedArgs.data); - - const parsedReturns = _this._def.returns.safeParse(result, params); - - if (!parsedReturns.success) { - throw new ZodError_1.ZodError([makeReturnsIssue(result, parsedReturns.error)]); - } - - return parsedReturns.data; - }); - } + return this._def.innerType._parse(input); } - parameters() { - return this._def.args; + unwrap() { + return this._def.innerType; } - returnType() { - return this._def.returns; - } +} - args() { - for (var _len3 = arguments.length, items = new Array(_len3), _key3 = 0; _key3 < _len3; _key3++) { - items[_key3] = arguments[_key3]; - } +exports.ZodOptional = ZodOptional; - return new ZodFunction({ ...this._def, - args: ZodTuple.create(items).rest(ZodUnknown.create()) - }); - } +ZodOptional.create = (type, params) => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, + ...processCreateParams(params) + }); +}; - returns(returnType) { - return new ZodFunction({ ...this._def, - returns: returnType - }); - } +class ZodNullable extends ZodType { + _parse(input) { + const parsedType = this._getType(input); - implement(func) { - const validatedFunc = this.parse(func); - return validatedFunc; + if (parsedType === parseUtil_1.ZodParsedType.null) { + return (0, parseUtil_1.OK)(null); + } + + return this._def.innerType._parse(input); } - strictImplement(func) { - const validatedFunc = this.parse(func); - return validatedFunc; + unwrap() { + return this._def.innerType; } } -exports.ZodFunction = ZodFunction; +exports.ZodNullable = ZodNullable; -ZodFunction.create = (args, returns, params) => { - return new ZodFunction({ - args: args ? args.rest(ZodUnknown.create()) : ZodTuple.create([]).rest(ZodUnknown.create()), - returns: returns || ZodUnknown.create(), - typeName: ZodFirstPartyTypeKind.ZodFunction, +ZodNullable.create = (type, params) => { + return new ZodNullable({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodNullable, ...processCreateParams(params) }); }; -class ZodLazy extends ZodType { - get schema() { - return this._def.getter(); - } - +class ZodDefault extends ZodType { _parse(input) { const { ctx } = this._processInputParams(input); - const lazySchema = this._def.getter(); + let data = ctx.data; - return lazySchema._parse({ - data: ctx.data, + if (ctx.parsedType === parseUtil_1.ZodParsedType.undefined) { + data = this._def.defaultValue(); + } + + return this._def.innerType._parse({ + data, path: ctx.path, parent: ctx }); } + removeDefault() { + return this._def.innerType; + } + } -exports.ZodLazy = ZodLazy; +exports.ZodDefault = ZodDefault; -ZodLazy.create = (getter, params) => { - return new ZodLazy({ - getter: getter, - typeName: ZodFirstPartyTypeKind.ZodLazy, +ZodDefault.create = (type, params) => { + return new ZodOptional({ + innerType: type, + typeName: ZodFirstPartyTypeKind.ZodOptional, ...processCreateParams(params) }); }; -class ZodLiteral extends ZodType { +class ZodNaN extends ZodType { _parse(input) { - if (input.data !== this._def.value) { + const parsedType = this._getType(input); + + if (parsedType !== parseUtil_1.ZodParsedType.nan) { const ctx = this._getOrReturnCtx(input); (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_literal, - expected: this._def.value + code: ZodError_1.ZodIssueCode.invalid_type, + expected: parseUtil_1.ZodParsedType.nan, + received: ctx.parsedType }); return parseUtil_1.INVALID; } @@ -3842,1051 +3586,1206 @@ class ZodLiteral extends ZodType { }; } - get value() { - return this._def.value; - } - } -exports.ZodLiteral = ZodLiteral; +exports.ZodNaN = ZodNaN; -ZodLiteral.create = (value, params) => { - return new ZodLiteral({ - value: value, - typeName: ZodFirstPartyTypeKind.ZodLiteral, +ZodNaN.create = params => { + return new ZodNaN({ + typeName: ZodFirstPartyTypeKind.ZodNaN, ...processCreateParams(params) }); }; -function createZodEnum(values) { - return new ZodEnum({ - values: values, - typeName: ZodFirstPartyTypeKind.ZodEnum - }); -} +const custom = (check, params) => { + if (check) return ZodAny.create().refine(check, params); + return ZodAny.create(); +}; -class ZodEnum extends ZodType { - _parse(input) { - if (typeof input.data !== "string") { - const ctx = this._getOrReturnCtx(input); +exports.custom = custom; +exports.late = { + object: ZodObject.lazycreate +}; +var ZodFirstPartyTypeKind; - const expectedValues = this._def.values; - (0, parseUtil_1.addIssueToContext)(ctx, { - expected: util_1.util.joinValues(expectedValues), - received: ctx.parsedType, - code: ZodError_1.ZodIssueCode.invalid_type - }); - return parseUtil_1.INVALID; - } +(function (ZodFirstPartyTypeKind) { + ZodFirstPartyTypeKind["ZodString"] = "ZodString"; + ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber"; + ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN"; + ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt"; + ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean"; + ZodFirstPartyTypeKind["ZodDate"] = "ZodDate"; + ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined"; + ZodFirstPartyTypeKind["ZodNull"] = "ZodNull"; + ZodFirstPartyTypeKind["ZodAny"] = "ZodAny"; + ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown"; + ZodFirstPartyTypeKind["ZodNever"] = "ZodNever"; + ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid"; + ZodFirstPartyTypeKind["ZodArray"] = "ZodArray"; + ZodFirstPartyTypeKind["ZodObject"] = "ZodObject"; + ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion"; + ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; + ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection"; + ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple"; + ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord"; + ZodFirstPartyTypeKind["ZodMap"] = "ZodMap"; + ZodFirstPartyTypeKind["ZodSet"] = "ZodSet"; + ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction"; + ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy"; + ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral"; + ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum"; + ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects"; + ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum"; + ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional"; + ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable"; + ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault"; + ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise"; +})(ZodFirstPartyTypeKind = exports.ZodFirstPartyTypeKind || (exports.ZodFirstPartyTypeKind = {})); - if (this._def.values.indexOf(input.data) === -1) { - const ctx = this._getOrReturnCtx(input); +const instanceOfType = function (cls) { + let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { + message: "Input not instance of ".concat(cls.name) + }; + return (0, exports.custom)(data => data instanceof cls, params); +}; - const expectedValues = this._def.values; - (0, parseUtil_1.addIssueToContext)(ctx, { - received: ctx.data, - code: ZodError_1.ZodIssueCode.invalid_enum_value, - options: expectedValues - }); - return parseUtil_1.INVALID; - } +exports.instanceof = instanceOfType; +const stringType = ZodString.create; +exports.string = stringType; +const numberType = ZodNumber.create; +exports.number = numberType; +const nanType = ZodNaN.create; +exports.nan = nanType; +const bigIntType = ZodBigInt.create; +exports.bigint = bigIntType; +const booleanType = ZodBoolean.create; +exports.boolean = booleanType; +const dateType = ZodDate.create; +exports.date = dateType; +const undefinedType = ZodUndefined.create; +exports.undefined = undefinedType; +const nullType = ZodNull.create; +exports.null = nullType; +const anyType = ZodAny.create; +exports.any = anyType; +const unknownType = ZodUnknown.create; +exports.unknown = unknownType; +const neverType = ZodNever.create; +exports.never = neverType; +const voidType = ZodVoid.create; +exports.void = voidType; +const arrayType = ZodArray.create; +exports.array = arrayType; +const objectType = ZodObject.create; +exports.object = objectType; +const strictObjectType = ZodObject.strictCreate; +exports.strictObject = strictObjectType; +const unionType = ZodUnion.create; +exports.union = unionType; +const discriminatedUnionType = ZodDiscriminatedUnion.create; +exports.discriminatedUnion = discriminatedUnionType; +const intersectionType = ZodIntersection.create; +exports.intersection = intersectionType; +const tupleType = ZodTuple.create; +exports.tuple = tupleType; +const recordType = ZodRecord.create; +exports.record = recordType; +const mapType = ZodMap.create; +exports.map = mapType; +const setType = ZodSet.create; +exports.set = setType; +const functionType = ZodFunction.create; +exports.function = functionType; +const lazyType = ZodLazy.create; +exports.lazy = lazyType; +const literalType = ZodLiteral.create; +exports.literal = literalType; +const enumType = ZodEnum.create; +exports.enum = enumType; +const nativeEnumType = ZodNativeEnum.create; +exports.nativeEnum = nativeEnumType; +const promiseType = ZodPromise.create; +exports.promise = promiseType; +const effectsType = ZodEffects.create; +exports.effect = effectsType; +exports.transformer = effectsType; +const optionalType = ZodOptional.create; +exports.optional = optionalType; +const nullableType = ZodNullable.create; +exports.nullable = nullableType; +const preprocessType = ZodEffects.createWithPreprocess; +exports.preprocess = preprocessType; - return (0, parseUtil_1.OK)(input.data); - } +const ostring = () => stringType().optional(); - get options() { - return this._def.values; - } +exports.ostring = ostring; - get enum() { - const enumValues = {}; +const onumber = () => numberType().optional(); - for (const val of this._def.values) { - enumValues[val] = val; - } +exports.onumber = onumber; - return enumValues; - } +const oboolean = () => booleanType().optional(); - get Values() { - const enumValues = {}; +exports.oboolean = oboolean; - for (const val of this._def.values) { - enumValues[val] = val; - } +},{"./ZodError":2,"./helpers/errorUtil":4,"./helpers/parseUtil":5,"./helpers/util":7}],10:[function(require,module,exports){ +"use strict"; - return enumValues; +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; + } +}); - get Enum() { - const enumValues = {}; +var _deviceApiCall = require("./lib/device-api-call.js"); - for (const val of this._def.values) { - enumValues[val] = val; - } +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; } - return enumValues; - } +/** + * 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} + */ -exports.ZodEnum = ZodEnum; -ZodEnum.create = createZodEnum; + /** @type {Params | null | undefined} */ -class ZodNativeEnum extends ZodType { - _parse(input) { - const nativeEnumValues = util_1.util.getValidEnumValues(this._def.values); + /** @type {Result | null | undefined} */ - const ctx = this._getOrReturnCtx(input); + /** @type {import("zod").infer} */ - if (ctx.parsedType !== parseUtil_1.ZodParsedType.string && ctx.parsedType !== parseUtil_1.ZodParsedType.number) { - const expectedValues = util_1.util.objectValues(nativeEnumValues); - (0, parseUtil_1.addIssueToContext)(ctx, { - expected: util_1.util.joinValues(expectedValues), - received: ctx.parsedType, - code: ZodError_1.ZodIssueCode.invalid_type - }); - return parseUtil_1.INVALID; - } + /** + * 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} + */ - if (nativeEnumValues.indexOf(input.data) === -1) { - const expectedValues = util_1.util.objectValues(nativeEnumValues); - (0, parseUtil_1.addIssueToContext)(ctx, { - received: ctx.data, - code: ZodError_1.ZodIssueCode.invalid_enum_value, - options: expectedValues - }); - return parseUtil_1.INVALID; - } + /** + * 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} + */ - return (0, parseUtil_1.OK)(input.data); - } + /** + * @param {import("zod").infer} data + */ + constructor(data) { + _defineProperty(this, "method", 'unknown'); - get enum() { - return this._def.values; - } + _defineProperty(this, "id", null); -} + _defineProperty(this, "paramsValidator", null); -exports.ZodNativeEnum = ZodNativeEnum; + _defineProperty(this, "resultValidator", null); -ZodNativeEnum.create = (values, params) => { - return new ZodNativeEnum({ - values: values, - typeName: ZodFirstPartyTypeKind.ZodNativeEnum, - ...processCreateParams(params) - }); -}; + _defineProperty(this, "params", void 0); -class ZodPromise extends ZodType { - _parse(input) { - const { - ctx - } = this._processInputParams(input); + _defineProperty(this, "throwOnResultKeysMissing", true); - if (ctx.parsedType !== parseUtil_1.ZodParsedType.promise && ctx.common.async === false) { - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.promise, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } + _defineProperty(this, "unwrapResult", true); - const promisified = ctx.parsedType === parseUtil_1.ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data); - return (0, parseUtil_1.OK)(promisified.then(data => { - return this._def.type.parseAsync(data, { - path: ctx.path, - errorMap: ctx.common.contextualErrorMap - }); - })); + this.params = data; } + /** + * @returns {import("zod").infer|undefined} + */ -} -exports.ZodPromise = ZodPromise; + validateParams() { + if (this.params === undefined) { + return undefined; + } -ZodPromise.create = (schema, params) => { - return new ZodPromise({ - type: schema, - typeName: ZodFirstPartyTypeKind.ZodPromise, - ...processCreateParams(params) - }); -}; + this._validate(this.params, this.paramsValidator); -class ZodEffects extends ZodType { - innerType() { - return this._def.schema; + return this.params; } + /** + * @param {any|null} incoming + * @returns {import("zod").infer} + */ - _parse(input) { - const { - status, - ctx - } = this._processInputParams(input); - const effect = this._def.effect || null; + validateResult(incoming) { + this._validate(incoming, this.resultValidator); - if (effect.type === "preprocess") { - const processed = effect.transform(ctx.data); + if (!incoming) { + return incoming; + } - if (ctx.common.async) { - return Promise.resolve(processed).then(processed => { - return this._def.schema._parseAsync({ - data: processed, - path: ctx.path, - parent: ctx - }); - }); - } else { - return this._def.schema._parseSync({ - data: processed, - path: ctx.path, - parent: ctx - }); - } + if (!this.unwrapResult) { + return incoming; } - const checkCtx = { - addIssue: arg => { - (0, parseUtil_1.addIssueToContext)(ctx, arg); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } - if (arg.fatal) { - status.abort(); - } else { - status.dirty(); - } - }, + if ('success' in incoming) { + return incoming.success; + } - get path() { - return ctx.path; + if ('error' in incoming) { + if (typeof incoming.error.message === 'string') { + throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); } + } - }; - checkCtx.addIssue = checkCtx.addIssue.bind(checkCtx); - - if (effect.type === "refinement") { - const executeRefinement = (acc // effect: RefinementEffect - ) => { - const result = effect.refinement(acc, checkCtx); - - if (ctx.common.async) { - return Promise.resolve(result); - } + if (this.throwOnResultKeysMissing) { + throw new Error('unreachable. Response did not contain `success` or `data`'); + } - if (result instanceof Promise) { - throw new Error("Async refinement encountered during synchronous parse operation. Use .parseAsync instead."); - } + return incoming; + } + /** + * @param {any} data + * @param {import("zod").ZodType|undefined|null} [validator] + * @private + */ - return acc; - }; - if (ctx.common.async === false) { - const inner = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); + _validate(data, validator) { + if (!validator) return data; - if (inner.status === "aborted") return parseUtil_1.INVALID; - if (inner.status === "dirty") status.dirty(); // return value is ignored + if (validator) { + const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); - executeRefinement(inner.value); - return { - status: status.value, - value: inner.value - }; - } else { - return this._def.schema._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }).then(inner => { - if (inner.status === "aborted") return parseUtil_1.INVALID; - if (inner.status === "dirty") status.dirty(); - return executeRefinement(inner.value).then(() => { - return { - status: status.value, - value: inner.value - }; - }); - }); + if (!result) { + throw new Error('unreachable, data failure', data); } - } - if (effect.type === "transform") { - if (ctx.common.async === false) { - const base = this._def.schema._parseSync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }); // if (base.status === "aborted") return INVALID; - // if (base.status === "dirty") { - // return { status: "dirty", value: base.value }; - // } + if (!result.success) { + if ('error' in result) { + this.throwError(result.error.issues); + } else { + console.error('unknown error from validate'); + } + } + } + } + /** + * @param {import('zod').ZodIssue[]} errors + */ - if (!(0, parseUtil_1.isValid)(base)) return base; - const result = effect.transform(base.value, checkCtx); + 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} + */ - if (result instanceof Promise) { - throw new Error("Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead."); - } - return { - status: status.value, - value: result - }; - } else { - return this._def.schema._parseAsync({ - data: ctx.data, - path: ctx.path, - parent: ctx - }).then(base => { - if (!(0, parseUtil_1.isValid)(base)) return base; // if (base.status === "aborted") return INVALID; - // if (base.status === "dirty") { - // return { status: "dirty", value: base.value }; - // } + result(response) { + return response; + } + /** + * @returns {import("zod").infer} + */ - return Promise.resolve(effect.transform(base.value, checkCtx)).then(result => ({ - status: status.value, - value: result - })); - }); - } - } - util_1.util.assertNever(effect); + preResultValidation(response) { + return response; } } -exports.ZodEffects = ZodEffects; -exports.ZodTransformer = ZodEffects; - -ZodEffects.create = (schema, effect, params) => { - return new ZodEffects({ - schema, - typeName: ZodFirstPartyTypeKind.ZodEffects, - effect, - ...processCreateParams(params) - }); -}; +exports.DeviceApiCall = DeviceApiCall; -ZodEffects.createWithPreprocess = (preprocess, schema, params) => { - return new ZodEffects({ - schema, - effect: { - type: "preprocess", - transform: preprocess - }, - typeName: ZodFirstPartyTypeKind.ZodEffects, - ...processCreateParams(params) - }); -}; +class DeviceApiCallError extends Error {} +/** + * Check for this error if you'd like to + */ -class ZodOptional extends ZodType { - _parse(input) { - const parsedType = this._getType(input); - if (parsedType === parseUtil_1.ZodParsedType.undefined) { - return (0, parseUtil_1.OK)(undefined); - } +exports.DeviceApiCallError = DeviceApiCallError; - return this._def.innerType._parse(input); - } +class SchemaValidationError extends Error { + constructor() { + super(...arguments); - unwrap() { - return this._def.innerType; + _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; -exports.ZodOptional = ZodOptional; + 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; + } -ZodOptional.create = (type, params) => { - return new ZodOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - ...processCreateParams(params) - }); -}; + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } -class ZodNullable extends ZodType { - _parse(input) { - const parsedType = this._getType(input); + break; + } - if (parsedType === parseUtil_1.ZodParsedType.null) { - return (0, parseUtil_1.OK)(null); + default: + { + console.log(name, 'other issue:', issue); + } + } } - return this._def.innerType._parse(input); - } + for (let error of errors) { + log(error); + } - unwrap() { - return this._def.innerType; + 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.ZodNullable = ZodNullable; -ZodNullable.create = (type, params) => { - return new ZodNullable({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodNullable, - ...processCreateParams(params) - }); -}; +exports.SchemaValidationError = SchemaValidationError; -class ZodDefault extends ZodType { - _parse(input) { - const { - ctx - } = this._processInputParams(input); +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; - let data = ctx.data; + /** @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} + */ - if (ctx.parsedType === parseUtil_1.ZodParsedType.undefined) { - data = this._def.defaultValue(); - } - return this._def.innerType._parse({ - data, - path: ctx.path, - parent: ctx - }); - } +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; +} - removeDefault() { - return this._def.innerType; - } +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; -exports.ZodDefault = ZodDefault; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; -ZodDefault.create = (type, params) => { - return new ZodOptional({ - innerType: type, - typeName: ZodFirstPartyTypeKind.ZodOptional, - ...processCreateParams(params) - }); -}; + if (validator) { + return validator.parse(data); + } + + return data; +} -class ZodNaN extends ZodType { - _parse(input) { - const parsedType = this._getType(input); +},{}],12:[function(require,module,exports){ +"use strict"; - if (parsedType !== parseUtil_1.ZodParsedType.nan) { - const ctx = this._getOrReturnCtx(input); +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.DeviceApiTransport = exports.DeviceApi = void 0; - (0, parseUtil_1.addIssueToContext)(ctx, { - code: ZodError_1.ZodIssueCode.invalid_type, - expected: parseUtil_1.ZodParsedType.nan, - received: ctx.parsedType - }); - return parseUtil_1.INVALID; - } +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; } - return { - status: "valid", - value: input.data - }; +/** + * 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.ZodNaN = ZodNaN; - -ZodNaN.create = params => { - return new ZodNaN({ - typeName: ZodFirstPartyTypeKind.ZodNaN, - ...processCreateParams(params) - }); -}; - -const custom = (check, params) => { - if (check) return ZodAny.create().refine(check, params); - return ZodAny.create(); -}; -exports.custom = custom; -exports.late = { - object: ZodObject.lazycreate -}; -var ZodFirstPartyTypeKind; +exports.DeviceApiTransport = DeviceApiTransport; -(function (ZodFirstPartyTypeKind) { - ZodFirstPartyTypeKind["ZodString"] = "ZodString"; - ZodFirstPartyTypeKind["ZodNumber"] = "ZodNumber"; - ZodFirstPartyTypeKind["ZodNaN"] = "ZodNaN"; - ZodFirstPartyTypeKind["ZodBigInt"] = "ZodBigInt"; - ZodFirstPartyTypeKind["ZodBoolean"] = "ZodBoolean"; - ZodFirstPartyTypeKind["ZodDate"] = "ZodDate"; - ZodFirstPartyTypeKind["ZodUndefined"] = "ZodUndefined"; - ZodFirstPartyTypeKind["ZodNull"] = "ZodNull"; - ZodFirstPartyTypeKind["ZodAny"] = "ZodAny"; - ZodFirstPartyTypeKind["ZodUnknown"] = "ZodUnknown"; - ZodFirstPartyTypeKind["ZodNever"] = "ZodNever"; - ZodFirstPartyTypeKind["ZodVoid"] = "ZodVoid"; - ZodFirstPartyTypeKind["ZodArray"] = "ZodArray"; - ZodFirstPartyTypeKind["ZodObject"] = "ZodObject"; - ZodFirstPartyTypeKind["ZodUnion"] = "ZodUnion"; - ZodFirstPartyTypeKind["ZodDiscriminatedUnion"] = "ZodDiscriminatedUnion"; - ZodFirstPartyTypeKind["ZodIntersection"] = "ZodIntersection"; - ZodFirstPartyTypeKind["ZodTuple"] = "ZodTuple"; - ZodFirstPartyTypeKind["ZodRecord"] = "ZodRecord"; - ZodFirstPartyTypeKind["ZodMap"] = "ZodMap"; - ZodFirstPartyTypeKind["ZodSet"] = "ZodSet"; - ZodFirstPartyTypeKind["ZodFunction"] = "ZodFunction"; - ZodFirstPartyTypeKind["ZodLazy"] = "ZodLazy"; - ZodFirstPartyTypeKind["ZodLiteral"] = "ZodLiteral"; - ZodFirstPartyTypeKind["ZodEnum"] = "ZodEnum"; - ZodFirstPartyTypeKind["ZodEffects"] = "ZodEffects"; - ZodFirstPartyTypeKind["ZodNativeEnum"] = "ZodNativeEnum"; - ZodFirstPartyTypeKind["ZodOptional"] = "ZodOptional"; - ZodFirstPartyTypeKind["ZodNullable"] = "ZodNullable"; - ZodFirstPartyTypeKind["ZodDefault"] = "ZodDefault"; - ZodFirstPartyTypeKind["ZodPromise"] = "ZodPromise"; -})(ZodFirstPartyTypeKind = exports.ZodFirstPartyTypeKind || (exports.ZodFirstPartyTypeKind = {})); +class DeviceApi { + /** @type {DeviceApiTransport} */ -const instanceOfType = function (cls) { - let params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : { - message: "Input not instance of ".concat(cls.name) - }; - return (0, exports.custom)(data => data instanceof cls, params); -}; + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); -exports.instanceof = instanceOfType; -const stringType = ZodString.create; -exports.string = stringType; -const numberType = ZodNumber.create; -exports.number = numberType; -const nanType = ZodNaN.create; -exports.nan = nanType; -const bigIntType = ZodBigInt.create; -exports.bigint = bigIntType; -const booleanType = ZodBoolean.create; -exports.boolean = booleanType; -const dateType = ZodDate.create; -exports.date = dateType; -const undefinedType = ZodUndefined.create; -exports.undefined = undefinedType; -const nullType = ZodNull.create; -exports.null = nullType; -const anyType = ZodAny.create; -exports.any = anyType; -const unknownType = ZodUnknown.create; -exports.unknown = unknownType; -const neverType = ZodNever.create; -exports.never = neverType; -const voidType = ZodVoid.create; -exports.void = voidType; -const arrayType = ZodArray.create; -exports.array = arrayType; -const objectType = ZodObject.create; -exports.object = objectType; -const strictObjectType = ZodObject.strictCreate; -exports.strictObject = strictObjectType; -const unionType = ZodUnion.create; -exports.union = unionType; -const discriminatedUnionType = ZodDiscriminatedUnion.create; -exports.discriminatedUnion = discriminatedUnionType; -const intersectionType = ZodIntersection.create; -exports.intersection = intersectionType; -const tupleType = ZodTuple.create; -exports.tuple = tupleType; -const recordType = ZodRecord.create; -exports.record = recordType; -const mapType = ZodMap.create; -exports.map = mapType; -const setType = ZodSet.create; -exports.set = setType; -const functionType = ZodFunction.create; -exports.function = functionType; -const lazyType = ZodLazy.create; -exports.lazy = lazyType; -const literalType = ZodLiteral.create; -exports.literal = literalType; -const enumType = ZodEnum.create; -exports.enum = enumType; -const nativeEnumType = ZodNativeEnum.create; -exports.nativeEnum = nativeEnumType; -const promiseType = ZodPromise.create; -exports.promise = promiseType; -const effectsType = ZodEffects.create; -exports.effect = effectsType; -exports.transformer = effectsType; -const optionalType = ZodOptional.create; -exports.optional = optionalType; -const nullableType = ZodNullable.create; -exports.nullable = nullableType; -const preprocessType = ZodEffects.createWithPreprocess; -exports.preprocess = preprocessType; + this.transport = transport; + } + /** + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} + */ -const ostring = () => stringType().optional(); -exports.ostring = ostring; + 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} + */ -const onumber = () => numberType().optional(); -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", { - 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", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.validate; + return _webkit.WebkitMessagingConfig; } }); -var _deviceApiCall = require("./lib/device-api-call.js"); +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); + } + /** + * 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] + */ -var _deviceApi = require("./lib/device-api.js"); -},{"./lib/device-api-call.js":15,"./lib/device-api.js":16}],15:[function(require,module,exports){ -"use strict"; + 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 {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} + */ -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; } + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); + } +} /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @interface */ -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} */ +exports.Messaging = Messaging; +class MessagingTransport { /** - * 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} + * @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'"); + } /** - * 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 {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 - /** - * @param {import("zod").infer} data - */ - 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} 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); + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ - this.params = data; - } + +class MissingHandler extends Error { /** - * @returns {import("zod").infer|undefined} + * @param {string} message + * @param {string} handlerName */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } +} +/** + * Some re-exports for convenience + */ - validateParams() { - if (this.params === undefined) { - return undefined; - } - this._validate(this.params, this.paramsValidator); +exports.MissingHandler = MissingHandler; - return this.params; - } - /** - * @param {any|null} incoming - * @returns {import("zod").infer} - */ +},{"./webkit.js":14}],14:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; - validateResult(incoming) { - this._validate(incoming, this.resultValidator); +var _messaging = require("./messaging.js"); - if (!incoming) { - return incoming; - } +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 (!this.unwrapResult) { - return incoming; - } +/** + * @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); - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } + _defineProperty(this, "globals", void 0); - if ('success' in incoming) { - return incoming.success; - } + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); - if ('error' in incoming) { - if (typeof incoming.error.message === 'string') { - throw new DeviceApiCallError("".concat(this.method, ": ").concat(incoming.error.message)); - } - } + this.config = config; + this.globals = captureGlobals(); - if (this.throwOnResultKeysMissing) { - throw new Error('unreachable. Response did not contain `success` or `data`'); + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); } - - return incoming; } /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - _validate(data, validator) { - if (!validator) return data; + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(data); + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - if (!result) { - throw new Error('unreachable, data failure', data); + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); + } + + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret } + }; - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } + 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 (_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 {import('zod').ZodIssue[]} errors + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - 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} - */ + 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 || '{}'); + } - result(response) { - return 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 + }; + } + } } /** - * @returns {import("zod").infer} + * @param {string} name + * @param {Record} [data] */ - 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", []); + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.wkSend(name, data); } - /** - * @param {import("zod").ZodIssue[]} errors * @param {string} name - * @returns {SchemaValidationError} + * @param {Record} [data] */ - 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); - } - } - } + // eslint-disable-next-line @typescript-eslint/no-unused-vars - 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; + 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 + */ -} -/** - * 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} - */ + generateRandomMethod(randomMethodName, callback) { + var _this = this; -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; -} + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, -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} - */ + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -exports.createNotification = createNotification; + delete _this.globals.window[randomMethodName]; + } + }); + } -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } - if (validator) { - return validator.parse(data); + createRandMethodName() { + return '_' + this.randomString(); } + /** + * @type {{name: string, length: number}} + */ - return data; -} -},{}],16:[function(require,module,exports){ -"use strict"; + /** + * @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} + */ -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; } + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } + /** + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ -/** - * Platforms should only need to implement this `send` method - */ -class DeviceApiTransport { + + 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); + } /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - async send(_deviceApiCall, _options) { - return undefined; + + + 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; + + /** + * `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; + } + } } } /** - * This is the base Sender class that platforms can will implement. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * Note: The 'handle' method must be implemented, unless you also implement 'send' + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * @typedef CallOptions - * @property {AbortSignal} [signal] + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); + * + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -exports.DeviceApiTransport = DeviceApiTransport; - -class DeviceApi { - /** @type {DeviceApiTransport} */ - - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); +exports.WebkitMessagingTransport = WebkitMessagingTransport; - this.transport = transport; - } +class WebkitMessagingConfig { /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} + * @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 + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); + 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 + */ + + +exports.WebkitMessagingConfig = WebkitMessagingConfig; + +class SecureMessagingParams { /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} + * @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[] + */ - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); + 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 + */ -exports.DeviceApi = DeviceApi; -},{}],17:[function(require,module,exports){ +exports.SecureMessagingParams = SecureMessagingParams; + +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: {} + }; +} + +},{"./messaging.js":13}],15:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -5035,7 +4934,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 +5558,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 +5579,7 @@ const constants = { }; exports.constants = constants; -},{}],20:[function(require,module,exports){ +},{}],18:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -6413,7 +6312,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 +7143,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 +7216,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 +7366,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 +7818,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 +7973,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 +8251,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 +9320,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 +9536,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 +9745,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 +9851,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 +9918,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 +9979,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],33:[function(require,module,exports){ +},{}],31:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -11000,7 +10899,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 +11293,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 +11861,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 +12218,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 +12320,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 +12600,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 +12661,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 +12675,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 +18047,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 +18082,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 +18170,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],64:[function(require,module,exports){ +},{}],62:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18289,7 +18188,7 @@ const constants = { }; exports.constants = constants; -},{}],65:[function(require,module,exports){ +},{}],63:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -18779,7 +18678,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 +19184,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 +19225,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 +19383,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 +19391,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 +19402,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 +19419,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 +19459,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 +19631,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 +19685,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 +19785,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 +19833,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..ab9bcf8e1 100644 --- a/swift-package/Resources/assets/autofill.js +++ b/swift-package/Resources/assets/autofill.js @@ -58,1159 +58,1058 @@ 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; + } + + this._validate(this.params, this.paramsValidator); -class MissingHandler extends Error { + 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 - */ + validateResult(incoming) { + this._validate(incoming, this.resultValidator); -exports.MissingHandler = MissingHandler; + if (!incoming) { + return incoming; + } -},{"./messaging/webkit.js":4,"./messaging/windows.js":5}],4:[function(require,module,exports){ -"use strict"; + if (!this.unwrapResult) { + return incoming; + } -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; } - -/** - * @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); + if ('data' in incoming) { + console.warn('response had `data` property. Please migrate to `success`'); + return incoming.data; + } - _defineProperty(this, "algoObj", { - name: 'AES-GCM', - length: 256 - }); + if ('success' in incoming) { + return incoming.success; + } - 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} - */ - - - 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 _messaging.MissingHandler('window.webkit.messageHandlers was absent', 'all'); - - for (let webkitMessageHandlerName of handlerNames) { - var _handlers$webkitMessa; + case 'invalid_union': + { + for (let unionError of issue.unionErrors) { + for (let issue1 of unionError.issues) { + log(issue1); + } + } - if (typeof ((_handlers$webkitMessa = handlers[webkitMessageHandlerName]) === null || _handlers$webkitMessa === void 0 ? void 0 : _handlers$webkitMessa.postMessage) === 'function') { - var _handlers$webkitMessa2; + break; + } - /** - * `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; + 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; } } /** - * 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", - * }); + * Creates an instance of `DeviceApiCall` from only a name and 'params' + * and optional validators. Use this to help migrate existing messages. * - * 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 {Params|null} [paramsValidator] + * @param {Result|null} [resultValidator] + * @returns {DeviceApiCall} */ -exports.WebkitMessagingTransport = WebkitMessagingTransport; - -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 - */ +exports.SchemaValidationError = SchemaValidationError; - this.secret = params.secret; - } +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; } /** - * 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 + * 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} */ -exports.WebkitMessagingConfig = WebkitMessagingConfig; - -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; - } - +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; /** - * Capture some globals used for messaging handling to prevent page - * scripts from tampering with this + * 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; -exports.SecureMessagingParams = SecureMessagingParams; +function validate(data) { + let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; -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), + if (validator) { + return validator.parse(data); + } - /** @type {Record} */ - capturedWebkitHandlers: {} - }; + return data; } -},{"../messaging.js":3}],5:[function(require,module,exports){ +},{}],4:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); -exports.WindowsMessagingTransport = exports.WindowsMessagingConfig = void 0; - -var _messaging = require("../messaging.js"); +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; } /** - * @implements {MessagingTransport} + * Platforms should only need to implement this `send` method */ -class WindowsMessagingTransport { +class DeviceApiTransport { /** - * @param {WindowsMessagingConfig} config + * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall + * @param {CallOptions} [_options] + * @returns {Promise} */ - constructor(config) { - _defineProperty(this, "config", void 0); - - this.config = config; + async send(_deviceApiCall, _options) { + return undefined; } - /** - * @param {string} name - * @param {Record} [data] - */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars +} +/** + * 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] + */ - notify(name) { - let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - throw new Error('todo: implement notify for windows'); + +exports.DeviceApiTransport = DeviceApiTransport; + +class DeviceApi { + /** @type {DeviceApiTransport} */ + + /** @param {DeviceApiTransport} transport */ + constructor(transport) { + _defineProperty(this, "transport", void 0); + + this.transport = transport; } /** - * @param {string} name - * @param {Record} [data] - * @param {{signal?: AbortSignal}} opts - * @return {Promise} + * @template {import("./device-api-call").DeviceApiCall} D + * @param {D} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise['success']>>} */ - // @ts-ignore - // eslint-disable-next-line @typescript-eslint/no-unused-vars - 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'); + async request(deviceApiCall, options) { + deviceApiCall.validateParams(); + let result = await this.transport.send(deviceApiCall, options); + let processed = deviceApiCall.preResultValidation(result); + return deviceApiCall.validateResult(processed); } - -} - -exports.WindowsMessagingTransport = WindowsMessagingTransport; - -class WindowsMessagingConfig { /** - * @param {object} params - * @param {string} params.featureName + * @template {import("./device-api-call").DeviceApiCall} P + * @param {P} deviceApiCall + * @param {CallOptions} [options] + * @returns {Promise} */ - constructor(params) { - this.featureName = params.featureName; + + + async notify(deviceApiCall, options) { + deviceApiCall.validateParams(); + return this.transport.send(deviceApiCall, options); } } -exports.WindowsMessagingConfig = WindowsMessagingConfig; +exports.DeviceApi = DeviceApi; -},{"../messaging.js":3}],6:[function(require,module,exports){ +},{}],5:[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", { +exports.MissingHandler = exports.MessagingTransport = exports.Messaging = void 0; +Object.defineProperty(exports, "WebkitMessagingConfig", { enumerable: true, get: function () { - return _deviceApiCall.validate; + return _webkit.WebkitMessagingConfig; } }); -var _deviceApiCall = require("./lib/device-api-call.js"); - -var _deviceApi = require("./lib/device-api.js"); - -},{"./lib/device-api-call.js":7,"./lib/device-api.js":8}],7:[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; } +var _webkit = require("./webkit.js"); /** - * This roughly follows https://www.jsonrpc.org/specification - * @template {import("zod").ZodType} Params=import("zod").ZodType - * @template {import("zod").ZodType} Result=import("zod").ZodType + * @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() }) + * ``` */ -class DeviceApiCall { - /** @type {string} */ +/** + * @implements {MessagingTransport} + */ +class Messaging { /** - * An optional 'id' - used to indicate if a request requires a response. - * @type {string|null} + * @param {WebkitMessagingConfig} config */ - - /** @type {Params | null | undefined} */ - - /** @type {Result | null | undefined} */ - - /** @type {import("zod").infer} */ - + constructor(config) { + this.transport = getTransport(config); + } /** - * 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} + * 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] */ - /** - * 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} - */ + notify(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + this.transport.notify(name, data); + } /** - * @param {import("zod").infer} 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} */ - constructor(data) { - _defineProperty(this, "method", 'unknown'); - _defineProperty(this, "id", null); - - _defineProperty(this, "paramsValidator", null); - _defineProperty(this, "resultValidator", null); + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + return this.transport.request(name, data); + } - _defineProperty(this, "params", void 0); +} +/** + * @interface + */ - _defineProperty(this, "throwOnResultKeysMissing", true); - _defineProperty(this, "unwrapResult", true); +exports.Messaging = Messaging; - this.params = data; +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'"); } /** - * @returns {import("zod").infer|undefined} + * @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 - validateParams() { - if (this.params === undefined) { - return undefined; - } + request(name) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + throw new Error('must implement'); + } - this._validate(this.params, this.paramsValidator); +} +/** + * @param {WebkitMessagingConfig} config + * @returns {MessagingTransport} + */ - return this.params; - } - /** - * @param {any|null} incoming - * @returns {import("zod").infer} - */ +exports.MessagingTransport = MessagingTransport; - validateResult(incoming) { - this._validate(incoming, this.resultValidator); +function getTransport(config) { + if (config instanceof _webkit.WebkitMessagingConfig) { + return new _webkit.WebkitMessagingTransport(config); + } - if (!incoming) { - return incoming; - } + throw new Error('unreachable'); +} +/** + * Thrown when a handler cannot be found + */ - if (!this.unwrapResult) { - return incoming; - } - if ('data' in incoming) { - console.warn('response had `data` property. Please migrate to `success`'); - return incoming.data; - } +class MissingHandler extends Error { + /** + * @param {string} message + * @param {string} handlerName + */ + constructor(message, handlerName) { + super(message); + this.handlerName = handlerName; + } - if ('success' in incoming) { - return incoming.success; - } +} +/** + * Some re-exports for convenience + */ - 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`'); - } +exports.MissingHandler = MissingHandler; - return incoming; - } - /** - * @param {any} data - * @param {import("zod").ZodType|undefined|null} [validator] - * @private - */ +},{"./webkit.js":6}],6:[function(require,module,exports){ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.WebkitMessagingTransport = exports.WebkitMessagingConfig = exports.SecureMessagingParams = void 0; - _validate(data, validator) { - if (!validator) return data; +var _messaging = require("./messaging.js"); - if (validator) { - const result = validator === null || validator === void 0 ? void 0 : validator.safeParse(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 (!result) { - throw new Error('unreachable, data failure', data); - } +/** + * @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} */ - if (!result.success) { - if ('error' in result) { - this.throwError(result.error.issues); - } else { - console.error('unknown error from validate'); - } - } - } - } /** - * @param {import('zod').ZodIssue[]} errors + * @param {WebkitMessagingConfig} config */ + constructor(config) { + _defineProperty(this, "config", void 0); + _defineProperty(this, "globals", void 0); - 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} - */ + _defineProperty(this, "algoObj", { + name: 'AES-GCM', + length: 256 + }); + this.config = config; + this.globals = captureGlobals(); - result(response) { - return response; + if (!this.config.hasModernWebkitAPI) { + this.captureWebkitHandlers(this.config.webkitMessageHandlerNames); + } } /** - * @returns {import("zod").infer} + * Sends message to the webkit layer (fire and forget) + * @param {String} handler + * @param {*} data + * @internal */ - preResultValidation(response) { - return response; - } - -} - -exports.DeviceApiCall = DeviceApiCall; + wkSend(handler) { + var _this$globals$window$, _this$globals$window$2; -class DeviceApiCallError extends Error {} -/** - * Check for this error if you'd like to - */ + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; + if (!(handler in this.globals.window.webkit.messageHandlers)) { + throw new _messaging.MissingHandler("Missing webkit handler: '".concat(handler, "'"), handler); + } -exports.DeviceApiCallError = DeviceApiCallError; + const outgoing = { ...data, + messageHandling: { ...data.messageHandling, + secret: this.config.secret + } + }; -class SchemaValidationError extends Error { - constructor() { - super(...arguments); + 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); + } + } - _defineProperty(this, "validationErrors", []); + 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 {import("zod").ZodIssue[]} errors - * @param {string} name - * @returns {SchemaValidationError} + * Sends message to the webkit layer and waits for the specified response + * @param {String} handler + * @param {*} data + * @returns {Promise<*>} + * @internal */ - 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); - } - } + async wkSendAndWait(handler) { + let data = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; - break; - } + if (this.config.hasModernWebkitAPI) { + const response = await this.wkSend(handler, data); + return this.globals.JSONparse(response || '{}'); + } - default: - { - console.log(name, 'other issue:', issue); - } + 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 {string} name + * @param {Record} [data] + */ - 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; + 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 -} -/** - * 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} - */ + 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 + */ -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; + generateRandomMethod(randomMethodName, callback) { + var _this = this; - /** @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} - */ + this.globals.ObjectDefineProperty(this.globals.window, randomMethodName, { + enumerable: false, + // configurable, To allow for deletion later + configurable: true, + writable: false, + /** + * @param {any[]} args + */ + value: function () { + callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. -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; -} + delete _this.globals.window[randomMethodName]; + } + }); + } -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} - */ + randomString() { + return '' + this.globals.getRandomValues(new this.globals.Uint32Array(1))[0]; + } -exports.createNotification = createNotification; + createRandMethodName() { + return '_' + this.randomString(); + } + /** + * @type {{name: string, length: number}} + */ -function validate(data) { - let validator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - if (validator) { - return validator.parse(data); + /** + * @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} + */ - return data; -} - -},{}],8:[function(require,module,exports){ -"use strict"; -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.DeviceApiTransport = exports.DeviceApi = void 0; + createRandIv() { + return this.globals.getRandomValues(new this.globals.Uint8Array(12)); + } + /** + * @param {BufferSource} ciphertext + * @param {BufferSource} key + * @param {Uint8Array} iv + * @returns {Promise} + */ -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 { + 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); + } /** - * @param {import("./device-api-call.js").DeviceApiCall} _deviceApiCall - * @param {CallOptions} [_options] - * @returns {Promise} + * When required (such as on macos 10.x), capture the `postMessage` method on + * each webkit messageHandler + * + * @param {string[]} handlerNames */ - async send(_deviceApiCall, _options) { - return undefined; + + + 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; + + /** + * `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; + } + } } } /** - * This is the base Sender class that platforms can will implement. + * Use this configuration to create an instance of {@link Messaging} for WebKit * - * Note: The 'handle' method must be implemented, unless you also implement 'send' + * ```js + * import { fromConfig, WebkitMessagingConfig } from "@duckduckgo/content-scope-scripts/lib/messaging.js" * - * @typedef CallOptions - * @property {AbortSignal} [signal] + * const config = new WebkitMessagingConfig({ + * hasModernWebkitAPI: true, + * webkitMessageHandlerNames: ["foo", "bar", "baz"], + * secret: "dax", + * }); + * + * const messaging = new Messaging(config) + * const resp = await messaging.request("debugConfig") + * ``` */ -exports.DeviceApiTransport = DeviceApiTransport; - -class DeviceApi { - /** @type {DeviceApiTransport} */ - - /** @param {DeviceApiTransport} transport */ - constructor(transport) { - _defineProperty(this, "transport", void 0); +exports.WebkitMessagingTransport = WebkitMessagingTransport; - this.transport = transport; - } +class WebkitMessagingConfig { /** - * @template {import("./device-api-call").DeviceApiCall} D - * @param {D} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise['success']>>} + * @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 + */ - async request(deviceApiCall, options) { - deviceApiCall.validateParams(); - let result = await this.transport.send(deviceApiCall, options); - let processed = deviceApiCall.preResultValidation(result); - return deviceApiCall.validateResult(processed); + 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 + */ + + +exports.WebkitMessagingConfig = WebkitMessagingConfig; + +class SecureMessagingParams { /** - * @template {import("./device-api-call").DeviceApiCall} P - * @param {P} deviceApiCall - * @param {CallOptions} [options] - * @returns {Promise} + * @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[] + */ - async notify(deviceApiCall, options) { - deviceApiCall.validateParams(); - return this.transport.send(deviceApiCall, options); + 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 + */ -exports.DeviceApi = DeviceApi; -},{}],9:[function(require,module,exports){ +exports.SecureMessagingParams = SecureMessagingParams; + +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: {} + }; +} + +},{"./messaging.js":5}],7:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -1359,7 +1258,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 +1882,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 +1903,7 @@ const constants = { }; exports.constants = constants; -},{}],12:[function(require,module,exports){ +},{}],10:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -2737,7 +2636,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 +3467,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 +3540,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 +3690,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 +4142,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 +4297,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 +4575,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 +5644,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 +5860,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 +6069,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 +6175,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 +6242,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 +6303,7 @@ class EmailProtection { exports.EmailProtection = EmailProtection; -},{}],25:[function(require,module,exports){ +},{}],23:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -7324,7 +7223,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 +7617,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 +8185,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 +8542,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 +8644,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 +8924,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 +8985,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 +8999,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 +14371,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 +14406,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 +14494,7 @@ function createGlobalConfig(overrides) { return config; } -},{}],56:[function(require,module,exports){ +},{}],54:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -14613,7 +14512,7 @@ const constants = { }; exports.constants = constants; -},{}],57:[function(require,module,exports){ +},{}],55:[function(require,module,exports){ "use strict"; Object.defineProperty(exports, "__esModule", { @@ -15103,7 +15002,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 +15086,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 +15127,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 +15285,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 +15293,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 +15304,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 +15321,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 +15361,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 +15533,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 +15587,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 +15687,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 +15735,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" ], From 85b4e9c388b1ec47be6e40eb643929550df6a22a Mon Sep 17 00:00:00 2001 From: Shane Osbourne Date: Tue, 26 Sep 2023 09:19:59 +0100 Subject: [PATCH 2/2] compiled assets --- dist/autofill-debug.js | 141 +++++++++--------- dist/autofill.js | 141 +++++++++--------- .../Resources/assets/autofill-debug.js | 141 +++++++++--------- swift-package/Resources/assets/autofill.js | 141 +++++++++--------- 4 files changed, 284 insertions(+), 280 deletions(-) diff --git a/dist/autofill-debug.js b/dist/autofill-debug.js index 2dafa7744..f97dbde2f 100644 --- a/dist/autofill-debug.js +++ b/dist/autofill-debug.js @@ -4251,25 +4251,25 @@ var _webkit = require("./webkit.js"); */ class Messaging { /** - * @param {WebkitMessagingConfig} config - */ + * @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] - */ + * 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) { @@ -4277,20 +4277,20 @@ class Messaging { 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} - */ + * 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) { @@ -4308,23 +4308,21 @@ exports.Messaging = Messaging; class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ + * @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'"); } /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + * @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 request(name) { @@ -4355,9 +4353,9 @@ function getTransport(config) { class MissingHandler extends Error { /** - * @param {string} message - * @param {string} handlerName - */ + * @param {string} message + * @param {string} handlerName + */ constructor(message, handlerName) { super(message); this.handlerName = handlerName; @@ -4383,6 +4381,10 @@ 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` @@ -4551,7 +4553,6 @@ class WebkitMessagingTransport { * @param {string} name * @param {Record} [data] */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars request(name) { @@ -4576,8 +4577,8 @@ class WebkitMessagingTransport { writable: false, /** - * @param {any[]} args - */ + * @param {any[]} args + */ value: function () { callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. @@ -4651,9 +4652,9 @@ class WebkitMessagingTransport { var _handlers$webkitMessa2; /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ + * `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; @@ -4685,11 +4686,11 @@ exports.WebkitMessagingTransport = WebkitMessagingTransport; class WebkitMessagingConfig { /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ + * @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 @@ -4697,14 +4698,14 @@ class WebkitMessagingConfig { */ this.hasModernWebkitAPI = params.hasModernWebkitAPI; /** - * A list of WebKit message handler names that a user script can send - */ + * 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 - */ + * A string provided by native platforms to be sent with future outgoing + * messages + */ this.secret = params.secret; } @@ -4720,30 +4721,30 @@ exports.WebkitMessagingConfig = WebkitMessagingConfig; class SecureMessagingParams { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ + * @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 - */ + * The secret used to ensure message sender validity + */ this.secret = params.secret; /** - * The CipherKey as number[] - */ + * The CipherKey as number[] + */ this.key = params.key; /** - * The Initial Vector as number[] - */ + * The Initial Vector as number[] + */ this.iv = params.iv; } diff --git a/dist/autofill.js b/dist/autofill.js index ab9bcf8e1..24c9967c9 100644 --- a/dist/autofill.js +++ b/dist/autofill.js @@ -575,25 +575,25 @@ var _webkit = require("./webkit.js"); */ class Messaging { /** - * @param {WebkitMessagingConfig} config - */ + * @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] - */ + * 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) { @@ -601,20 +601,20 @@ class Messaging { 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} - */ + * 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) { @@ -632,23 +632,21 @@ exports.Messaging = Messaging; class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ + * @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'"); } /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + * @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 request(name) { @@ -679,9 +677,9 @@ function getTransport(config) { class MissingHandler extends Error { /** - * @param {string} message - * @param {string} handlerName - */ + * @param {string} message + * @param {string} handlerName + */ constructor(message, handlerName) { super(message); this.handlerName = handlerName; @@ -707,6 +705,10 @@ 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` @@ -875,7 +877,6 @@ class WebkitMessagingTransport { * @param {string} name * @param {Record} [data] */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars request(name) { @@ -900,8 +901,8 @@ class WebkitMessagingTransport { writable: false, /** - * @param {any[]} args - */ + * @param {any[]} args + */ value: function () { callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. @@ -975,9 +976,9 @@ class WebkitMessagingTransport { var _handlers$webkitMessa2; /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ + * `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; @@ -1009,11 +1010,11 @@ exports.WebkitMessagingTransport = WebkitMessagingTransport; class WebkitMessagingConfig { /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ + * @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 @@ -1021,14 +1022,14 @@ class WebkitMessagingConfig { */ this.hasModernWebkitAPI = params.hasModernWebkitAPI; /** - * A list of WebKit message handler names that a user script can send - */ + * 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 - */ + * A string provided by native platforms to be sent with future outgoing + * messages + */ this.secret = params.secret; } @@ -1044,30 +1045,30 @@ exports.WebkitMessagingConfig = WebkitMessagingConfig; class SecureMessagingParams { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ + * @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 - */ + * The secret used to ensure message sender validity + */ this.secret = params.secret; /** - * The CipherKey as number[] - */ + * The CipherKey as number[] + */ this.key = params.key; /** - * The Initial Vector as number[] - */ + * The Initial Vector as number[] + */ this.iv = params.iv; } diff --git a/swift-package/Resources/assets/autofill-debug.js b/swift-package/Resources/assets/autofill-debug.js index 2dafa7744..f97dbde2f 100644 --- a/swift-package/Resources/assets/autofill-debug.js +++ b/swift-package/Resources/assets/autofill-debug.js @@ -4251,25 +4251,25 @@ var _webkit = require("./webkit.js"); */ class Messaging { /** - * @param {WebkitMessagingConfig} config - */ + * @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] - */ + * 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) { @@ -4277,20 +4277,20 @@ class Messaging { 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} - */ + * 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) { @@ -4308,23 +4308,21 @@ exports.Messaging = Messaging; class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ + * @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'"); } /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + * @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 request(name) { @@ -4355,9 +4353,9 @@ function getTransport(config) { class MissingHandler extends Error { /** - * @param {string} message - * @param {string} handlerName - */ + * @param {string} message + * @param {string} handlerName + */ constructor(message, handlerName) { super(message); this.handlerName = handlerName; @@ -4383,6 +4381,10 @@ 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` @@ -4551,7 +4553,6 @@ class WebkitMessagingTransport { * @param {string} name * @param {Record} [data] */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars request(name) { @@ -4576,8 +4577,8 @@ class WebkitMessagingTransport { writable: false, /** - * @param {any[]} args - */ + * @param {any[]} args + */ value: function () { callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. @@ -4651,9 +4652,9 @@ class WebkitMessagingTransport { var _handlers$webkitMessa2; /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ + * `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; @@ -4685,11 +4686,11 @@ exports.WebkitMessagingTransport = WebkitMessagingTransport; class WebkitMessagingConfig { /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ + * @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 @@ -4697,14 +4698,14 @@ class WebkitMessagingConfig { */ this.hasModernWebkitAPI = params.hasModernWebkitAPI; /** - * A list of WebKit message handler names that a user script can send - */ + * 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 - */ + * A string provided by native platforms to be sent with future outgoing + * messages + */ this.secret = params.secret; } @@ -4720,30 +4721,30 @@ exports.WebkitMessagingConfig = WebkitMessagingConfig; class SecureMessagingParams { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ + * @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 - */ + * The secret used to ensure message sender validity + */ this.secret = params.secret; /** - * The CipherKey as number[] - */ + * The CipherKey as number[] + */ this.key = params.key; /** - * The Initial Vector as number[] - */ + * The Initial Vector as number[] + */ this.iv = params.iv; } diff --git a/swift-package/Resources/assets/autofill.js b/swift-package/Resources/assets/autofill.js index ab9bcf8e1..24c9967c9 100644 --- a/swift-package/Resources/assets/autofill.js +++ b/swift-package/Resources/assets/autofill.js @@ -575,25 +575,25 @@ var _webkit = require("./webkit.js"); */ class Messaging { /** - * @param {WebkitMessagingConfig} config - */ + * @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] - */ + * 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) { @@ -601,20 +601,20 @@ class Messaging { 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} - */ + * 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) { @@ -632,23 +632,21 @@ exports.Messaging = Messaging; class MessagingTransport { /** - * @param {string} name - * @param {Record} [data] - * @returns {void} - */ + * @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'"); } /** - * @param {string} name - * @param {Record} [data] - * @return {Promise} - */ + * @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 request(name) { @@ -679,9 +677,9 @@ function getTransport(config) { class MissingHandler extends Error { /** - * @param {string} message - * @param {string} handlerName - */ + * @param {string} message + * @param {string} handlerName + */ constructor(message, handlerName) { super(message); this.handlerName = handlerName; @@ -707,6 +705,10 @@ 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` @@ -875,7 +877,6 @@ class WebkitMessagingTransport { * @param {string} name * @param {Record} [data] */ - // eslint-disable-next-line @typescript-eslint/no-unused-vars request(name) { @@ -900,8 +901,8 @@ class WebkitMessagingTransport { writable: false, /** - * @param {any[]} args - */ + * @param {any[]} args + */ value: function () { callback(...arguments); // @ts-ignore - we want this to throw if it fails as it would indicate a fatal error. @@ -975,9 +976,9 @@ class WebkitMessagingTransport { var _handlers$webkitMessa2; /** - * `bind` is used here to ensure future calls to the captured - * `postMessage` have the correct `this` context - */ + * `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; @@ -1009,11 +1010,11 @@ exports.WebkitMessagingTransport = WebkitMessagingTransport; class WebkitMessagingConfig { /** - * @param {object} params - * @param {boolean} params.hasModernWebkitAPI - * @param {string[]} params.webkitMessageHandlerNames - * @param {string} params.secret - */ + * @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 @@ -1021,14 +1022,14 @@ class WebkitMessagingConfig { */ this.hasModernWebkitAPI = params.hasModernWebkitAPI; /** - * A list of WebKit message handler names that a user script can send - */ + * 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 - */ + * A string provided by native platforms to be sent with future outgoing + * messages + */ this.secret = params.secret; } @@ -1044,30 +1045,30 @@ exports.WebkitMessagingConfig = WebkitMessagingConfig; class SecureMessagingParams { /** - * @param {object} params - * @param {string} params.methodName - * @param {string} params.secret - * @param {number[]} params.key - * @param {number[]} params.iv - */ + * @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 - */ + * The secret used to ensure message sender validity + */ this.secret = params.secret; /** - * The CipherKey as number[] - */ + * The CipherKey as number[] + */ this.key = params.key; /** - * The Initial Vector as number[] - */ + * The Initial Vector as number[] + */ this.iv = params.iv; }