diff --git a/404.html b/404.html index 01f30defaa..2bd86868f9 100644 --- a/404.html +++ b/404.html @@ -17,8 +17,8 @@ - - + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/assets/images/GrpcMetatype.drawio-e6e626affae448f5b44a48ab82805ee9.png b/assets/images/GrpcMetatype.drawio-e6e626affae448f5b44a48ab82805ee9.png new file mode 100644 index 0000000000..d62e1b535d Binary files /dev/null and b/assets/images/GrpcMetatype.drawio-e6e626affae448f5b44a48ab82805ee9.png differ diff --git a/assets/js/4f68146b.3a54c1b3.js b/assets/js/4f68146b.3a54c1b3.js deleted file mode 100644 index 60f1e377a7..0000000000 --- a/assets/js/4f68146b.3a54c1b3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1732],{53919:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>c,toc:()=>h});var t=r(86070),s=r(25710),i=r(27676),o=r(65480);const a={},l="Distributed execution flow paradigms",c={permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",source:"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",title:"Distributed execution flow paradigms",description:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.",date:"2024-08-27T00:00:00.000Z",tags:[],readingTime:10.92,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,nextItem:{title:"Python on WebAssembly: How?",permalink:"/blog/2024/08/26/python-on-webassembly"}},d={authorsImageUrls:[]},h=[{value:"1. Event-Driven Architecture with Message Queues",id:"1-event-driven-architecture-with-message-queues",level:3},{value:"Advantages",id:"advantages",level:4},{value:"Challenges",id:"challenges",level:4},{value:"2. The Saga Pattern",id:"2-the-saga-pattern",level:3},{value:"Advantages",id:"advantages-1",level:4},{value:"Drawbacks",id:"drawbacks",level:4},{value:"3. Stateful Orchestrators",id:"3-stateful-orchestrators",level:3},{value:"Advantages",id:"advantages-2",level:4},{value:"Challenges",id:"challenges-1",level:4},{value:"4. Durable Execution",id:"4-durable-execution",level:3},{value:"Advantages",id:"advantages-3",level:4},{value:"Challenges",id:"challenges-2",level:4}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components},{Details:a}=n;return a||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies."}),"\n",(0,t.jsx)(n.p,{children:"Having multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\nLet's explore some of the solutions that have been proposed to achieve workflow completeness."}),"\n",(0,t.jsx)(n.h3,{id:"1-event-driven-architecture-with-message-queues",children:"1. Event-Driven Architecture with Message Queues"}),"\n",(0,t.jsx)(n.p,{children:"This architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.rabbitmq.com/",children:"RabbitMQ"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://aws.amazon.com/sqs/",children:"Amazon SQS"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(16676).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"5em"},children:(0,t.jsx)(n.p,{children:"Fig. Event Driven Architecture with Message Queues - RabbitMQ"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Improved Scalability"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Responsiveness"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Fault Tolerance"}),"\n",(0,t.jsx)(n.li,{children:"Simplified Complex Workflows"}),"\n",(0,t.jsx)(n.li,{children:"Real-Time Data Processing"}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Event Ordering"}),"\n",(0,t.jsx)(n.li,{children:"Data Consistency"}),"\n",(0,t.jsx)(n.li,{children:"Monitoring and Debugging"}),"\n",(0,t.jsx)(n.li,{children:"Event Deduplication"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"You can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning."}),"\n",(0,t.jsxs)(n.h3,{id:"2-the-saga-pattern",children:["2. The ",(0,t.jsx)(n.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})]}),"\n",(0,t.jsx)(n.p,{children:"This design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),": In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(35936).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"10em"},children:(0,t.jsx)(n.p,{children:"Fig. The Saga Pattern for Order delivery system"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages-1",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Ensures data consistency in a distributed system without tight coupling."}),"\n",(0,t.jsx)(n.li,{children:"Provides Roll back if one of the operations in the sequence fails."}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"drawbacks",children:"Drawbacks"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Might be challenging to implement initially."}),"\n",(0,t.jsx)(n.li,{children:"Hard to debug."}),"\n",(0,t.jsx)(n.li,{children:"Compensating transactions don\u2019t always work."}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"3-stateful-orchestrators",children:["3. ",(0,t.jsx)(n.a,{href:"https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073",children:"Stateful Orchestrators"})]}),"\n",(0,t.jsx)(n.p,{children:"Stateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html",children:"Apache Airflow"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://azure.microsoft.com/en-us/products/logic-apps",children:"Azure Logic Apps"})}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"advantages-2",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"High Resiliency"}),": Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Data Persistence"}),": They allow you to keep, review, or reference data from previous events, which is useful for long-running processes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Extended Runtime"}),": Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-1",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Additional Complexity"}),": They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Cost"}),": With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"4-durable-execution",children:"4. Durable Execution"}),"\n",(0,t.jsx)(n.p,{children:"Durable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion."}),"\n",(0,t.jsx)(n.p,{children:"Durable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/durable-exec.svg",alt:"Durable workflow engine - Temporal"}),"\n",(0,t.jsx)("div",{style:{marginLeft:"15em"},children:"Fig. Durable workflow engine"}),"\n",(0,t.jsx)(n.h4,{id:"advantages-3",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Reduced Manual Intervention"}),": Minimizes the need for human intervention by handling retries and failures programmatically."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Improved Observability"}),": Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Scalability"}),": Scales efficiently across distributed systems while maintaining workflow integrity."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-2",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Resource Intensive"}),": Persistent state storage and management can consume significant resources, especially in large-scale systems."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Latency"}),": The need to persist state and handle retries can introduce latency in the execution flow."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"As durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Uber Cadence"})}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Among these, ",(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders."]}),"\n",(0,t.jsxs)(n.p,{children:["At Metatype, we recognize the value of durable execution and are committed to making it accessible. Our ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Below is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype."}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsxs)(n.p,{children:["If you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this ",(0,t.jsx)(n.a,{href:"/docs/tutorials/quick-start",children:"guideline"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"For this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery."}),"\n",(0,t.jsx)(n.p,{children:"Your temporal workflow definition should look similar to the one below."}),"\n",(0,t.jsxs)(o.Ay,{children:[(0,t.jsxs)(i.A,{value:"typescript",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"src/activities.ts"}),":`"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'async function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n}\n\nexport async function processPayment(orderId: string): Promise {\n console.log(`Processing payment for order ${orderId}`);\n // Simulate payment processing logic\n await sleep(2);\n return "Payment processed";\n}\n\nexport async function checkInventory(orderId: string): Promise {\n console.log(`Checking inventory for order ${orderId}`);\n // Simulate inventory check logic\n await sleep(2);\n return "Inventory available";\n}\n\nexport async function deliverOrder(orderId: string): Promise {\n console.log(`Delivering order ${orderId}`);\n // Simulate delivery logic\n await sleep(5);\n return "Order delivered";\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Workflow definition inside ",(0,t.jsx)(n.code,{children:"src/workflows.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",metastring:'import {proxyActivities} from "@temporalio/workflow";',children:'\nexport const { processPayment, checkInventory, deliverOrder } =\n proxyActivities<{\n processPayment(orderId: string): Promise;\n checkInventory(orderId: string): Promise;\n deliverOrder(orderId: string): Promise;\n }>({\n startToCloseTimeout: "10 seconds",\n });\n\nexport async function OrderWorkflow(orderId: string): Promise {\n const paymentResult = await processPayment(orderId);\n const inventoryResult = await checkInventory(orderId);\n const deliveryResult = await deliverOrder(orderId);\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker definintion inside ",(0,t.jsx)(n.code,{children:"src/worker.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { NativeConnection, Worker } from "@temporalio/worker";\nimport * as activities from "./activities";\nimport { TASK_QUEUE_NAME } from "./shared";\n\nasync function run() {\n const connection = await NativeConnection.connect({\n address: "localhost:7233",\n });\n\n const worker = await Worker.create({\n connection,\n namespace: "default",\n taskQueue: TASK_QUEUE_NAME,\n workflowsPath: require.resolve("./workflows"),\n activities,\n });\n\n await worker.run();\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { Policy, t, typegraph } from "@typegraph/sdk/index.ts";\nimport { TemporalRuntime } from "@typegraph/sdk/providers/temporal.ts";\n\ntypegraph(\n {\n name: "order_delivery",\n },\n (g: any) => {\n const pub = Policy.public();\n\n const temporal = new TemporalRuntime({\n name: "order_delivery",\n hostSecret: "HOST",\n namespaceSecret: "NAMESPACE",\n });\n\n const workflow_id = "order-delivery-1";\n\n const order_id = t.string();\n\n g.expose(\n {\n start: temporal.startWorkflow("OrderWorkflow", order_id),\n describe: workflow_id\n ? temporal.describeWorkflow().reduce({ workflow_id })\n : temporal.describeWorkflow(),\n },\n pub,\n );\n },\n);\n'})})]}),(0,t.jsxs)(i.A,{value:"python",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"activities.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from temporalio import activity\nimport time\n\n@activity.defn\nasync def process_payment(order_id: str) -> str:\n print(f"Processing payment for order {order_id}")\n # Simulate payment processing logic\n time.sleep(5)\n return "Payment processed"\n\n@activity.defn\nasync def check_inventory(order_id: str) -> str:\n print(f"Checking inventory for order {order_id}")\n # Simulate inventory check logic\n time.sleep(4)\n return "Inventory available"\n\n@activity.defn\nasync def deliver_order(order_id: str) -> str:\n print(f"Delivering order {order_id}")\n time.sleep(8)\n # Simulate delivery logic\n return "Order delivered"\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker defintion inside ",(0,t.jsx)(n.code,{children:"run_worker.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'import asyncio\n\nfrom temporalio.client import Client\nfrom temporalio.worker import Worker\n\nfrom activities import process_payment, deliver_order, check_inventory\nfrom shared import ORDER_DELIVERY_QUEUE\nfrom workflows import OrderWorkflow\n\n\nasync def main() -> None:\n client: Client = await Client.connect("localhost:7233", namespace="default")\n worker: Worker = Worker(\n client,\n task_queue=ORDER_DELIVERY_QUEUE,\n workflows=[OrderWorkflow],\n activities=[process_payment, check_inventory, deliver_order],\n )\n await worker.run()\n\n\nif __name__ == "__main__":\n asyncio.run(main())\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from typegraph import t, typegraph, Policy, Graph\nfrom typegraph.providers.temporal import TemporalRuntime\n\n\n@typegraph()\ndef example(g: Graph):\n public = Policy.public()\n\n temporal = TemporalRuntime(\n "example", "HOST", namespace_secret="NAMESPACE"\n )\n\n workflow_id = "order-delivery-1"\n\n order_id = t.string()\n\n g.expose(\n public,\n start=temporal.start_workflow("OrderWorkflow", order_id),\n describe=temporal.describe_workflow().reduce({"workflow_id": workflow_id})\n if workflow_id\n else temporal.describe_workflow(),\n )\n'})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add the secrets ",(0,t.jsx)(n.code,{children:"HOST"})," and ",(0,t.jsx)(n.code,{children:"NAMESPACE"})," under your typegraph name inside the ",(0,t.jsx)(n.code,{children:"metatype.yaml"})," file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"metatype.yaml"}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'typegate:\n dev:\n url: "http://localhost:7890"\n username: admin\n password: password\n secrets:\n example:\n POSTGRES: "postgresql://postgres:password@postgres:5432/db"\n HOST: "http://localhost:7233"\n NAMESPACE: "default"\n'})})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the ",(0,t.jsx)(n.code,{children:"example"})," parent, which is the name of your typegraph. If the name doesn't match, you will face secret not found issues when deploying your typegraph."]}),"\n",(0,t.jsxs)(n.p,{children:["Before deploying the above typegraph, you need to start the temporal server and the worker. You need to have ",(0,t.jsx)(n.a,{href:"https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli",children:"temporal"})," installed on your machine."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"Boot up temporal"}),(0,t.jsx)(n.p,{children:"Start the temporal server."}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"temporal server start-dev\n"})}),(0,t.jsx)(n.p,{children:"Start the worker."}),(0,t.jsxs)(o.Ay,{children:[(0,t.jsx)(i.A,{value:"typescript",children:(0,t.jsx)(n.p,{children:(0,t.jsx)(n.code,{children:"typescript npx ts-node src/worker.ts "})})}),(0,t.jsx)(i.A,{value:"python",children:(0,t.jsx)(n.code,{children:"python python run_worker.py "})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["After booting the temporal server, run the command down below to get a locally spinning ",(0,t.jsx)(n.a,{href:"/docs/reference/typegate",children:"typegate"})," instance with your typegraph deployed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"meta dev\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After completing the above steps, you can access the web GraphQL client of the typegate at ",(0,t.jsx)(n.a,{href:"http://localhost:7890/example",children:(0,t.jsx)(n.code,{children:"http://localhost:7890/example"})}),". Run this query inside the client to start your workflow."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'mutation {\n start(\n workflow_id: "order-delivery-3"\n task_queue: "order-delivery-queue"\n args: ["order12"]\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After a successful run, you will get the following result which includes the ",(0,t.jsx)(n.code,{children:"run_id"})," of the workflow which has just been started."]}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/start-workflow-result.png",alt:"Query result"}),"\n",(0,t.jsx)(n.p,{children:"You can also check the temporal web UI to monitor your workflows and you should see a result similar to this one."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/temporal-web-ui.png",alt:"Workflows dashboard"}),"\n",(0,t.jsxs)(n.p,{children:["You can explore the ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," for more info."]}),"\n",(0,t.jsx)(n.p,{children:"This wraps up the blog, thanks for reading until the end :)"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},65480:(e,n,r)=>{r.d(n,{Ay:()=>o,gc:()=>a});r(30758);var t=r(3733),s=r(56315),i=r(86070);function o(e){let{children:n}=e;const[r,o]=(0,t.e)();return(0,i.jsx)(s.mS,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,onChange:o,children:n})}function a(e){let{children:n}=e;const[r]=(0,t.e)();return(0,i.jsx)(s.q9,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,children:n})}},16676:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/eda.drawio-9d730aef7e9f00ffed737626d602be5c.svg"},35936:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/saga.drawio-6f492c8332ead1021dde63fa7daf0efd.svg"}}]); \ No newline at end of file diff --git a/assets/js/4f68146b.edca1cc7.js b/assets/js/4f68146b.edca1cc7.js new file mode 100644 index 0000000000..43a22535d5 --- /dev/null +++ b/assets/js/4f68146b.edca1cc7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1732],{53919:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>c,toc:()=>h});var t=r(86070),s=r(25710),i=r(27676),o=r(65480);const a={},l="Distributed execution flow paradigms",c={permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",source:"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",title:"Distributed execution flow paradigms",description:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.",date:"2024-08-27T00:00:00.000Z",tags:[],readingTime:10.92,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,prevItem:{title:"Introducing gRPC Runtime",permalink:"/blog/2024/09/26/introducing-grpc-runtime"},nextItem:{title:"Python on WebAssembly: How?",permalink:"/blog/2024/08/26/python-on-webassembly"}},d={authorsImageUrls:[]},h=[{value:"1. Event-Driven Architecture with Message Queues",id:"1-event-driven-architecture-with-message-queues",level:3},{value:"Advantages",id:"advantages",level:4},{value:"Challenges",id:"challenges",level:4},{value:"2. The Saga Pattern",id:"2-the-saga-pattern",level:3},{value:"Advantages",id:"advantages-1",level:4},{value:"Drawbacks",id:"drawbacks",level:4},{value:"3. Stateful Orchestrators",id:"3-stateful-orchestrators",level:3},{value:"Advantages",id:"advantages-2",level:4},{value:"Challenges",id:"challenges-1",level:4},{value:"4. Durable Execution",id:"4-durable-execution",level:3},{value:"Advantages",id:"advantages-3",level:4},{value:"Challenges",id:"challenges-2",level:4}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components},{Details:a}=n;return a||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies."}),"\n",(0,t.jsx)(n.p,{children:"Having multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\nLet's explore some of the solutions that have been proposed to achieve workflow completeness."}),"\n",(0,t.jsx)(n.h3,{id:"1-event-driven-architecture-with-message-queues",children:"1. Event-Driven Architecture with Message Queues"}),"\n",(0,t.jsx)(n.p,{children:"This architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.rabbitmq.com/",children:"RabbitMQ"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://aws.amazon.com/sqs/",children:"Amazon SQS"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(16676).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"5em"},children:(0,t.jsx)(n.p,{children:"Fig. Event Driven Architecture with Message Queues - RabbitMQ"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Improved Scalability"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Responsiveness"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Fault Tolerance"}),"\n",(0,t.jsx)(n.li,{children:"Simplified Complex Workflows"}),"\n",(0,t.jsx)(n.li,{children:"Real-Time Data Processing"}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Event Ordering"}),"\n",(0,t.jsx)(n.li,{children:"Data Consistency"}),"\n",(0,t.jsx)(n.li,{children:"Monitoring and Debugging"}),"\n",(0,t.jsx)(n.li,{children:"Event Deduplication"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"You can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning."}),"\n",(0,t.jsxs)(n.h3,{id:"2-the-saga-pattern",children:["2. The ",(0,t.jsx)(n.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})]}),"\n",(0,t.jsx)(n.p,{children:"This design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),": In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(35936).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"10em"},children:(0,t.jsx)(n.p,{children:"Fig. The Saga Pattern for Order delivery system"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages-1",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Ensures data consistency in a distributed system without tight coupling."}),"\n",(0,t.jsx)(n.li,{children:"Provides Roll back if one of the operations in the sequence fails."}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"drawbacks",children:"Drawbacks"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Might be challenging to implement initially."}),"\n",(0,t.jsx)(n.li,{children:"Hard to debug."}),"\n",(0,t.jsx)(n.li,{children:"Compensating transactions don\u2019t always work."}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"3-stateful-orchestrators",children:["3. ",(0,t.jsx)(n.a,{href:"https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073",children:"Stateful Orchestrators"})]}),"\n",(0,t.jsx)(n.p,{children:"Stateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html",children:"Apache Airflow"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://azure.microsoft.com/en-us/products/logic-apps",children:"Azure Logic Apps"})}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"advantages-2",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"High Resiliency"}),": Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Data Persistence"}),": They allow you to keep, review, or reference data from previous events, which is useful for long-running processes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Extended Runtime"}),": Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-1",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Additional Complexity"}),": They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Cost"}),": With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"4-durable-execution",children:"4. Durable Execution"}),"\n",(0,t.jsx)(n.p,{children:"Durable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion."}),"\n",(0,t.jsx)(n.p,{children:"Durable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/durable-exec.svg",alt:"Durable workflow engine - Temporal"}),"\n",(0,t.jsx)("div",{style:{marginLeft:"15em"},children:"Fig. Durable workflow engine"}),"\n",(0,t.jsx)(n.h4,{id:"advantages-3",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Reduced Manual Intervention"}),": Minimizes the need for human intervention by handling retries and failures programmatically."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Improved Observability"}),": Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Scalability"}),": Scales efficiently across distributed systems while maintaining workflow integrity."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-2",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Resource Intensive"}),": Persistent state storage and management can consume significant resources, especially in large-scale systems."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Latency"}),": The need to persist state and handle retries can introduce latency in the execution flow."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"As durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Uber Cadence"})}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Among these, ",(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders."]}),"\n",(0,t.jsxs)(n.p,{children:["At Metatype, we recognize the value of durable execution and are committed to making it accessible. Our ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Below is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype."}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsxs)(n.p,{children:["If you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this ",(0,t.jsx)(n.a,{href:"/docs/tutorials/quick-start",children:"guideline"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"For this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery."}),"\n",(0,t.jsx)(n.p,{children:"Your temporal workflow definition should look similar to the one below."}),"\n",(0,t.jsxs)(o.Ay,{children:[(0,t.jsxs)(i.A,{value:"typescript",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"src/activities.ts"}),":`"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'async function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n}\n\nexport async function processPayment(orderId: string): Promise {\n console.log(`Processing payment for order ${orderId}`);\n // Simulate payment processing logic\n await sleep(2);\n return "Payment processed";\n}\n\nexport async function checkInventory(orderId: string): Promise {\n console.log(`Checking inventory for order ${orderId}`);\n // Simulate inventory check logic\n await sleep(2);\n return "Inventory available";\n}\n\nexport async function deliverOrder(orderId: string): Promise {\n console.log(`Delivering order ${orderId}`);\n // Simulate delivery logic\n await sleep(5);\n return "Order delivered";\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Workflow definition inside ",(0,t.jsx)(n.code,{children:"src/workflows.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",metastring:'import {proxyActivities} from "@temporalio/workflow";',children:'\nexport const { processPayment, checkInventory, deliverOrder } =\n proxyActivities<{\n processPayment(orderId: string): Promise;\n checkInventory(orderId: string): Promise;\n deliverOrder(orderId: string): Promise;\n }>({\n startToCloseTimeout: "10 seconds",\n });\n\nexport async function OrderWorkflow(orderId: string): Promise {\n const paymentResult = await processPayment(orderId);\n const inventoryResult = await checkInventory(orderId);\n const deliveryResult = await deliverOrder(orderId);\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker definintion inside ",(0,t.jsx)(n.code,{children:"src/worker.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { NativeConnection, Worker } from "@temporalio/worker";\nimport * as activities from "./activities";\nimport { TASK_QUEUE_NAME } from "./shared";\n\nasync function run() {\n const connection = await NativeConnection.connect({\n address: "localhost:7233",\n });\n\n const worker = await Worker.create({\n connection,\n namespace: "default",\n taskQueue: TASK_QUEUE_NAME,\n workflowsPath: require.resolve("./workflows"),\n activities,\n });\n\n await worker.run();\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { Policy, t, typegraph } from "@typegraph/sdk/index.ts";\nimport { TemporalRuntime } from "@typegraph/sdk/providers/temporal.ts";\n\ntypegraph(\n {\n name: "order_delivery",\n },\n (g: any) => {\n const pub = Policy.public();\n\n const temporal = new TemporalRuntime({\n name: "order_delivery",\n hostSecret: "HOST",\n namespaceSecret: "NAMESPACE",\n });\n\n const workflow_id = "order-delivery-1";\n\n const order_id = t.string();\n\n g.expose(\n {\n start: temporal.startWorkflow("OrderWorkflow", order_id),\n describe: workflow_id\n ? temporal.describeWorkflow().reduce({ workflow_id })\n : temporal.describeWorkflow(),\n },\n pub,\n );\n },\n);\n'})})]}),(0,t.jsxs)(i.A,{value:"python",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"activities.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from temporalio import activity\nimport time\n\n@activity.defn\nasync def process_payment(order_id: str) -> str:\n print(f"Processing payment for order {order_id}")\n # Simulate payment processing logic\n time.sleep(5)\n return "Payment processed"\n\n@activity.defn\nasync def check_inventory(order_id: str) -> str:\n print(f"Checking inventory for order {order_id}")\n # Simulate inventory check logic\n time.sleep(4)\n return "Inventory available"\n\n@activity.defn\nasync def deliver_order(order_id: str) -> str:\n print(f"Delivering order {order_id}")\n time.sleep(8)\n # Simulate delivery logic\n return "Order delivered"\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker defintion inside ",(0,t.jsx)(n.code,{children:"run_worker.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'import asyncio\n\nfrom temporalio.client import Client\nfrom temporalio.worker import Worker\n\nfrom activities import process_payment, deliver_order, check_inventory\nfrom shared import ORDER_DELIVERY_QUEUE\nfrom workflows import OrderWorkflow\n\n\nasync def main() -> None:\n client: Client = await Client.connect("localhost:7233", namespace="default")\n worker: Worker = Worker(\n client,\n task_queue=ORDER_DELIVERY_QUEUE,\n workflows=[OrderWorkflow],\n activities=[process_payment, check_inventory, deliver_order],\n )\n await worker.run()\n\n\nif __name__ == "__main__":\n asyncio.run(main())\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from typegraph import t, typegraph, Policy, Graph\nfrom typegraph.providers.temporal import TemporalRuntime\n\n\n@typegraph()\ndef example(g: Graph):\n public = Policy.public()\n\n temporal = TemporalRuntime(\n "example", "HOST", namespace_secret="NAMESPACE"\n )\n\n workflow_id = "order-delivery-1"\n\n order_id = t.string()\n\n g.expose(\n public,\n start=temporal.start_workflow("OrderWorkflow", order_id),\n describe=temporal.describe_workflow().reduce({"workflow_id": workflow_id})\n if workflow_id\n else temporal.describe_workflow(),\n )\n'})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add the secrets ",(0,t.jsx)(n.code,{children:"HOST"})," and ",(0,t.jsx)(n.code,{children:"NAMESPACE"})," under your typegraph name inside the ",(0,t.jsx)(n.code,{children:"metatype.yaml"})," file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"metatype.yaml"}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'typegate:\n dev:\n url: "http://localhost:7890"\n username: admin\n password: password\n secrets:\n example:\n POSTGRES: "postgresql://postgres:password@postgres:5432/db"\n HOST: "http://localhost:7233"\n NAMESPACE: "default"\n'})})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the ",(0,t.jsx)(n.code,{children:"example"})," parent, which is the name of your typegraph. If the name doesn't match, you will face secret not found issues when deploying your typegraph."]}),"\n",(0,t.jsxs)(n.p,{children:["Before deploying the above typegraph, you need to start the temporal server and the worker. You need to have ",(0,t.jsx)(n.a,{href:"https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli",children:"temporal"})," installed on your machine."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"Boot up temporal"}),(0,t.jsx)(n.p,{children:"Start the temporal server."}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"temporal server start-dev\n"})}),(0,t.jsx)(n.p,{children:"Start the worker."}),(0,t.jsxs)(o.Ay,{children:[(0,t.jsx)(i.A,{value:"typescript",children:(0,t.jsx)(n.p,{children:(0,t.jsx)(n.code,{children:"typescript npx ts-node src/worker.ts "})})}),(0,t.jsx)(i.A,{value:"python",children:(0,t.jsx)(n.code,{children:"python python run_worker.py "})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["After booting the temporal server, run the command down below to get a locally spinning ",(0,t.jsx)(n.a,{href:"/docs/reference/typegate",children:"typegate"})," instance with your typegraph deployed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"meta dev\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After completing the above steps, you can access the web GraphQL client of the typegate at ",(0,t.jsx)(n.a,{href:"http://localhost:7890/example",children:(0,t.jsx)(n.code,{children:"http://localhost:7890/example"})}),". Run this query inside the client to start your workflow."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'mutation {\n start(\n workflow_id: "order-delivery-3"\n task_queue: "order-delivery-queue"\n args: ["order12"]\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After a successful run, you will get the following result which includes the ",(0,t.jsx)(n.code,{children:"run_id"})," of the workflow which has just been started."]}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/start-workflow-result.png",alt:"Query result"}),"\n",(0,t.jsx)(n.p,{children:"You can also check the temporal web UI to monitor your workflows and you should see a result similar to this one."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/temporal-web-ui.png",alt:"Workflows dashboard"}),"\n",(0,t.jsxs)(n.p,{children:["You can explore the ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," for more info."]}),"\n",(0,t.jsx)(n.p,{children:"This wraps up the blog, thanks for reading until the end :)"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},65480:(e,n,r)=>{r.d(n,{Ay:()=>o,gc:()=>a});r(30758);var t=r(3733),s=r(56315),i=r(86070);function o(e){let{children:n}=e;const[r,o]=(0,t.e)();return(0,i.jsx)(s.mS,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,onChange:o,children:n})}function a(e){let{children:n}=e;const[r]=(0,t.e)();return(0,i.jsx)(s.q9,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,children:n})}},16676:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/eda.drawio-9d730aef7e9f00ffed737626d602be5c.svg"},35936:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/saga.drawio-6f492c8332ead1021dde63fa7daf0efd.svg"}}]); \ No newline at end of file diff --git a/assets/js/6b5a7be1.510e9cd3.js b/assets/js/6b5a7be1.510e9cd3.js new file mode 100644 index 0000000000..9530f8ccde --- /dev/null +++ b/assets/js/6b5a7be1.510e9cd3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[2920],{65977:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=n(86070),r=n(25710);const s={},o="Introducing gRPC Runtime",a={permalink:"/blog/2024/09/26/introducing-grpc-runtime",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-09-26-introducing-grpc-runtime/index.mdx",source:"@site/blog/2024-09-26-introducing-grpc-runtime/index.mdx",title:"Introducing gRPC Runtime",description:"We're excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform's ability to create versatile and powerful backends through typegraphs.",date:"2024-09-26T00:00:00.000Z",tags:[],readingTime:4.4,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,nextItem:{title:"Distributed execution flow paradigms",permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms"}},l={authorsImageUrls:[]},c=[{value:"What is gRPC?",id:"what-is-grpc",level:2},{value:"Why gRPC Matters for Metatype",id:"why-grpc-matters-for-metatype",level:2},{value:"Diagram: gRPC and Metatype Integration",id:"diagram-grpc-and-metatype-integration",level:2},{value:"Introducing gRPC Runtime in Metatype",id:"introducing-grpc-runtime-in-metatype",level:2},{value:"Key Technical Details",id:"key-technical-details",level:2},{value:"Architecture",id:"architecture",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Benefits for Developers",id:"benefits-for-developers",level:2},{value:"Getting Started",id:"getting-started",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"We're excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform's ability to create versatile and powerful backends through typegraphs."}),"\n",(0,i.jsx)(t.h2,{id:"what-is-grpc",children:"What is gRPC?"}),"\n",(0,i.jsxs)(t.p,{children:["gRPC, or ",(0,i.jsx)(t.strong,{children:"g"}),"oogle ",(0,i.jsx)(t.strong,{children:"R"}),"emote ",(0,i.jsx)(t.strong,{children:"P"}),"rocedure ",(0,i.jsx)(t.strong,{children:"C"}),"all, is a high-performance, open-source communication framework initially developed by Google. It enables ",(0,i.jsx)(t.strong,{children:"efficient and fast communication between microservices"})," in a distributed system, making it ideal for modern backend architectures."]}),"\n",(0,i.jsxs)(t.p,{children:["Unlike traditional HTTP APIs that use JSON, gRPC relies on ",(0,i.jsx)(t.strong,{children:"Protocol Buffers"})," (protobufs) for serializing data, which are more compact and faster to process. This approach allows gRPC to support high-throughput, low-latency communication, which is crucial for applications where speed and efficiency matter, such as in real-time data processing or large-scale distributed systems."]}),"\n",(0,i.jsx)(t.p,{children:"Key benefits of gRPC include:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Cross-language support"}),": gRPC supports multiple programming languages, allowing services written in different languages to communicate seamlessly."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Strong type safety"}),": Protocol Buffers ensure type-safe communication, catching errors early and improving reliability."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Bidirectional streaming"}),": gRPC allows for client and server streaming, enabling continuous data transfer in both directions, ideal for applications like real-time analytics."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"In short, gRPC is well-suited for high-performance, scalable backend systems where speed and type safety are essential."}),"\n",(0,i.jsx)(t.h2,{id:"why-grpc-matters-for-metatype",children:"Why gRPC Matters for Metatype"}),"\n",(0,i.jsxs)(t.p,{children:["Metatype is a platform that enables developers to create ",(0,i.jsx)(t.strong,{children:"typegraphs"}),"\u2014strongly-typed, composable backend structures that can support multiple protocols and runtime environments. With the introduction of the gRPC Runtime, Metatype allows developers to incorporate gRPC services into these typegraphs, further enhancing the platform\u2019s versatility."]}),"\n",(0,i.jsx)(t.p,{children:"By integrating gRPC, Metatype empowers developers to:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Expose gRPC services via GraphQL or HTTP endpoints"}),", making them accessible to clients in a way that best suits their needs."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Compose gRPC services with other backend components"}),", such as databases or other APIs, to create powerful and cohesive backend systems."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"diagram-grpc-and-metatype-integration",children:"Diagram: gRPC and Metatype Integration"}),"\n",(0,i.jsx)("center",{children:(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"gRPC and Metatype Integration Diagram",src:n(15602).A+"",width:"161",height:"681"})})}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.em,{children:"Metatype\u2019s gRPC Runtime allows developers to integrate gRPC services into their typegraphs, enabling seamless interaction with gRPC services in the backend."})}),"\n",(0,i.jsx)(t.h2,{id:"introducing-grpc-runtime-in-metatype",children:"Introducing gRPC Runtime in Metatype"}),"\n",(0,i.jsx)(t.p,{children:"The new gRPC Runtime is the latest addition to Metatype's suite of runtimes, joining existing options like the HTTP runtime. This expansion allows you to incorporate gRPC services into your typegraphs, further enhancing the versatility of your Metatype-powered backends."}),"\n",(0,i.jsx)(t.h2,{id:"key-technical-details",children:"Key Technical Details"}),"\n",(0,i.jsx)(t.h3,{id:"architecture",children:"Architecture"}),"\n",(0,i.jsx)(t.p,{children:"The gRPC Runtime integrates seamlessly with Metatype's existing architecture. It acts as a bridge between your typegraph and external gRPC services, allowing you to incorporate gRPC calls alongside other runtime operations in your backend logic."}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"GrpcRuntime Class"}),": The main interface for defining gRPC interactions within your typegraph."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"proto_file"}),": Path to the .proto file that defines the gRPC service."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"endpoint"}),": The gRPC server address in the format ",(0,i.jsx)(t.code,{children:"tcp://:"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"call method"}),": Creates a typegraph function for gRPC method calls."]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsx)(t.p,{children:"Here's how the gRPC Runtime fits into a Metatype typegraph:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from typegraph import Graph, Policy, typegraph\nfrom typegraph.graph.params import Cors\nfrom typegraph.runtimes.grpc import GrpcRuntime\n\n@typegraph(\n cors=Cors(allow_origin=["https://metatype.dev", "http://localhost:3000"]),\n)\ndef create_grpc_typegraph(g: Graph):\n # The GrpcRuntime acts as a bridge between your typegraph and external gRPC services\n grpc_runtime = GrpcRuntime(\n # proto_file: Path to the .proto file that defines the gRPC service\n proto_file="proto/helloworld.proto",\n # endpoint: The gRPC server address in the format tcp://:\n endpoint="tcp://localhost:4770"\n )\n \n # Expose the gRPC service within your typegraph\n # This allows you to incorporate gRPC calls alongside other runtime operations\n g.expose(\n Policy.public(),\n # call method: Creates a typegraph function for gRPC method calls\n # It uses the full path to the gRPC method: /package_name.service_name/method_name\n greet=grpc_runtime.call("/helloworld.Greeter/SayHello"),\n )\n\n# The typegraph can now be exposed via GraphQL or HTTP, \n# allowing clients to interact with the gRPC service through Metatype\'s unified interface\n'})}),"\n",(0,i.jsx)(t.p,{children:"This implementation demonstrates how the gRPC Runtime integrates with your typegraph, allowing you to:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Define gRPC service connections using the GrpcRuntime class"}),"\n",(0,i.jsx)(t.li,{children:"Expose gRPC methods as part of your typegraph"}),"\n",(0,i.jsx)(t.li,{children:"Combine gRPC functionality with other Metatype features and runtimes"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"By structuring your gRPC interactions this way, you can seamlessly incorporate gRPC services into your larger Metatype-powered backend, alongside other data sources and business logic."}),"\n",(0,i.jsx)(t.h2,{id:"benefits-for-developers",children:"Benefits for Developers"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Unified Backend Structure"}),": Incorporate gRPC services alongside other protocols and data sources in a single, coherent typegraph."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Type Safety"}),": Leverage Metatype's strong typing system in conjunction with gRPC's protocol buffers for end-to-end type safety."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Flexible Exposure"}),": Easily expose your gRPC services via GraphQL or HTTP endpoints, allowing clients to interact with them using their preferred protocol."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Composability"}),": Combine gRPC calls with other runtime operations, database queries, or business logic within your typegraph."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,i.jsx)(t.p,{children:"To start using the gRPC Runtime in your Metatype project:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Ensure you have the latest version of Metatype installed."}),"\n",(0,i.jsx)(t.li,{children:"Prepare your .proto files for the gRPC services you want to integrate."}),"\n",(0,i.jsx)(t.li,{children:"Set up your typegraph as shown in the example above, incorporating the GrpcRuntime."}),"\n",(0,i.jsx)(t.li,{children:"Configure your Metatype backend to expose the typegraph via GraphQL or HTTP as needed."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,i.jsx)(t.p,{children:"The addition of the gRPC Runtime to Metatype further solidifies its position as a comprehensive platform for building robust, type-safe backends. By allowing seamless integration of gRPC services alongside other protocols and data sources, Metatype empowers developers to create versatile and powerful backend systems with ease."}),"\n",(0,i.jsxs)(t.p,{children:["For more detailed documentation, code examples, and best practices, check out our ",(0,i.jsx)(t.a,{href:"https://metatype.dev/docs",children:"official Metatype docs"}),"#."]})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},15602:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/GrpcMetatype.drawio-e6e626affae448f5b44a48ab82805ee9.png"}}]); \ No newline at end of file diff --git a/assets/js/6e544dd5.67ab3519.js b/assets/js/6e544dd5.67ab3519.js deleted file mode 100644 index c8ce4a4c5c..0000000000 --- a/assets/js/6e544dd5.67ab3519.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3126],{2845:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>c,toc:()=>h});var t=r(86070),s=r(25710),i=r(27676),o=r(65480);const a={},l="Distributed execution flow paradigms",c={permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",source:"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",title:"Distributed execution flow paradigms",description:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.",date:"2024-08-27T00:00:00.000Z",tags:[],readingTime:10.92,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,nextItem:{title:"Python on WebAssembly: How?",permalink:"/blog/2024/08/26/python-on-webassembly"}},d={authorsImageUrls:[]},h=[{value:"1. Event-Driven Architecture with Message Queues",id:"1-event-driven-architecture-with-message-queues",level:3},{value:"Advantages",id:"advantages",level:4},{value:"Challenges",id:"challenges",level:4},{value:"2. The Saga Pattern",id:"2-the-saga-pattern",level:3},{value:"Advantages",id:"advantages-1",level:4},{value:"Drawbacks",id:"drawbacks",level:4},{value:"3. Stateful Orchestrators",id:"3-stateful-orchestrators",level:3},{value:"Advantages",id:"advantages-2",level:4},{value:"Challenges",id:"challenges-1",level:4},{value:"4. Durable Execution",id:"4-durable-execution",level:3},{value:"Advantages",id:"advantages-3",level:4},{value:"Challenges",id:"challenges-2",level:4}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components},{Details:a}=n;return a||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies."}),"\n",(0,t.jsx)(n.p,{children:"Having multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\nLet's explore some of the solutions that have been proposed to achieve workflow completeness."}),"\n",(0,t.jsx)(n.h3,{id:"1-event-driven-architecture-with-message-queues",children:"1. Event-Driven Architecture with Message Queues"}),"\n",(0,t.jsx)(n.p,{children:"This architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.rabbitmq.com/",children:"RabbitMQ"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://aws.amazon.com/sqs/",children:"Amazon SQS"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(16676).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"5em"},children:(0,t.jsx)(n.p,{children:"Fig. Event Driven Architecture with Message Queues - RabbitMQ"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Improved Scalability"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Responsiveness"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Fault Tolerance"}),"\n",(0,t.jsx)(n.li,{children:"Simplified Complex Workflows"}),"\n",(0,t.jsx)(n.li,{children:"Real-Time Data Processing"}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Event Ordering"}),"\n",(0,t.jsx)(n.li,{children:"Data Consistency"}),"\n",(0,t.jsx)(n.li,{children:"Monitoring and Debugging"}),"\n",(0,t.jsx)(n.li,{children:"Event Deduplication"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"You can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning."}),"\n",(0,t.jsxs)(n.h3,{id:"2-the-saga-pattern",children:["2. The ",(0,t.jsx)(n.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})]}),"\n",(0,t.jsx)(n.p,{children:"This design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),": In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(35936).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"10em"},children:(0,t.jsx)(n.p,{children:"Fig. The Saga Pattern for Order delivery system"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages-1",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Ensures data consistency in a distributed system without tight coupling."}),"\n",(0,t.jsx)(n.li,{children:"Provides Roll back if one of the operations in the sequence fails."}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"drawbacks",children:"Drawbacks"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Might be challenging to implement initially."}),"\n",(0,t.jsx)(n.li,{children:"Hard to debug."}),"\n",(0,t.jsx)(n.li,{children:"Compensating transactions don\u2019t always work."}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"3-stateful-orchestrators",children:["3. ",(0,t.jsx)(n.a,{href:"https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073",children:"Stateful Orchestrators"})]}),"\n",(0,t.jsx)(n.p,{children:"Stateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html",children:"Apache Airflow"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://azure.microsoft.com/en-us/products/logic-apps",children:"Azure Logic Apps"})}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"advantages-2",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"High Resiliency"}),": Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Data Persistence"}),": They allow you to keep, review, or reference data from previous events, which is useful for long-running processes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Extended Runtime"}),": Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-1",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Additional Complexity"}),": They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Cost"}),": With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"4-durable-execution",children:"4. Durable Execution"}),"\n",(0,t.jsx)(n.p,{children:"Durable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion."}),"\n",(0,t.jsx)(n.p,{children:"Durable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/durable-exec.svg",alt:"Durable workflow engine - Temporal"}),"\n",(0,t.jsx)("div",{style:{marginLeft:"15em"},children:"Fig. Durable workflow engine"}),"\n",(0,t.jsx)(n.h4,{id:"advantages-3",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Reduced Manual Intervention"}),": Minimizes the need for human intervention by handling retries and failures programmatically."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Improved Observability"}),": Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Scalability"}),": Scales efficiently across distributed systems while maintaining workflow integrity."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-2",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Resource Intensive"}),": Persistent state storage and management can consume significant resources, especially in large-scale systems."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Latency"}),": The need to persist state and handle retries can introduce latency in the execution flow."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"As durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Uber Cadence"})}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Among these, ",(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders."]}),"\n",(0,t.jsxs)(n.p,{children:["At Metatype, we recognize the value of durable execution and are committed to making it accessible. Our ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Below is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype."}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsxs)(n.p,{children:["If you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this ",(0,t.jsx)(n.a,{href:"/docs/tutorials/quick-start",children:"guideline"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"For this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery."}),"\n",(0,t.jsx)(n.p,{children:"Your temporal workflow definition should look similar to the one below."}),"\n",(0,t.jsxs)(o.Ay,{children:[(0,t.jsxs)(i.A,{value:"typescript",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"src/activities.ts"}),":`"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'async function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n}\n\nexport async function processPayment(orderId: string): Promise {\n console.log(`Processing payment for order ${orderId}`);\n // Simulate payment processing logic\n await sleep(2);\n return "Payment processed";\n}\n\nexport async function checkInventory(orderId: string): Promise {\n console.log(`Checking inventory for order ${orderId}`);\n // Simulate inventory check logic\n await sleep(2);\n return "Inventory available";\n}\n\nexport async function deliverOrder(orderId: string): Promise {\n console.log(`Delivering order ${orderId}`);\n // Simulate delivery logic\n await sleep(5);\n return "Order delivered";\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Workflow definition inside ",(0,t.jsx)(n.code,{children:"src/workflows.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",metastring:'import {proxyActivities} from "@temporalio/workflow";',children:'\nexport const { processPayment, checkInventory, deliverOrder } =\n proxyActivities<{\n processPayment(orderId: string): Promise;\n checkInventory(orderId: string): Promise;\n deliverOrder(orderId: string): Promise;\n }>({\n startToCloseTimeout: "10 seconds",\n });\n\nexport async function OrderWorkflow(orderId: string): Promise {\n const paymentResult = await processPayment(orderId);\n const inventoryResult = await checkInventory(orderId);\n const deliveryResult = await deliverOrder(orderId);\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker definintion inside ",(0,t.jsx)(n.code,{children:"src/worker.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { NativeConnection, Worker } from "@temporalio/worker";\nimport * as activities from "./activities";\nimport { TASK_QUEUE_NAME } from "./shared";\n\nasync function run() {\n const connection = await NativeConnection.connect({\n address: "localhost:7233",\n });\n\n const worker = await Worker.create({\n connection,\n namespace: "default",\n taskQueue: TASK_QUEUE_NAME,\n workflowsPath: require.resolve("./workflows"),\n activities,\n });\n\n await worker.run();\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { Policy, t, typegraph } from "@typegraph/sdk/index.ts";\nimport { TemporalRuntime } from "@typegraph/sdk/providers/temporal.ts";\n\ntypegraph(\n {\n name: "order_delivery",\n },\n (g: any) => {\n const pub = Policy.public();\n\n const temporal = new TemporalRuntime({\n name: "order_delivery",\n hostSecret: "HOST",\n namespaceSecret: "NAMESPACE",\n });\n\n const workflow_id = "order-delivery-1";\n\n const order_id = t.string();\n\n g.expose(\n {\n start: temporal.startWorkflow("OrderWorkflow", order_id),\n describe: workflow_id\n ? temporal.describeWorkflow().reduce({ workflow_id })\n : temporal.describeWorkflow(),\n },\n pub,\n );\n },\n);\n'})})]}),(0,t.jsxs)(i.A,{value:"python",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"activities.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from temporalio import activity\nimport time\n\n@activity.defn\nasync def process_payment(order_id: str) -> str:\n print(f"Processing payment for order {order_id}")\n # Simulate payment processing logic\n time.sleep(5)\n return "Payment processed"\n\n@activity.defn\nasync def check_inventory(order_id: str) -> str:\n print(f"Checking inventory for order {order_id}")\n # Simulate inventory check logic\n time.sleep(4)\n return "Inventory available"\n\n@activity.defn\nasync def deliver_order(order_id: str) -> str:\n print(f"Delivering order {order_id}")\n time.sleep(8)\n # Simulate delivery logic\n return "Order delivered"\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker defintion inside ",(0,t.jsx)(n.code,{children:"run_worker.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'import asyncio\n\nfrom temporalio.client import Client\nfrom temporalio.worker import Worker\n\nfrom activities import process_payment, deliver_order, check_inventory\nfrom shared import ORDER_DELIVERY_QUEUE\nfrom workflows import OrderWorkflow\n\n\nasync def main() -> None:\n client: Client = await Client.connect("localhost:7233", namespace="default")\n worker: Worker = Worker(\n client,\n task_queue=ORDER_DELIVERY_QUEUE,\n workflows=[OrderWorkflow],\n activities=[process_payment, check_inventory, deliver_order],\n )\n await worker.run()\n\n\nif __name__ == "__main__":\n asyncio.run(main())\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from typegraph import t, typegraph, Policy, Graph\nfrom typegraph.providers.temporal import TemporalRuntime\n\n\n@typegraph()\ndef example(g: Graph):\n public = Policy.public()\n\n temporal = TemporalRuntime(\n "example", "HOST", namespace_secret="NAMESPACE"\n )\n\n workflow_id = "order-delivery-1"\n\n order_id = t.string()\n\n g.expose(\n public,\n start=temporal.start_workflow("OrderWorkflow", order_id),\n describe=temporal.describe_workflow().reduce({"workflow_id": workflow_id})\n if workflow_id\n else temporal.describe_workflow(),\n )\n'})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add the secrets ",(0,t.jsx)(n.code,{children:"HOST"})," and ",(0,t.jsx)(n.code,{children:"NAMESPACE"})," under your typegraph name inside the ",(0,t.jsx)(n.code,{children:"metatype.yaml"})," file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"metatype.yaml"}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'typegate:\n dev:\n url: "http://localhost:7890"\n username: admin\n password: password\n secrets:\n example:\n POSTGRES: "postgresql://postgres:password@postgres:5432/db"\n HOST: "http://localhost:7233"\n NAMESPACE: "default"\n'})})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the ",(0,t.jsx)(n.code,{children:"example"})," parent, which is the name of your typegraph. If the name doesn't match, you will face secret not found issues when deploying your typegraph."]}),"\n",(0,t.jsxs)(n.p,{children:["Before deploying the above typegraph, you need to start the temporal server and the worker. You need to have ",(0,t.jsx)(n.a,{href:"https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli",children:"temporal"})," installed on your machine."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"Boot up temporal"}),(0,t.jsx)(n.p,{children:"Start the temporal server."}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"temporal server start-dev\n"})}),(0,t.jsx)(n.p,{children:"Start the worker."}),(0,t.jsxs)(o.Ay,{children:[(0,t.jsx)(i.A,{value:"typescript",children:(0,t.jsx)(n.p,{children:(0,t.jsx)(n.code,{children:"typescript npx ts-node src/worker.ts "})})}),(0,t.jsx)(i.A,{value:"python",children:(0,t.jsx)(n.code,{children:"python python run_worker.py "})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["After booting the temporal server, run the command down below to get a locally spinning ",(0,t.jsx)(n.a,{href:"/docs/reference/typegate",children:"typegate"})," instance with your typegraph deployed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"meta dev\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After completing the above steps, you can access the web GraphQL client of the typegate at ",(0,t.jsx)(n.a,{href:"http://localhost:7890/example",children:(0,t.jsx)(n.code,{children:"http://localhost:7890/example"})}),". Run this query inside the client to start your workflow."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'mutation {\n start(\n workflow_id: "order-delivery-3"\n task_queue: "order-delivery-queue"\n args: ["order12"]\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After a successful run, you will get the following result which includes the ",(0,t.jsx)(n.code,{children:"run_id"})," of the workflow which has just been started."]}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/start-workflow-result.png",alt:"Query result"}),"\n",(0,t.jsx)(n.p,{children:"You can also check the temporal web UI to monitor your workflows and you should see a result similar to this one."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/temporal-web-ui.png",alt:"Workflows dashboard"}),"\n",(0,t.jsxs)(n.p,{children:["You can explore the ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," for more info."]}),"\n",(0,t.jsx)(n.p,{children:"This wraps up the blog, thanks for reading until the end :)"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},65480:(e,n,r)=>{r.d(n,{Ay:()=>o,gc:()=>a});r(30758);var t=r(3733),s=r(56315),i=r(86070);function o(e){let{children:n}=e;const[r,o]=(0,t.e)();return(0,i.jsx)(s.mS,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,onChange:o,children:n})}function a(e){let{children:n}=e;const[r]=(0,t.e)();return(0,i.jsx)(s.q9,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,children:n})}},16676:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/eda.drawio-9d730aef7e9f00ffed737626d602be5c.svg"},35936:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/saga.drawio-6f492c8332ead1021dde63fa7daf0efd.svg"}}]); \ No newline at end of file diff --git a/assets/js/6e544dd5.aa17255f.js b/assets/js/6e544dd5.aa17255f.js new file mode 100644 index 0000000000..b31cf30d30 --- /dev/null +++ b/assets/js/6e544dd5.aa17255f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3126],{2845:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>l,default:()=>u,frontMatter:()=>a,metadata:()=>c,toc:()=>h});var t=r(86070),s=r(25710),i=r(27676),o=r(65480);const a={},l="Distributed execution flow paradigms",c={permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",source:"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",title:"Distributed execution flow paradigms",description:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.",date:"2024-08-27T00:00:00.000Z",tags:[],readingTime:10.92,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,prevItem:{title:"Introducing gRPC Runtime",permalink:"/blog/2024/09/26/introducing-grpc-runtime"},nextItem:{title:"Python on WebAssembly: How?",permalink:"/blog/2024/08/26/python-on-webassembly"}},d={authorsImageUrls:[]},h=[{value:"1. Event-Driven Architecture with Message Queues",id:"1-event-driven-architecture-with-message-queues",level:3},{value:"Advantages",id:"advantages",level:4},{value:"Challenges",id:"challenges",level:4},{value:"2. The Saga Pattern",id:"2-the-saga-pattern",level:3},{value:"Advantages",id:"advantages-1",level:4},{value:"Drawbacks",id:"drawbacks",level:4},{value:"3. Stateful Orchestrators",id:"3-stateful-orchestrators",level:3},{value:"Advantages",id:"advantages-2",level:4},{value:"Challenges",id:"challenges-1",level:4},{value:"4. Durable Execution",id:"4-durable-execution",level:3},{value:"Advantages",id:"advantages-3",level:4},{value:"Challenges",id:"challenges-2",level:4}];function p(e){const n={a:"a",admonition:"admonition",code:"code",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,s.R)(),...e.components},{Details:a}=n;return a||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.p,{children:"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies."}),"\n",(0,t.jsx)(n.p,{children:"Having multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\nLet's explore some of the solutions that have been proposed to achieve workflow completeness."}),"\n",(0,t.jsx)(n.h3,{id:"1-event-driven-architecture-with-message-queues",children:"1. Event-Driven Architecture with Message Queues"}),"\n",(0,t.jsx)(n.p,{children:"This architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://www.rabbitmq.com/",children:"RabbitMQ"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://aws.amazon.com/sqs/",children:"Amazon SQS"})}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(16676).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"5em"},children:(0,t.jsx)(n.p,{children:"Fig. Event Driven Architecture with Message Queues - RabbitMQ"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Improved Scalability"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Responsiveness"}),"\n",(0,t.jsx)(n.li,{children:"Enhanced Fault Tolerance"}),"\n",(0,t.jsx)(n.li,{children:"Simplified Complex Workflows"}),"\n",(0,t.jsx)(n.li,{children:"Real-Time Data Processing"}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Event Ordering"}),"\n",(0,t.jsx)(n.li,{children:"Data Consistency"}),"\n",(0,t.jsx)(n.li,{children:"Monitoring and Debugging"}),"\n",(0,t.jsx)(n.li,{children:"Event Deduplication"}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"You can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning."}),"\n",(0,t.jsxs)(n.h3,{id:"2-the-saga-pattern",children:["2. The ",(0,t.jsx)(n.a,{href:"https://microservices.io/patterns/data/saga.html",children:"Saga Pattern"})]}),"\n",(0,t.jsx)(n.p,{children:"This design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions."}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.strong,{children:"Note"}),": In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{src:r(35936).A+""})}),"\n",(0,t.jsx)("div",{style:{marginLeft:"10em"},children:(0,t.jsx)(n.p,{children:"Fig. The Saga Pattern for Order delivery system"})}),"\n",(0,t.jsx)(n.h4,{id:"advantages-1",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Ensures data consistency in a distributed system without tight coupling."}),"\n",(0,t.jsx)(n.li,{children:"Provides Roll back if one of the operations in the sequence fails."}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"drawbacks",children:"Drawbacks"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"Might be challenging to implement initially."}),"\n",(0,t.jsx)(n.li,{children:"Hard to debug."}),"\n",(0,t.jsx)(n.li,{children:"Compensating transactions don\u2019t always work."}),"\n"]}),"\n",(0,t.jsxs)(n.h3,{id:"3-stateful-orchestrators",children:["3. ",(0,t.jsx)(n.a,{href:"https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073",children:"Stateful Orchestrators"})]}),"\n",(0,t.jsx)(n.p,{children:"Stateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html",children:"Apache Airflow"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://azure.microsoft.com/en-us/products/logic-apps",children:"Azure Logic Apps"})}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"advantages-2",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"High Resiliency"}),": Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Data Persistence"}),": They allow you to keep, review, or reference data from previous events, which is useful for long-running processes."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Extended Runtime"}),": Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-1",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Additional Complexity"}),": They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Cost"}),": With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed."]}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"4-durable-execution",children:"4. Durable Execution"}),"\n",(0,t.jsx)(n.p,{children:"Durable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion."}),"\n",(0,t.jsx)(n.p,{children:"Durable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/durable-exec.svg",alt:"Durable workflow engine - Temporal"}),"\n",(0,t.jsx)("div",{style:{marginLeft:"15em"},children:"Fig. Durable workflow engine"}),"\n",(0,t.jsx)(n.h4,{id:"advantages-3",children:"Advantages"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Reduced Manual Intervention"}),": Minimizes the need for human intervention by handling retries and failures programmatically."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Improved Observability"}),": Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Scalability"}),": Scales efficiently across distributed systems while maintaining workflow integrity."]}),"\n"]}),"\n",(0,t.jsx)(n.h4,{id:"challenges-2",children:"Challenges"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Resource Intensive"}),": Persistent state storage and management can consume significant resources, especially in large-scale systems."]}),"\n",(0,t.jsxs)(n.li,{children:[(0,t.jsx)(n.strong,{children:"Latency"}),": The need to persist state and handle retries can introduce latency in the execution flow."]}),"\n"]}),"\n",(0,t.jsx)(n.p,{children:"As durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are"}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})}),"\n",(0,t.jsx)(n.li,{children:(0,t.jsx)(n.a,{href:"https://cadenceworkflow.io/",children:"Uber Cadence"})}),"\n"]}),"\n",(0,t.jsxs)(n.p,{children:["Among these, ",(0,t.jsx)(n.a,{href:"https://temporal.io/",children:"Temporal"})," has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders."]}),"\n",(0,t.jsxs)(n.p,{children:["At Metatype, we recognize the value of durable execution and are committed to making it accessible. Our ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"}),"."]}),"\n",(0,t.jsx)(n.p,{children:"Below is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype."}),"\n",(0,t.jsx)(n.admonition,{type:"note",children:(0,t.jsxs)(n.p,{children:["If you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this ",(0,t.jsx)(n.a,{href:"/docs/tutorials/quick-start",children:"guideline"}),"."]})}),"\n",(0,t.jsx)(n.p,{children:"For this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery."}),"\n",(0,t.jsx)(n.p,{children:"Your temporal workflow definition should look similar to the one below."}),"\n",(0,t.jsxs)(o.Ay,{children:[(0,t.jsxs)(i.A,{value:"typescript",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"src/activities.ts"}),":`"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'async function sleep(time: number) {\n return new Promise((resolve) => {\n setTimeout(resolve, time);\n });\n}\n\nexport async function processPayment(orderId: string): Promise {\n console.log(`Processing payment for order ${orderId}`);\n // Simulate payment processing logic\n await sleep(2);\n return "Payment processed";\n}\n\nexport async function checkInventory(orderId: string): Promise {\n console.log(`Checking inventory for order ${orderId}`);\n // Simulate inventory check logic\n await sleep(2);\n return "Inventory available";\n}\n\nexport async function deliverOrder(orderId: string): Promise {\n console.log(`Delivering order ${orderId}`);\n // Simulate delivery logic\n await sleep(5);\n return "Order delivered";\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Workflow definition inside ",(0,t.jsx)(n.code,{children:"src/workflows.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",metastring:'import {proxyActivities} from "@temporalio/workflow";',children:'\nexport const { processPayment, checkInventory, deliverOrder } =\n proxyActivities<{\n processPayment(orderId: string): Promise;\n checkInventory(orderId: string): Promise;\n deliverOrder(orderId: string): Promise;\n }>({\n startToCloseTimeout: "10 seconds",\n });\n\nexport async function OrderWorkflow(orderId: string): Promise {\n const paymentResult = await processPayment(orderId);\n const inventoryResult = await checkInventory(orderId);\n const deliveryResult = await deliverOrder(orderId);\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\n}\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker definintion inside ",(0,t.jsx)(n.code,{children:"src/worker.ts"}),":"]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { NativeConnection, Worker } from "@temporalio/worker";\nimport * as activities from "./activities";\nimport { TASK_QUEUE_NAME } from "./shared";\n\nasync function run() {\n const connection = await NativeConnection.connect({\n address: "localhost:7233",\n });\n\n const worker = await Worker.create({\n connection,\n namespace: "default",\n taskQueue: TASK_QUEUE_NAME,\n workflowsPath: require.resolve("./workflows"),\n activities,\n });\n\n await worker.run();\n}\n\nrun().catch((err) => {\n console.error(err);\n process.exit(1);\n});\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-typescript",children:'import { Policy, t, typegraph } from "@typegraph/sdk/index.ts";\nimport { TemporalRuntime } from "@typegraph/sdk/providers/temporal.ts";\n\ntypegraph(\n {\n name: "order_delivery",\n },\n (g: any) => {\n const pub = Policy.public();\n\n const temporal = new TemporalRuntime({\n name: "order_delivery",\n hostSecret: "HOST",\n namespaceSecret: "NAMESPACE",\n });\n\n const workflow_id = "order-delivery-1";\n\n const order_id = t.string();\n\n g.expose(\n {\n start: temporal.startWorkflow("OrderWorkflow", order_id),\n describe: workflow_id\n ? temporal.describeWorkflow().reduce({ workflow_id })\n : temporal.describeWorkflow(),\n },\n pub,\n );\n },\n);\n'})})]}),(0,t.jsxs)(i.A,{value:"python",children:[(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Activities definition inside ",(0,t.jsx)(n.code,{children:"activities.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from temporalio import activity\nimport time\n\n@activity.defn\nasync def process_payment(order_id: str) -> str:\n print(f"Processing payment for order {order_id}")\n # Simulate payment processing logic\n time.sleep(5)\n return "Payment processed"\n\n@activity.defn\nasync def check_inventory(order_id: str) -> str:\n print(f"Checking inventory for order {order_id}")\n # Simulate inventory check logic\n time.sleep(4)\n return "Inventory available"\n\n@activity.defn\nasync def deliver_order(order_id: str) -> str:\n print(f"Delivering order {order_id}")\n time.sleep(8)\n # Simulate delivery logic\n return "Order delivered"\n'})})]}),(0,t.jsxs)(a,{children:[(0,t.jsxs)("summary",{children:["Worker defintion inside ",(0,t.jsx)(n.code,{children:"run_worker.py"}),"."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'import asyncio\n\nfrom temporalio.client import Client\nfrom temporalio.worker import Worker\n\nfrom activities import process_payment, deliver_order, check_inventory\nfrom shared import ORDER_DELIVERY_QUEUE\nfrom workflows import OrderWorkflow\n\n\nasync def main() -> None:\n client: Client = await Client.connect("localhost:7233", namespace="default")\n worker: Worker = Worker(\n client,\n task_queue=ORDER_DELIVERY_QUEUE,\n workflows=[OrderWorkflow],\n activities=[process_payment, check_inventory, deliver_order],\n )\n await worker.run()\n\n\nif __name__ == "__main__":\n asyncio.run(main())\n'})})]}),(0,t.jsxs)(n.p,{children:["After you have setup the above components, now you need a client to start of any ",(0,t.jsx)(n.code,{children:"OrderWorkflow"}),". Here is where metatype comes in, through the simple APIs ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," exposes, you can communicate with your temporal cluster.\nDown below is the workflow communication bridge for this system expressed within a ",(0,t.jsx)(n.a,{href:"/docs/reference/typegraph",children:"typegraph"})," which includes endpoints to start a new workflow and describe an existing one."]}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-python",children:'from typegraph import t, typegraph, Policy, Graph\nfrom typegraph.providers.temporal import TemporalRuntime\n\n\n@typegraph()\ndef example(g: Graph):\n public = Policy.public()\n\n temporal = TemporalRuntime(\n "example", "HOST", namespace_secret="NAMESPACE"\n )\n\n workflow_id = "order-delivery-1"\n\n order_id = t.string()\n\n g.expose(\n public,\n start=temporal.start_workflow("OrderWorkflow", order_id),\n describe=temporal.describe_workflow().reduce({"workflow_id": workflow_id})\n if workflow_id\n else temporal.describe_workflow(),\n )\n'})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add the secrets ",(0,t.jsx)(n.code,{children:"HOST"})," and ",(0,t.jsx)(n.code,{children:"NAMESPACE"})," under your typegraph name inside the ",(0,t.jsx)(n.code,{children:"metatype.yaml"})," file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"metatype.yaml"}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-yaml",children:'typegate:\n dev:\n url: "http://localhost:7890"\n username: admin\n password: password\n secrets:\n example:\n POSTGRES: "postgresql://postgres:password@postgres:5432/db"\n HOST: "http://localhost:7233"\n NAMESPACE: "default"\n'})})]}),"\n",(0,t.jsxs)(n.p,{children:["You need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the ",(0,t.jsx)(n.code,{children:"example"})," parent, which is the name of your typegraph. If the name doesn't match, you will face secret not found issues when deploying your typegraph."]}),"\n",(0,t.jsxs)(n.p,{children:["Before deploying the above typegraph, you need to start the temporal server and the worker. You need to have ",(0,t.jsx)(n.a,{href:"https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli",children:"temporal"})," installed on your machine."]}),"\n",(0,t.jsxs)(a,{children:[(0,t.jsx)("summary",{children:"Boot up temporal"}),(0,t.jsx)(n.p,{children:"Start the temporal server."}),(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"temporal server start-dev\n"})}),(0,t.jsx)(n.p,{children:"Start the worker."}),(0,t.jsxs)(o.Ay,{children:[(0,t.jsx)(i.A,{value:"typescript",children:(0,t.jsx)(n.p,{children:(0,t.jsx)(n.code,{children:"typescript npx ts-node src/worker.ts "})})}),(0,t.jsx)(i.A,{value:"python",children:(0,t.jsx)(n.code,{children:"python python run_worker.py "})})]})]}),"\n",(0,t.jsxs)(n.p,{children:["After booting the temporal server, run the command down below to get a locally spinning ",(0,t.jsx)(n.a,{href:"/docs/reference/typegate",children:"typegate"})," instance with your typegraph deployed."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-bash",children:"meta dev\n"})}),"\n",(0,t.jsxs)(n.p,{children:["After completing the above steps, you can access the web GraphQL client of the typegate at ",(0,t.jsx)(n.a,{href:"http://localhost:7890/example",children:(0,t.jsx)(n.code,{children:"http://localhost:7890/example"})}),". Run this query inside the client to start your workflow."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-graphql",children:'mutation {\n start(\n workflow_id: "order-delivery-3"\n task_queue: "order-delivery-queue"\n args: ["order12"]\n )\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["After a successful run, you will get the following result which includes the ",(0,t.jsx)(n.code,{children:"run_id"})," of the workflow which has just been started."]}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/start-workflow-result.png",alt:"Query result"}),"\n",(0,t.jsx)(n.p,{children:"You can also check the temporal web UI to monitor your workflows and you should see a result similar to this one."}),"\n",(0,t.jsx)("img",{src:"/images/blog/execution-flow-paradigms/temporal-web-ui.png",alt:"Workflows dashboard"}),"\n",(0,t.jsxs)(n.p,{children:["You can explore the ",(0,t.jsx)(n.a,{href:"/docs/reference/runtimes/temporal",children:"Temporal Runtime"})," for more info."]}),"\n",(0,t.jsx)(n.p,{children:"This wraps up the blog, thanks for reading until the end :)"})]})}function u(e={}){const{wrapper:n}={...(0,s.R)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(p,{...e})}):p(e)}},65480:(e,n,r)=>{r.d(n,{Ay:()=>o,gc:()=>a});r(30758);var t=r(3733),s=r(56315),i=r(86070);function o(e){let{children:n}=e;const[r,o]=(0,t.e)();return(0,i.jsx)(s.mS,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,onChange:o,children:n})}function a(e){let{children:n}=e;const[r]=(0,t.e)();return(0,i.jsx)(s.q9,{choices:{typescript:"Typescript SDK",python:"Python SDK"},choice:r,children:n})}},16676:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/eda.drawio-9d730aef7e9f00ffed737626d602be5c.svg"},35936:(e,n,r)=>{r.d(n,{A:()=>t});const t=r.p+"assets/images/saga.drawio-6f492c8332ead1021dde63fa7daf0efd.svg"}}]); \ No newline at end of file diff --git a/assets/js/95b96bb9.0ec46023.js b/assets/js/95b96bb9.0ec46023.js deleted file mode 100644 index 62872cda25..0000000000 --- a/assets/js/95b96bb9.0ec46023.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6405],{7057:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"Distributed execution flow paradigms","permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms","unlisted":false},{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly","unlisted":false},{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment","unlisted":false},{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility","unlisted":false},{"title":"Programmable glue for developers","permalink":"/blog/2023/06/18/programmable-glue","unlisted":false}]}')}}]); \ No newline at end of file diff --git a/assets/js/95b96bb9.3dbec1e6.js b/assets/js/95b96bb9.3dbec1e6.js new file mode 100644 index 0000000000..25b597c777 --- /dev/null +++ b/assets/js/95b96bb9.3dbec1e6.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6405],{7057:e=>{e.exports=JSON.parse('{"title":"Recent posts","items":[{"title":"Introducing gRPC Runtime","permalink":"/blog/2024/09/26/introducing-grpc-runtime","unlisted":false},{"title":"Distributed execution flow paradigms","permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms","unlisted":false},{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly","unlisted":false},{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment","unlisted":false},{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility","unlisted":false}]}')}}]); \ No newline at end of file diff --git a/assets/js/97787cbd.9066a603.js b/assets/js/97787cbd.85bdc752.js similarity index 75% rename from assets/js/97787cbd.9066a603.js rename to assets/js/97787cbd.85bdc752.js index 03f21dd957..b5c7f255e0 100644 --- a/assets/js/97787cbd.9066a603.js +++ b/assets/js/97787cbd.85bdc752.js @@ -1 +1 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1922],{63961:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog","page":1,"postsPerPage":10,"totalPages":1,"totalCount":6,"blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[1922],{63961:e=>{e.exports=JSON.parse('{"metadata":{"permalink":"/blog","page":1,"postsPerPage":10,"totalPages":1,"totalCount":7,"blogDescription":"Blog","blogTitle":"Blog"}}')}}]); \ No newline at end of file diff --git a/assets/js/b3219b4c.29471a66.js b/assets/js/b3219b4c.29471a66.js deleted file mode 100644 index 0e78cd06d0..0000000000 --- a/assets/js/b3219b4c.29471a66.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3099],{83890:e=>{e.exports=JSON.parse('{"archive":{"blogPosts":[{"id":"/2024/08/27/distributed-execution-flow-paradigms","metadata":{"permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx","source":"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx","title":"Distributed execution flow paradigms","description":"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.","date":"2024-08-27T00:00:00.000Z","tags":[],"readingTime":10.92,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"nextItem":{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly"}},"content":"import TabItem from \\"@theme/TabItem\\";\\nimport SDKTabs from \\"@site/src/components/SDKTabs\\";\\n\\n\\nIn this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.\\n\\nHaving multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\\nLet\'s explore some of the solutions that have been proposed to achieve workflow completeness.\\n\\n### 1. Event-Driven Architecture with Message Queues\\n\\nThis architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:\\n\\n- [RabbitMQ](https://www.rabbitmq.com/)\\n- [Amazon SQS](https://aws.amazon.com/sqs/)\\n\\n![](eda.drawio.svg)\\n\\n
\\n Fig. Event Driven Architecture with Message Queues - RabbitMQ\\n
\\n\\n#### Advantages\\n\\n- Improved Scalability\\n- Enhanced Responsiveness\\n- Enhanced Fault Tolerance\\n- Simplified Complex Workflows\\n- Real-Time Data Processing\\n\\n#### Challenges\\n\\n- Event Ordering\\n- Data Consistency\\n- Monitoring and Debugging\\n- Event Deduplication\\n\\nYou can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning.\\n\\n### 2. The [Saga Pattern](https://microservices.io/patterns/data/saga.html)\\n\\nThis design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions.\\n\\n**Note**: In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention.\\n\\n![](saga.drawio.svg)\\n\\n
\\n Fig. The Saga Pattern for Order delivery system\\n
\\n\\n#### Advantages\\n\\n- Ensures data consistency in a distributed system without tight coupling.\\n- Provides Roll back if one of the operations in the sequence fails.\\n\\n#### Drawbacks\\n\\n- Might be challenging to implement initially.\\n- Hard to debug.\\n- Compensating transactions don\u2019t always work.\\n\\n### 3. [Stateful Orchestrators](https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073)\\n\\nStateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:\\n\\n- [Apache Airflow](https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html)\\n- [Azure Logic Apps](https://azure.microsoft.com/en-us/products/logic-apps)\\n\\n#### Advantages\\n\\n- **High Resiliency**: Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off.\\n- **Data Persistence**: They allow you to keep, review, or reference data from previous events, which is useful for long-running processes.\\n- **Extended Runtime**: Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks.\\n\\n#### Challenges\\n\\n- **Additional Complexity**: They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking.\\n- **Cost**: With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed.\\n\\n### 4. Durable Execution\\n\\nDurable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion.\\n\\nDurable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability.\\n\\n\\n
Fig. Durable workflow engine
\\n\\n#### Advantages\\n\\n- **Reduced Manual Intervention**: Minimizes the need for human intervention by handling retries and failures programmatically.\\n- **Improved Observability**: Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring.\\n- **Scalability**: Scales efficiently across distributed systems while maintaining workflow integrity.\\n\\n#### Challenges\\n\\n- **Resource Intensive**: Persistent state storage and management can consume significant resources, especially in large-scale systems.\\n- **Latency**: The need to persist state and handle retries can introduce latency in the execution flow.\\n\\nAs durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are\\n\\n- [Temporal](https://temporal.io/)\\n- [Uber Cadence](https://cadenceworkflow.io/)\\n\\nAmong these, [Temporal](https://temporal.io/) has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders.\\n\\nAt Metatype, we recognize the value of durable execution and are committed to making it accessible. Our [Temporal Runtime](/docs/reference/runtimes/temporal) integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with [Temporal Runtime](/docs/reference/runtimes/temporal).\\n\\nBelow is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype.\\n\\n:::note\\nIf you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this [guideline](/docs/tutorials/quick-start).\\n:::\\n\\nFor this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery.\\n\\nYour temporal workflow definition should look similar to the one below.\\n\\n\\n\\n \\n\\n
\\n\\nActivities definition inside `src/activities.ts`:`\\n\\n```typescript\\nasync function sleep(time: number) {\\n return new Promise((resolve) => {\\n setTimeout(resolve, time);\\n });\\n}\\n\\nexport async function processPayment(orderId: string): Promise {\\n console.log(`Processing payment for order ${orderId}`);\\n // Simulate payment processing logic\\n await sleep(2);\\n return \\"Payment processed\\";\\n}\\n\\nexport async function checkInventory(orderId: string): Promise {\\n console.log(`Checking inventory for order ${orderId}`);\\n // Simulate inventory check logic\\n await sleep(2);\\n return \\"Inventory available\\";\\n}\\n\\nexport async function deliverOrder(orderId: string): Promise {\\n console.log(`Delivering order ${orderId}`);\\n // Simulate delivery logic\\n await sleep(5);\\n return \\"Order delivered\\";\\n}\\n```\\n\\n
\\n\\n
\\n\\nWorkflow definition inside `src/workflows.ts`:\\n```typescript import {proxyActivities} from \\"@temporalio/workflow\\";\\n\\nexport const { processPayment, checkInventory, deliverOrder } =\\n proxyActivities<{\\n processPayment(orderId: string): Promise;\\n checkInventory(orderId: string): Promise;\\n deliverOrder(orderId: string): Promise;\\n }>({\\n startToCloseTimeout: \\"10 seconds\\",\\n });\\n\\nexport async function OrderWorkflow(orderId: string): Promise {\\n const paymentResult = await processPayment(orderId);\\n const inventoryResult = await checkInventory(orderId);\\n const deliveryResult = await deliverOrder(orderId);\\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\\n}\\n```\\n
\\n\\n
\\nWorker definintion inside `src/worker.ts`:\\n\\n```typescript\\nimport { NativeConnection, Worker } from \\"@temporalio/worker\\";\\nimport * as activities from \\"./activities\\";\\nimport { TASK_QUEUE_NAME } from \\"./shared\\";\\n\\nasync function run() {\\n const connection = await NativeConnection.connect({\\n address: \\"localhost:7233\\",\\n });\\n\\n const worker = await Worker.create({\\n connection,\\n namespace: \\"default\\",\\n taskQueue: TASK_QUEUE_NAME,\\n workflowsPath: require.resolve(\\"./workflows\\"),\\n activities,\\n });\\n\\n await worker.run();\\n}\\n\\nrun().catch((err) => {\\n console.error(err);\\n process.exit(1);\\n});\\n```\\n\\n
\\n\\nAfter you have setup the above components, now you need a client to start of any `OrderWorkflow`. Here is where metatype comes in, through the simple APIs [Temporal Runtime](/docs/reference/runtimes/temporal) exposes, you can communicate with your temporal cluster.\\nDown below is the workflow communication bridge for this system expressed within a [typegraph](/docs/reference/typegraph) which includes endpoints to start a new workflow and describe an existing one.\\n\\n```typescript\\nimport { Policy, t, typegraph } from \\"@typegraph/sdk/index.ts\\";\\nimport { TemporalRuntime } from \\"@typegraph/sdk/providers/temporal.ts\\";\\n\\ntypegraph(\\n {\\n name: \\"order_delivery\\",\\n },\\n (g: any) => {\\n const pub = Policy.public();\\n\\n const temporal = new TemporalRuntime({\\n name: \\"order_delivery\\",\\n hostSecret: \\"HOST\\",\\n namespaceSecret: \\"NAMESPACE\\",\\n });\\n\\n const workflow_id = \\"order-delivery-1\\";\\n\\n const order_id = t.string();\\n\\n g.expose(\\n {\\n start: temporal.startWorkflow(\\"OrderWorkflow\\", order_id),\\n describe: workflow_id\\n ? temporal.describeWorkflow().reduce({ workflow_id })\\n : temporal.describeWorkflow(),\\n },\\n pub,\\n );\\n },\\n);\\n```\\n\\n
\\n\\n {/* break */}\\n \\n\\n
\\nActivities definition inside `activities.py`.\\n\\n```python\\nfrom temporalio import activity\\nimport time\\n\\n@activity.defn\\nasync def process_payment(order_id: str) -> str:\\n print(f\\"Processing payment for order {order_id}\\")\\n # Simulate payment processing logic\\n time.sleep(5)\\n return \\"Payment processed\\"\\n\\n@activity.defn\\nasync def check_inventory(order_id: str) -> str:\\n print(f\\"Checking inventory for order {order_id}\\")\\n # Simulate inventory check logic\\n time.sleep(4)\\n return \\"Inventory available\\"\\n\\n@activity.defn\\nasync def deliver_order(order_id: str) -> str:\\n print(f\\"Delivering order {order_id}\\")\\n time.sleep(8)\\n # Simulate delivery logic\\n return \\"Order delivered\\"\\n```\\n\\n
\\n\\n
\\nWorker defintion inside `run_worker.py`.\\n\\n```python\\nimport asyncio\\n\\nfrom temporalio.client import Client\\nfrom temporalio.worker import Worker\\n\\nfrom activities import process_payment, deliver_order, check_inventory\\nfrom shared import ORDER_DELIVERY_QUEUE\\nfrom workflows import OrderWorkflow\\n\\n\\nasync def main() -> None:\\n client: Client = await Client.connect(\\"localhost:7233\\", namespace=\\"default\\")\\n worker: Worker = Worker(\\n client,\\n task_queue=ORDER_DELIVERY_QUEUE,\\n workflows=[OrderWorkflow],\\n activities=[process_payment, check_inventory, deliver_order],\\n )\\n await worker.run()\\n\\n\\nif __name__ == \\"__main__\\":\\n asyncio.run(main())\\n```\\n\\n
\\n\\nAfter you have setup the above components, now you need a client to start of any `OrderWorkflow`. Here is where metatype comes in, through the simple APIs [Temporal Runtime](/docs/reference/runtimes/temporal) exposes, you can communicate with your temporal cluster.\\nDown below is the workflow communication bridge for this system expressed within a [typegraph](/docs/reference/typegraph) which includes endpoints to start a new workflow and describe an existing one.\\n\\n```python\\nfrom typegraph import t, typegraph, Policy, Graph\\nfrom typegraph.providers.temporal import TemporalRuntime\\n\\n\\n@typegraph()\\ndef example(g: Graph):\\n public = Policy.public()\\n\\n temporal = TemporalRuntime(\\n \\"example\\", \\"HOST\\", namespace_secret=\\"NAMESPACE\\"\\n )\\n\\n workflow_id = \\"order-delivery-1\\"\\n\\n order_id = t.string()\\n\\n g.expose(\\n public,\\n start=temporal.start_workflow(\\"OrderWorkflow\\", order_id),\\n describe=temporal.describe_workflow().reduce({\\"workflow_id\\": workflow_id})\\n if workflow_id\\n else temporal.describe_workflow(),\\n )\\n```\\n\\n
\\n\\n
\\n\\nYou need to add the secrets `HOST` and `NAMESPACE` under your typegraph name inside the `metatype.yaml` file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below.\\n\\n
\\nmetatype.yaml\\n\\n```yaml\\ntypegate:\\n dev:\\n url: \\"http://localhost:7890\\"\\n username: admin\\n password: password\\n secrets:\\n example:\\n POSTGRES: \\"postgresql://postgres:password@postgres:5432/db\\"\\n HOST: \\"http://localhost:7233\\"\\n NAMESPACE: \\"default\\"\\n```\\n\\n
\\n\\nYou need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the `example` parent, which is the name of your typegraph. If the name doesn\'t match, you will face secret not found issues when deploying your typegraph.\\n\\nBefore deploying the above typegraph, you need to start the temporal server and the worker. You need to have [temporal](https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli) installed on your machine.\\n\\n
\\nBoot up temporal\\n\\nStart the temporal server.\\n\\n```bash\\ntemporal server start-dev\\n```\\n\\nStart the worker.\\n\\n\\n\\n\\n ```typescript npx ts-node src/worker.ts ```\\n\\n\\n```python python run_worker.py ```\\n\\n\\n
\\n\\nAfter booting the temporal server, run the command down below to get a locally spinning [typegate](/docs/reference/typegate) instance with your typegraph deployed.\\n\\n```bash\\nmeta dev\\n```\\n\\nAfter completing the above steps, you can access the web GraphQL client of the typegate at [`http://localhost:7890/example`](http://localhost:7890/example). Run this query inside the client to start your workflow.\\n\\n```graphql\\nmutation {\\n start(\\n workflow_id: \\"order-delivery-3\\"\\n task_queue: \\"order-delivery-queue\\"\\n args: [\\"order12\\"]\\n )\\n}\\n```\\n\\nAfter a successful run, you will get the following result which includes the `run_id` of the workflow which has just been started.\\n\\n\\n\\nYou can also check the temporal web UI to monitor your workflows and you should see a result similar to this one.\\n\\n\\n\\nYou can explore the [Temporal Runtime](/docs/reference/runtimes/temporal) for more info.\\n\\nThis wraps up the blog, thanks for reading until the end :)"},{"id":"/2024/08/26/python-on-webassembly","metadata":{"permalink":"/blog/2024/08/26/python-on-webassembly","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-26-python-on-webassembly/index.mdx","source":"@site/blog/2024-08-26-python-on-webassembly/index.mdx","title":"Python on WebAssembly: How?","description":"Metatype\'s different language runtimes are nice, but integrating one is an entire story. Let\'s discover how we managed to implement one for Python.","date":"2024-08-26T00:00:00.000Z","tags":[],"readingTime":11.125,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Distributed execution flow paradigms","permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms"},"nextItem":{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment"}},"content":"Metatype\'s different language runtimes are nice, but integrating one is an entire story. Let\'s discover how we managed to implement one for Python.\\n\\n## Why?\\n\\nYou have probably heard of \\"Function as a Service\\" or FaaS. \\nIn simple terms, FaaS are platforms that allow users to run code in response to events without the hassle of managing the underlying infrastructure. \\nUsers submit their programs and the platform takes care of the rest including, usually, scaling, availability, and configuration.\\nAWS Lambda is one such example and FaaS as a whole are a popular implementation of the serverless model.\\n\\nMetatype has this model at heart with applications composed of small functions that respond to events like http requests and authorization checks. \\nThis is achieved through runtimes like the [`DenoRuntime`](/docs/reference/runtimes/deno) which implements a way to execute functions authored in Typescript using Web Workers as implemented by [Deno](https://docs.deno.com/runtime/manual/runtime/workers/) (not based on Deno Deploy). \\n\\n:::note\\nMetatype supports running multiple apps or typegraphs on a single deployed cluster but we\'re still in the kitchen on a hosted cloud solution. \\nSubscribe to the [blog](https://metatype.dev/blog/rss.xml) or the [Github](https://github.com/metatypedev/metatype) repository for updates.\\n:::\\n\\nImplementing the `DenoRuntime` was a very straightforward affair as the Typegate (the engine at the heart of Metatype) is primarily written in Typescript and runs on a slightly modified version of the Deno runtime.\\nWhat\'s more, JavaScript has single threaded and asynchronous semantics and the v8 engine that it commonly runs on is of very high-quality by all regards. \\nThese qualities lend themselves very well to the requirements of running a serverless platform like security (good sandboxing) and performance (low start-up latencies).\\nThis fact is reflected in the dominance of JavaScript in the serverless market though it doesn\'t hurt that it\'s also the most popular language in use today.\\n\\nAnother very popular language is Python; and its standard library can be quite resourceful for this type of use case.\\nHowever, as we shall see, integrating the Python runtime isn\'t as simple as integrating Deno.\\n\\n## What are the requirements?\\n\\nThere are a number of Python runtimes available but a set of extra factors limit what we can achieve.\\n\\n1. **Security**: functions should have limited access to the execution environment. Python doesn\'t have built-in features for sandboxing out of the box unlike Deno.\\n2. **Speed**: functions should run fast and with low latency. We\'re interested in metrics like cold-start latency and overhead of any cross process/system communication.\\n3. **User-friendliness**: functionalities provided in any of the languages supported by Metatype should, within reason, mirror each other and maintain a degree of uniformity. We support inline code snippets and external file references for `DenoRuntime` and this should be the case for Python as well.\\n4. **Interoperability**: functions running in Python will need to have access to other parts of the app running on the Typegate like being able to invoke other functions.\\n\\nThe Typegate is a TypeScript program with a bit of Rust sprinkled in. \\nIt runs as a traditional POSIX process. \\nThink Linux containers. \\nThis fact renders multi-processing, one of the readily apparent approaches, undesirable as it would require investing is robust worker process management and distribution schemes.\\nIt\'d be great if we could keep everything inside the Typegate process.\\n\\nOne solution that presents itself here is the [PyO3](https://pyo3.rs/) project which provide Rust bindings to different Python runtimes like CPython and PyPy.\\nIt\'d not only allow us to run Python code in-process but it also provide an easy way to expose the functions written in Rust to Python and vice-versa. \\nA good solution for the bidirectional communication needed for our interoperability requirements.\\n\\nUnfortunately, PyO3 doesn\'t have any provisions for sandboxing which is critical for our use case.\\nThis is where WebAssembly enters into the picture. \\nWebAssembly or Wasm for short is a executable bytecode format that originates from the web world and is designed for applications that run inside web-browsers. \\nThis use case shares most of our requirements and the Wasm world promises excellent sandboxing properties that should be perfect for our use case.\\nWe just have to find a way to run Python inside of it.\\n\\n## An aside on WASI \\n\\nWebAssembly System Interface (WASI) is an additional spec for the bytecode format that formalizes how Wasm programs access their host environment.\\nA lot like POSIX, this generally means OS capabilities such as file system access and networking but also, in it\'s latest iteration extends to any custom host defined functionality.\\n\\nWasm + WASI fits very well to our use case. As opposed to mutli-processing, we can instantiate, manage, and expose resources programmatically with ease.\\nAnd as luck would have it, some [community work](https://github.com/vmware-labs/webassembly-language-runtimes) has already been done at the time that led to wasm builds of CPython being available.\\n\\nUnfortunately, the WASI spec itself is a work in progress.\\nWhen we started out, only the limited \\"[preview1](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md)\\" implementation was supported by most runtimes.\\n`preview1` only focused on a standard set of host functionalities much like a `libc` implementation.\\nWell enough but any custom functionality meant having to rely on simple C ABI alike functions for _intra_-process communication.\\nIn order to make this work easier, we elected to bring PyO3 back into the picture so that all the IPC stuff is written in Rust, the language with the most support in the Wasm ecosystem today.\\n\\nAll in all, this would mean the python interpreter wrapped in a PyO3 based native API.\\nAn assembly that accepts user code as strings and then invokes them in response to events.\\nAll of this would be running inside a Wasm runtime, [WasmEdge](https://wasmedge.org/) in this case, which ticks of all of the sandboxing and security requirements.\\nThis approach is well described as the [Reactor pattern](https://wasmcloud.com/blog/webassembly-patterns-command-reactor-library#the-reactor-pattern), a common pattern used in Wasm land.\\n\\n\\"FIRST\\n\\n### File system access\\n\\nSince the PyO3 project doesn\'t support [statically linking](https://github.com/PyO3/pyo3/issues/416) the Python runtime, we\'ll need to find a way dynamically link `libpython`.\\nThankfully, Wasm does support [dynamic linking](https://github.com/WebAssembly/design/blob/main/DynamicLinking.md) and wasm builds of [`libpython`](https://github.com/vmware-labs/webassembly-language-runtimes/tree/main/python) are available curtsy of the WebAssembly Language Runtimes project. \\nBringing all of this together isn\'t as simple though as PyO3\'s tries to load `libpython` from certain _paths_, a concept that isn\'t exactly clearly defined in Wasm\'s post POSIX webtopia.\\n\\nOur first solution was to use [wasi-vfs](https://github.com/kateinoigakukun/wasi-vfs), a tool which allows you to embed a virtual file system, accessible through preview1 APIs, directly into your wasm binaries.\\nThis way, we could prepare a single wasm artifact that contains both the `libpython` build and the custom glue code.\\n\\nThis approach turned out to be quite hacky though and after encountering several issues, we ultimately decided to go with **preopens**.\\nPreopens are another virtual file-system solution where you map an actual file-system directory to a virtual directory visible to a running Wasm instance.\\nThis means we\'ll need to prepare the `libpython` Wasm file on disk before running the instance but it was an acceptable solution.\\nWe also use preopens to provide some of the user submitted code to our custom python runtime.\\n\\nThe following rust snippet demonstrates the preopens looked like in use:\\n\\n```rust\\nfn init_Python_vm() -> Result {\\n let preopens = vec![\\n // User script will be uploaded at ./src/Python which is virtually seen as /app\\n // Each script has access only to /app\\n \\"/app:./src/Python:readonly\\".to_owned()\\n ];\\n\\n // This follow the same idea as above, but for clarity\'s sake we decided to separate it\\n let pylib = PathBuf::from(\\"./vendor/libpython/usr/local/lib\\");\\n\\n // This is our wasm module reponsible for running Python scripts at runtime\\n // It assumes /app and libpython to be available in its world\\n let wasi_mod = PathBuf::from(\\"./build/Python-wasi-reactor.wasm\\");\\n\\n // Now we can instantiate the WASI module with all the configurations above\\n let rt = instantiate_custom_python_runtime(preopens, pylib, wasi_mod)?;\\n rt.run_func(None, \\"init_Python\\", params!())?;\\n\\n // ..\\n\\n Ok(rt)\\n}\\n```\\n\\n### WASI 0.2\\n\\nThe solution described above worked well to an extent but the limitations of preview1 and all the wrangling with PyO3 resulted in complexity that we were always ready to get rid of.\\nThis was exactly what we did after the Bytecode Alliance finalized [WASI 0.2](https://bytecodealliance.org/articles/WASI-0.2) back in January 2024 and with it, a slew of new opportunuties.\\n\\nWASI 0.2 introduces a whole new concept of components, wasm modules that come with pre-specifed interfaces using the [Wit](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md) format and based on a whole new [ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md) to boot.\\nThese new capabilities suggest that it should possible to replace our PyO3 based glue code with the WASI based layer. \\nLet\'s see how.\\n\\nWe first used the new found WASI powers to implement support for Wasm based functions through the [`WasmRuntime`](/docs/reference/runtimes/wasm).\\nThis lead us to implement the [`wit_wire`](https://github.com/metatypedev/metatype/blob/2e692b9ae9e48b6e1a863130fc1bfbdd004cb631/src/wit/wit-wire.wit) protocol, a simple JSON based WIT interface that\'d be used by any wasm component that intenteds to run on the `WasmRuntime`.\\nSimple enough that it\'s reproduced down below in it\'s entirety.\\n\\n```wit\\npackage metatype:wit-wire;\\n\\n// what the host provides\\ninterface typegate-wire {\\n hostcall: func(op-name: string, json: string) -> result;\\n}\\n\\n// what\'s expected from the guest\\ninterface mat-wire {\\n\\n // init function called when we first make the component\\n init: func(args: init-args) -> result;\\n // general purpose event handler\\n handle: func(req: handle-req) -> result;\\n\\n type json-str = string;\\n\\n record init-args {\\n // the list of operations the application is expecting\\n // from this component\\n expected-ops: list\\n metatype-version: string,\\n }\\n\\n record mat-info {\\n op-name: string,\\n mat-title: string,\\n mat-data-json: string,\\n }\\n\\n record init-response {\\n ok: bool\\n }\\n\\n variant init-error {\\n version-mismatch(string),\\n unexpected-mat(mat-info),\\n other(string)\\n }\\n\\n record handle-req {\\n op-name: string,\\n in-json: json-str,\\n }\\n\\n variant handle-err {\\n no-handler,\\n in-json-err(string),\\n handler-err(string),\\n }\\n}\\n\\n// a world defines what interfaces get imported\\n// and exported\\nworld wit-wire {\\n import typegate-wire;\\n\\n export mat-wire;\\n}\\n\\n```\\n\\nSquint your eyes tight enough and the `wit_wire` protocol as implemented wasn\'t far off from what the PyO3 based glue code was doing in the previous implementation.\\nSpecifically, register a list of operations that the Typegate is expecting from the module and execute them for incoming event.\\nWe just need to add support for the operation metadata to contain extra items.\\nIn the case of the [`PythonRuntime`](/docs/reference/runtimes/python), this would be the Python code itself.\\n\\nNow that we have the `wit_wire` implementation taking care of bidirectional communication, we have little reason to keep the PyO3 based glue code around.\\nThis glue was doing a bit more than acting as a boundary though.\\nIt was also responsible for setting up the operating environment for the Python code.\\nFor example, we\'d need some kind of initialization to execute the user\'s Python snippets which are in free standing `lambda` form. \\nHow does one create components out of Python anyways?\\n\\n[componentize-py](https://github.com/bytecodealliance/componentize-py) is a tool authored by the Bytecode Alliance that allows you to produce WASI components that are authored in Python.\\nIt has code generation suite that emits guest bindings in Python for any WIT specification you feed it.\\nIt then takes your Python code written against these bindings and embeds them in a Wasm build of the Python interpreter to produce a component that supports the specified Wit.\\n\\nUnsurprisingly, componentize-py relies on PyO3 and preopens itself in addition to [component-init](https://github.com/dicej/component-init), a solution to pre-intialize components up to a certain point for improved startup latencies.\\nThis pre-intialization means we won\'t need to provide the actual preopens for the resulting component, baking the `libpython` object code directly into it as PyO3 will have dynamically loaded the object code by that point.\\nUltimately, this allows us to write all of our glue code in Python itself.\\n\\nWe still need a bit of Rust to support the `wit_wire` interface on the Typegate but this implementation is general across both the `PythonRuntime` and `WasmRuntime`.\\nWe\'d also moved to the [Wasmtime](https://wasmtime.dev/), also by Bytecode Alliance, for our wasm workloads at this point and their Rust bindings are a pleasure to use.\\nIt\'s all smooth sailing from here.\\n\\n## Cloudy skies?\\n\\nA final stumbling block for this approach was the many seconds Wasmtime spends cooking all your CPU cores when it compiles the fat wasm module that contains the Python interpreter, Pyo3 bindings and more.\\nThis happens because Wasmtime does\'t ([yet](https://github.com/bytecodealliance/rfcs/blob/main/accepted/wasmtime-baseline-compilation.md)) implement any schemes for tiered compilation, all code being greeted by their optimizing compiler, Cranelift.\\nAnd optimizations take time.\\nSure, you only pay this cost the first time you load the Python runtime module as Wasmtime has great support for caching including on-disk caching.\\nBut, 10+ second cold-starts, as measured on one developer\'s machine, are unacceptable in a system that primarily serves HTTP requests.\\nWhat to do?\\n\\nWasmtime has just the feature for this problem, [pre-compilation](https://docs.wasmtime.dev/cli-options.html#compile).\\nAhead-of-time compilation of wasm bytecode into a native instruction set.\\nSuch files are commonly given the `.cwasm` extesion, _c_ for compiled, and they are not a standalone executable but inteded to be run within Wasmtime\'s sandbox.\\nThis eliminates the compliation cost but the semantics of the source wasm bytecode and the runtime safe-guards means that this should be just as safe as JITting it (just-in-time compilation).\\nWe then statically embed this pre-compiled wasm artifact, after compressing it, in the Typegate binary removing the need for sidecar files while ensuring minimal cold-starts for our python workloads.\\nTo be concrete, this means _roughly_ around 200 ms of overhead for a cold function and 5 ms for a warm one.\\nGood enough.\\n\\nThis post describes the technical journey we took to arrive to the current implementation of the `PythonRuntime`. Hopefully, all details were clear enough and please direct any feedback, questions, and thoughts to the comments down below and our Github issues/discussion board."},{"id":"/2024/05/09/programmatic-deployment","metadata":{"permalink":"/blog/2024/05/09/programmatic-deployment","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-05-09-programmatic-deployment/index.mdx","source":"@site/blog/2024-05-09-programmatic-deployment/index.mdx","title":"Programmatic deployment (v0.4.x)","description":"A new approach to deploying typegraphs has been introduced starting with version 0.4.0. This aims to facilitate the development of automation tools around the APIs you build within the Metatype ecosystem.","date":"2024-05-09T00:00:00.000Z","tags":[],"readingTime":3.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly"},"nextItem":{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility"}},"content":"import SDKTabs from \\"@site/src/components/SDKTabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\nimport UpgradePythonSDK from \\"../../shared/upgrade/python-sdk.mdx\\";\\nimport UpgradeTsSDK from \\"../../shared/upgrade/typescript-sdk.mdx\\";\\n\\n\\nA new approach to deploying typegraphs has been introduced starting with version 0.4.0. This aims to facilitate the development of automation tools around the APIs you build within the Metatype ecosystem.\\n\\n## What has changed?\\n\\nBefore v0.4.x, we had to entirely rely on the [meta cli](/docs/reference/meta-cli) to deploy typegraphs to a typegate instance.\\n\\nThis is no longer the case, as all core logic has been moved to the TypeScript/Python typegraph SDKs, both of which share the same WebAssembly-based **typegraph-core** behind the scenes. This provides some degree of assurance that you will have nearly identical experiences with each SDK.\\n\\n## What are the use-cases?\\n\\nSince typegraphs can be written using the programming language your preferred SDK is based on, you can dynamically create typegraphs with ease.\\n\\nThe missing piece was having an interface natively backed inside the SDK for doing deployment programmatically.\\n\\n### Programmatic deployment\\n\\n### Initial setup\\n\\nJust like any other dependency in your favorite programming language, each SDKs can be installed with your favorite package manager.\\n\\nYou can use one of the commands below to get started with the latest available version.\\n\\n\\n \\n \\n \\n \\n \\n \\n\\n\\n#### Configuration\\n\\nThis is analoguous to the yaml configuration file when you are using [meta cli](/docs/reference/meta-cli).\\n\\nIt\'s the place where you tell which typegate you want to deploy to, how you want the artifacts to be resolved, among other settings.\\n\\n\\n \\n\\n```python\\nconfig: TypegraphDeployParams = TypegraphDeployParams(\\n typegate=TypegateConnectionOptions(url=\\"\\", auth=BasicAuth(\\"\\", \\"\\")),\\n typegraph_path=os.path.join(cwd, \\"path-to-typegraph\\"),\\n prefix=\\"\\",\\n secrets={},\\n migrations_dir=path.join(\\"prisma-migrations\\", example.name),\\n migration_actions=None,\\n default_migration_action=MigrationAction(\\n apply=True,\\n reset=True, # allow destructive migrations\\n create=True,\\n ),\\n )\\n```\\n\\n \\n \\n\\n```typescript\\nconst config = {\\n typegate: {\\n url: \\"\\",\\n auth: new BasicAuth(\\"\\", \\"\\"),\\n },\\n typegraphPath: path.join(cwd, \\"path-to-typegraph.ts\\"),\\n prefix: \\"\\",\\n secrets: { POSTGRES: \\"\\" },\\n migrationsDir: path.join(\\"prisma-migrations\\", tg.name),\\n defaultMigrationAction: {\\n create: true,\\n reset: true, // allow destructive migrations\\n },\\n};\\n```\\n\\n \\n\\n\\n\\n### Deploy/remove\\n\\nNow, picture this, you have a lot of typegraphs and one or more typegate instance(s) running, you can easily make small scripts that does any specific job you want.\\n\\n```typescript\\n// ..\\nimport { tgDeploy, tgRemove } from \\"@typegraph/sdk/tg_deploy.js\\";\\n// ..\\n\\nconst BASIC_AUTH = loadMyAuthsFromSomeSource();\\nconst TYPEGATE_URL = \\"...\\";\\n\\nexport async function getTypegraphs() {\\n // Suppose we have these typegraphs..\\n // Let\'s enumerate them like this to simplify\\n return [\\n {\\n tg: await import(\\"path/to/shop-finances\\"),\\n location: \\"path/to/shop-finances.ts\\",\\n },\\n {\\n tg: await import(\\"path/to/shop-stats\\"),\\n location: \\"path/to/shop-stats.ts\\",\\n },\\n ];\\n}\\n\\nexport function getConfig(tgName: string, tgLocation: string) {\\n // Note: You can always develop various ways of constructing the configuration,\\n // like loading it from a file.\\n return {\\n typegate: {\\n url: \\"\\",\\n auth: new BasicAuth(\\"\\", \\"\\"),\\n },\\n typegraphPath: path.join(cwd, \\"path-to-typegraph.ts\\"),\\n prefix: \\"\\",\\n secrets: { POSTGRES: \\"\\" },\\n migrationsDir: path.join(\\"prisma-migrations\\", tg.name),\\n defaultMigrationAction: {\\n create: true,\\n reset: true, // allow destructive migrations\\n },\\n };\\n}\\n\\nexport async function deployAll() {\\n const typegraphs = await getTypegraphs();\\n for (const { tg, location } of typegraphs) {\\n try {\\n const config = getConfig(tg.name, location);\\n // use tgDeploy to deploy typegraphs, it will contain the response from typegate\\n const { typegate } = await tgDeploy(tg, config);\\n const selection = typegate?.data?.addTypegraph;\\n if (selection) {\\n const { messages } = selection;\\n console.log(messages.map(({ text }) => text).join(\\"\\\\n\\"));\\n } else {\\n throw new Error(JSON.stringify(typegate));\\n }\\n } catch (e) {\\n console.error(\\"[!] Failed deploying\\", tg.name);\\n console.error(e);\\n }\\n }\\n}\\n\\nexport async function undeployAll() {\\n const typegraphs = await getTypegraphs();\\n for (const { tg } of typegraphs) {\\n try {\\n // use tgRemove to remove typegraphs\\n const { typegate } = await tgRemove(\\"\\", {\\n baseUrl: TYPEGATE_URL,\\n auth: BASIC_AUTH,\\n });\\n console.log(typegate);\\n } catch (e) {\\n console.error(\\"Failed removing\\", tg.name);\\n console.error(e);\\n }\\n }\\n}\\n```\\n\\n### Going beyond\\n\\nWith these new additions, you can automate virtually anything programmatically on the typegraph side. Starting from having highly dynamic APIs to providing ways to deploy and configure them, you can even build a custom framework around the ecosystem!\\n\\nPlease tell us what you think and report any issues you found on [Github](https://github.com/metatypedev/metatype/issues).\\n\\n:::info Notes\\n\\nYou can check the [Programmatic deployment](/docs/guides/programmatic-deployment) reference page for more information.\\n\\n:::"},{"id":"/2023/11/27/node-compatibility","metadata":{"permalink":"/blog/2023/11/27/node-compatibility","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-11-27-node-compatibility/index.mdx","source":"@site/blog/2023-11-27-node-compatibility/index.mdx","title":"The Node/Deno SDK is now available","description":"We are happy to announce that we have redesigned our SDKs to support Node/Deno and facilitate the integration of future languages. Most of the typegraph SDK is now written in Rust and shaped around a core interface running in WebAssembly.","date":"2023-11-27T00:00:00.000Z","tags":[],"readingTime":1.7,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment"},"nextItem":{"title":"Programmable glue for developers","permalink":"/blog/2023/06/18/programmable-glue"}},"content":"We are happy to announce that we have redesigned our SDKs to support Node/Deno and facilitate the integration of future languages. Most of the [typegraph SDK](/docs/reference/typegraph) is now written in Rust and shaped around a core interface running in WebAssembly.\\n\\n## Meet `wit`\\n\\nIn the realm of WebAssembly, the [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) project emerges as the most mature tool to create and maintain the language bindings for WebAssembly modules. This tool introduces WIT (WebAssembly Interface Types) as an Interface Definition Language (IDL) to describe the imports, exports, and capabilities of WebAssembly components seamlessly.\\n\\nFor example, Metatype implements the reactor pattern to handle requests as they come and delegate part of their execution in correct WASM runtime. The wit-bindgen helps there to define the interfaces between the guest (the Metatype runtime) and the host (the typegate) to ensure the correct serialization of the payloads. The `wit` definition could look like this:\\n\\n```\\npackage metatype:wit-wire;\\n\\ninterface typegate-wire {\\n hostcall: func(op-name: string, json: string) -> result;\\n}\\n\\ninterface mat-wire {\\n record handle-req {\\n op-name: string,\\n in-json: string,\\n }\\n\\n handle: func(req: handle-req) -> result;\\n}\\n\\nworld wit-wire {\\n import typegate-wire;\\n\\n export mat-wire;\\n}\\n```\\n\\nThe `wit` file is then used to generate the bindings for the host and the guest in Rust, TypeScript, Python, and other languages. The host bindings are used in the typegate to call the WASM runtime, and the guest bindings are used in the WASM runtime to call the typegate.\\n\\n## Install the v0.2.x series\\n\\nThe documentation contains now examples for Node and Deno.\\n\\n### Upgrade with Node\\n\\n```bash\\nnpm install @typegraph/sdk\\nmeta new --template node .\\n```\\n\\n### Upgrade with Deno\\n\\n```bash\\nmeta new --template deno .\\n```\\n\\n```typescript\\nimport { typegraph } from \\"npm:@typegraph/sdk/index.js\\";\\n```\\n\\n### Upgrade with Python\\n\\n```python\\npip3 install --upgrade typegraph\\npoetry add typegraph@latest\\n```\\n\\n## Give us feedback!\\n\\nThis new release enables us to provide a consistent experience across all languages and reduce the work to maintain the existing Python SDK.\\n\\nAs always, report issues and let us know what you think on [GitHub](https://github.com/metatypedev/metatype/discussions)."},{"id":"/2023/06/18/programmable-glue","metadata":{"permalink":"/blog/2023/06/18/programmable-glue","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-06-18-programmable-glue/index.mdx","source":"@site/blog/2023-06-18-programmable-glue/index.mdx","title":"Programmable glue for developers","description":"We are introducing Metatype, a new project that allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.","date":"2023-06-18T00:00:00.000Z","tags":[],"readingTime":1.295,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility"},"nextItem":{"title":"Emulating your server nodes locally","permalink":"/blog/2023/03/15/emulating-servers"}},"content":"import { CompareLandscape } from \\"@site/src/components/CompareLandscape\\";\\nimport Metatype from \\"@site/shared/metatype-intro.mdx\\";\\nimport TGExample from \\"@site/src/components/TGExample\\";\\n\\n\\nWe are introducing Metatype, a new project that allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.\\n\\n## What is Metatype?\\n\\n\\n\\n## What are virtual graphs?\\n\\nTypegraphs are a declarative way to expose all APIs, storage and business logic of your stack as a single graph. They take inspiration from domain-driven design principles and in the idea that the relation between of the data is as important as data itself, even though they might be in different locations or shapes.\\n\\n\\n\\nThese elements can then be combined and composed together similarly on how you would compose web components to create an interface in modern frontend practices. This allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.\\n\\n## Where does this belong in the tech landscape?\\n\\nBefore Metatype, there was a gap in the technological landscape for a solution that specifically addressed the transactional, short-lived use cases. While there were existing tools for analytical or long-running use cases, such as Trino and Temporal, there was no generic engine for handling transactional, short-lived tasks.\\n\\n \\n\\n## Give it a try!\\n\\nLet us know what you think! Metatype is open source and we welcome any feedback or contributions. The community primarily lives on [GitHub](https://github.com/metatypedev/metatype).\\n\\n:::info Next steps\\n\\n[Build your first typegraph](/docs/tutorials/metatype-basics) or read more about the [concepts behind Metatype](/docs/concepts/mental-model).\\n\\n:::"},{"id":"/2023/03/15/emulating-servers","metadata":{"permalink":"/blog/2023/03/15/emulating-servers","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-03-15-emulating-servers/index.mdx","source":"@site/blog/2023-03-15-emulating-servers/index.mdx","title":"Emulating your server nodes locally","description":"Introducing the Embedded Typegate","date":"2023-03-15T00:00:00.000Z","tags":[],"readingTime":3.07,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Programmable glue for developers","permalink":"/blog/2023/06/18/programmable-glue"}},"content":"import BlogIntro from \\"@site/src/components/BlogIntro\\";\\nimport UpgradeMetatype from \\"../../shared/upgrade/index.mdx\\";\\n\\n\\n\\n\\n## Introducing the Embedded Typegate\\n\\nThe embedded typegate is a feature that comes with the [Meta CLI](/docs/reference/meta-cli) which provides the option of spinning a typegate instance from the CLI with minimum configurations and installations needed from the developer. All that is required to access the _Embedded Typegate_ is to install _Meta CLI_. The spawned typegate instance behaves similarly to cloud-deployed typegates.\\n\\n## The motive\\n\\nThere are more than a couple of reasons why a developer would be tempted to use an emedded typegate. While developers can start a typegate instance using docker compose, the developer needs to install docker as a dependency to run the typegate container. Even though docker is familiar among many developers, it can sometimes be tricky and unbeknownst to some developers. We at metatype highly value the developer experience and one reason for adding the _embedded typegate_ feature to the _Meta CLI_ is for users to have a smooth experience with our system by providing a docker compose free experience.\\nThis feature provides a great utility for developers to author and test typegraphs in their local machine before deploying them to production level typegate instances on the cloud.\\nAdditionally, developers need not concern themselves with deployment configurations which are needed only during deployment. The only need to focus their energy and time in developing the right application and easily test them on _embedded typegate_ running from the terminal. To add more to what is said, as the typegate engine keeps evolving, users will be abstracted away from the different configurations which might be added on the future. The _Meta CLI_ will abstract much of what\'s not needed in a dev environment. Thus, leaving less headaches to developers on new changes.\\nUltimately, The _embedded typegate_ is designed to be a good dev environment friendly tool which faciliates development time.\\n\\n## Quick First hand example\\n\\n### Install the v0.3.x series\\n\\nEither of the two [Typegraph](/docs/reference/typegraph) SDKs are needed to author typegraphs. For this example, the node SDK will be used.\\n\\nFirst, make sure the _Meta CLI_ is installed.\\n\\n```shell\\ncurl -fsSL https://raw.githubusercontent.com/metatypedev/metatype/main/installer.sh | bash\\n```\\n\\nNext, create a new node project using this command.\\n\\n```shell\\nmeta new --template node\\n```\\n\\nThe above command will create a sample typegraph which you can use to test the embedded typegate.\\n\\nNow, you need to install the typegraph SDK by running the command down below. The previous command generates a `package.json` with the SDK specified as a dependency.\\n\\n```shell\\nnpm install\\n```\\n\\nBefore deploying the typegraph to the embedded typegate, Run the following commands below.\\n\\n```shell\\nmeta dev\\n```\\n\\nNow that there is running instance of a typegate, you can deploy the example typegraph. From another terminal, run the command below.\\n\\n```shell\\nmeta deploy -f api/example.ts --allow-dirty --create-migration --target dev --gate http://localhost:7890\\n```\\n\\nThe typegate runs on port 7890 by default. If you access [http://localhost:7890/example](http://localhost:7890/example) on your browser, you can see an GraphQL interface to interact with the deployed typegraph. You can test the example typegraph using the following graphql query below.\\n\\n```graphql\\nquery {\\n multilpy(first: 3, second: 5)\\n}\\n```\\n\\n\\n\\n## Learn more about Metatype\\n\\nWanna dive deep into the basics of _Metaype_? check our interactive [tutorial](/docs/tutorials/metatype-basics) revolving around the core features of the system."}]}}')}}]); \ No newline at end of file diff --git a/assets/js/b3219b4c.7c571c01.js b/assets/js/b3219b4c.7c571c01.js new file mode 100644 index 0000000000..fd604fb826 --- /dev/null +++ b/assets/js/b3219b4c.7c571c01.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[3099],{83890:e=>{e.exports=JSON.parse('{"archive":{"blogPosts":[{"id":"/2024/09/26/introducing-grpc-runtime","metadata":{"permalink":"/blog/2024/09/26/introducing-grpc-runtime","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-09-26-introducing-grpc-runtime/index.mdx","source":"@site/blog/2024-09-26-introducing-grpc-runtime/index.mdx","title":"Introducing gRPC Runtime","description":"We\'re excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform\'s ability to create versatile and powerful backends through typegraphs.","date":"2024-09-26T00:00:00.000Z","tags":[],"readingTime":4.4,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"nextItem":{"title":"Distributed execution flow paradigms","permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms"}},"content":"We\'re excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform\'s ability to create versatile and powerful backends through typegraphs.\\n\\n## What is gRPC?\\n\\ngRPC, or **g**oogle **R**emote **P**rocedure **C**all, is a high-performance, open-source communication framework initially developed by Google. It enables **efficient and fast communication between microservices** in a distributed system, making it ideal for modern backend architectures.\\n\\nUnlike traditional HTTP APIs that use JSON, gRPC relies on **Protocol Buffers** (protobufs) for serializing data, which are more compact and faster to process. This approach allows gRPC to support high-throughput, low-latency communication, which is crucial for applications where speed and efficiency matter, such as in real-time data processing or large-scale distributed systems.\\n\\nKey benefits of gRPC include:\\n- **Cross-language support**: gRPC supports multiple programming languages, allowing services written in different languages to communicate seamlessly.\\n- **Strong type safety**: Protocol Buffers ensure type-safe communication, catching errors early and improving reliability.\\n- **Bidirectional streaming**: gRPC allows for client and server streaming, enabling continuous data transfer in both directions, ideal for applications like real-time analytics.\\n\\nIn short, gRPC is well-suited for high-performance, scalable backend systems where speed and type safety are essential.\\n\\n## Why gRPC Matters for Metatype\\n\\nMetatype is a platform that enables developers to create **typegraphs**\u2014strongly-typed, composable backend structures that can support multiple protocols and runtime environments. With the introduction of the gRPC Runtime, Metatype allows developers to incorporate gRPC services into these typegraphs, further enhancing the platform\u2019s versatility.\\n\\nBy integrating gRPC, Metatype empowers developers to:\\n- **Expose gRPC services via GraphQL or HTTP endpoints**, making them accessible to clients in a way that best suits their needs.\\n- **Compose gRPC services with other backend components**, such as databases or other APIs, to create powerful and cohesive backend systems.\\n\\n## Diagram: gRPC and Metatype Integration\\n\\n
\\n ![gRPC and Metatype Integration Diagram](./GrpcMetatype.drawio.png)\\n
\\n\\n\\n*Metatype\u2019s gRPC Runtime allows developers to integrate gRPC services into their typegraphs, enabling seamless interaction with gRPC services in the backend.*\\n\\n## Introducing gRPC Runtime in Metatype\\n\\nThe new gRPC Runtime is the latest addition to Metatype\'s suite of runtimes, joining existing options like the HTTP runtime. This expansion allows you to incorporate gRPC services into your typegraphs, further enhancing the versatility of your Metatype-powered backends.\\n\\n## Key Technical Details\\n\\n### Architecture\\nThe gRPC Runtime integrates seamlessly with Metatype\'s existing architecture. It acts as a bridge between your typegraph and external gRPC services, allowing you to incorporate gRPC calls alongside other runtime operations in your backend logic.\\n\\n1. **GrpcRuntime Class**: The main interface for defining gRPC interactions within your typegraph.\\n2. **proto_file**: Path to the .proto file that defines the gRPC service.\\n3. **endpoint**: The gRPC server address in the format `tcp://:`.\\n4. **call method**: Creates a typegraph function for gRPC method calls.\\n\\n### Implementation\\n\\nHere\'s how the gRPC Runtime fits into a Metatype typegraph:\\n\\n```python\\nfrom typegraph import Graph, Policy, typegraph\\nfrom typegraph.graph.params import Cors\\nfrom typegraph.runtimes.grpc import GrpcRuntime\\n\\n@typegraph(\\n cors=Cors(allow_origin=[\\"https://metatype.dev\\", \\"http://localhost:3000\\"]),\\n)\\ndef create_grpc_typegraph(g: Graph):\\n # The GrpcRuntime acts as a bridge between your typegraph and external gRPC services\\n grpc_runtime = GrpcRuntime(\\n # proto_file: Path to the .proto file that defines the gRPC service\\n proto_file=\\"proto/helloworld.proto\\",\\n # endpoint: The gRPC server address in the format tcp://:\\n endpoint=\\"tcp://localhost:4770\\"\\n )\\n \\n # Expose the gRPC service within your typegraph\\n # This allows you to incorporate gRPC calls alongside other runtime operations\\n g.expose(\\n Policy.public(),\\n # call method: Creates a typegraph function for gRPC method calls\\n # It uses the full path to the gRPC method: /package_name.service_name/method_name\\n greet=grpc_runtime.call(\\"/helloworld.Greeter/SayHello\\"),\\n )\\n\\n# The typegraph can now be exposed via GraphQL or HTTP, \\n# allowing clients to interact with the gRPC service through Metatype\'s unified interface\\n```\\nThis implementation demonstrates how the gRPC Runtime integrates with your typegraph, allowing you to:\\n\\n1. Define gRPC service connections using the GrpcRuntime class\\n2. Expose gRPC methods as part of your typegraph\\n3. Combine gRPC functionality with other Metatype features and runtimes\\n\\nBy structuring your gRPC interactions this way, you can seamlessly incorporate gRPC services into your larger Metatype-powered backend, alongside other data sources and business logic.\\n\\n## Benefits for Developers\\n\\n1. **Unified Backend Structure**: Incorporate gRPC services alongside other protocols and data sources in a single, coherent typegraph.\\n2. **Type Safety**: Leverage Metatype\'s strong typing system in conjunction with gRPC\'s protocol buffers for end-to-end type safety.\\n3. **Flexible Exposure**: Easily expose your gRPC services via GraphQL or HTTP endpoints, allowing clients to interact with them using their preferred protocol.\\n4. **Composability**: Combine gRPC calls with other runtime operations, database queries, or business logic within your typegraph.\\n\\n## Getting Started\\n\\nTo start using the gRPC Runtime in your Metatype project:\\n\\n1. Ensure you have the latest version of Metatype installed.\\n2. Prepare your .proto files for the gRPC services you want to integrate.\\n3. Set up your typegraph as shown in the example above, incorporating the GrpcRuntime.\\n4. Configure your Metatype backend to expose the typegraph via GraphQL or HTTP as needed.\\n\\n## Conclusion\\n\\nThe addition of the gRPC Runtime to Metatype further solidifies its position as a comprehensive platform for building robust, type-safe backends. By allowing seamless integration of gRPC services alongside other protocols and data sources, Metatype empowers developers to create versatile and powerful backend systems with ease.\\n\\nFor more detailed documentation, code examples, and best practices, check out our [official Metatype docs](https://metatype.dev/docs)#."},{"id":"/2024/08/27/distributed-execution-flow-paradigms","metadata":{"permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx","source":"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx","title":"Distributed execution flow paradigms","description":"In this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.","date":"2024-08-27T00:00:00.000Z","tags":[],"readingTime":10.92,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Introducing gRPC Runtime","permalink":"/blog/2024/09/26/introducing-grpc-runtime"},"nextItem":{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly"}},"content":"import TabItem from \\"@theme/TabItem\\";\\nimport SDKTabs from \\"@site/src/components/SDKTabs\\";\\n\\n\\nIn this age of cloud development and microservices architecture, problems start to arise with the increased workloads that run in the system. Imagine an e-commerce platform where a customer places an order for a product during a high-demand sale event. The order triggers a series of interconnected processes: payment processing, inventory checks, packaging, shipping, and final delivery. Each of these processes might be handled by different microservices, potentially running on different servers or even in different data centers. What happens if the payment service goes down right after the payment is authorized but before the inventory is updated? Or if the packaging service fails just after the inventory is deducted but before the item is packed? Without a robust mechanism to ensure that each step in the workflow completes successfully and that failures are properly handled, you could end up with unhappy customers, lost orders, and inventory discrepancies.\\n\\nHaving multiple components in your system introduces more failure points, which is a common phenomenon in complex systems. But one important behavior any application must ensure is that the execution flow reaches its completion. As systems grow in features and complexity, the likelihood of long-running processes increases. To ensure these processes complete as intended, several solutions have been introduced over the last few decades.\\nLet\'s explore some of the solutions that have been proposed to achieve workflow completeness.\\n\\n### 1. Event-Driven Architecture with Message Queues\\n\\nThis architecture relies heavily on services communicating by publishing and subscribing to events using message queues. Message queues are persistent storages that ensure data is not lost during failures or service unavailability. Components in a distributed system synchronize by using events/messages through these independent services. While this approach offers service decomposability and fault tolerance, it has some shortcomings. For example, using message queues comes with the overhead of managing messages (e.g., deduplication and message ordering). It also isn\u2019t ideal for systems requiring immediate consistency across components. Some technologies and patterns that utilize this architecture include:\\n\\n- [RabbitMQ](https://www.rabbitmq.com/)\\n- [Amazon SQS](https://aws.amazon.com/sqs/)\\n\\n![](eda.drawio.svg)\\n\\n
\\n Fig. Event Driven Architecture with Message Queues - RabbitMQ\\n
\\n\\n#### Advantages\\n\\n- Improved Scalability\\n- Enhanced Responsiveness\\n- Enhanced Fault Tolerance\\n- Simplified Complex Workflows\\n- Real-Time Data Processing\\n\\n#### Challenges\\n\\n- Event Ordering\\n- Data Consistency\\n- Monitoring and Debugging\\n- Event Deduplication\\n\\nYou can mitigate or reduce these challenges by following best practices like Event Sourcing, Idempotent Processing, CQRS (Command Query Responsibility Segregation), and Event Versioning.\\n\\n### 2. The [Saga Pattern](https://microservices.io/patterns/data/saga.html)\\n\\nThis design pattern aims to achieve consistency across different services in a distributed system by breaking complex transactions spanning multiple components into a series of local transactions. Each of these transactions triggers an event or message that starts the next transaction in the sequence. If any local transaction fails to complete, a series of compensating actions roll back the effects of preceding transactions. While the orchestration of local transactions can vary, the pattern aims to achieve consistency in a microservices-based system. Events are designed to be stored in durable storage systems or logs, providing a trail to reconstruct the system to a state after a failure. While the saga pattern is an effective way to ensure consistency, it can be challenging to implement timer/timeout-based workflows and to design and implement the compensating actions for local transactions.\\n\\n**Note**: In the Saga pattern, a compensating transaction must be idempotent and retryable. These principles ensure that transactions can be managed without manual intervention.\\n\\n![](saga.drawio.svg)\\n\\n
\\n Fig. The Saga Pattern for Order delivery system\\n
\\n\\n#### Advantages\\n\\n- Ensures data consistency in a distributed system without tight coupling.\\n- Provides Roll back if one of the operations in the sequence fails.\\n\\n#### Drawbacks\\n\\n- Might be challenging to implement initially.\\n- Hard to debug.\\n- Compensating transactions don\u2019t always work.\\n\\n### 3. [Stateful Orchestrators](https://docs.oracle.com/en/applications/jd-edwards/cross-product/9.2/eotos/creating-a-stateful-orchestration-release-9-2-8-3.html#u30249073)\\n\\nStateful orchestrators provide a solution for long-running workflows by maintaining the state of each step in a workflow. Each step in a workflow represents a task, and these tasks are represented as states inside workflows. Workflows are defined as state machines or directed acyclic graphs (DAGs). In this approach, an orchestrator handles task execution order, transitioning, handling retries, and maintaining state. In the event of a failure, the system can recover from the persisted state. Stateful orchestrators offer significant value in fault tolerance, consistency, and observability. It\u2019s one of the solutions proven effective in modern distributed computing. Some well-known services that provide this solution include:\\n\\n- [Apache Airflow](https://airflow.apache.org/docs/apache-airflow/stable/core-concepts/overview.html)\\n- [Azure Logic Apps](https://azure.microsoft.com/en-us/products/logic-apps)\\n\\n#### Advantages\\n\\n- **High Resiliency**: Stateful orchestrators provide high resiliency in case of outages, ensuring that workflows can continue from where they left off.\\n- **Data Persistence**: They allow you to keep, review, or reference data from previous events, which is useful for long-running processes.\\n- **Extended Runtime**: Stateful workflows can continue running for much longer than stateless workflows, making them suitable for complex and long-running tasks.\\n\\n#### Challenges\\n\\n- **Additional Complexity**: They introduce additional complexity, requiring you to manage issues such as load balancing, CPU and memory usage, and networking.\\n- **Cost**: With stateful workflows, you pay for the VMs that are running in the cluster, whereas with stateless workflows, you pay only for the actual compute resources consumed.\\n\\n### 4. Durable Execution\\n\\nDurable execution refers to the ability of a system to preserve the state of an application and persist execution despite failures or interruptions. Durable execution ensures that for every task, its inputs, outputs, call stack, and local variables are persisted. These constraints, or rather features, allow a system to automatically retry or continue running in the face of infrastructure or system failures, ultimately ensuring completion.\\n\\nDurable execution isn\u2019t a completely distinct solution from the ones listed above but rather incorporates some of their strengths while presenting a more comprehensive approach to achieving consistency, fault tolerance, data integrity, resilience for long-running processes, and observability.\\n\\n\\n
Fig. Durable workflow engine
\\n\\n#### Advantages\\n\\n- **Reduced Manual Intervention**: Minimizes the need for human intervention by handling retries and failures programmatically.\\n- **Improved Observability**: Provides a clear audit trail and visibility into the state of workflows, which aids in debugging and monitoring.\\n- **Scalability**: Scales efficiently across distributed systems while maintaining workflow integrity.\\n\\n#### Challenges\\n\\n- **Resource Intensive**: Persistent state storage and management can consume significant resources, especially in large-scale systems.\\n- **Latency**: The need to persist state and handle retries can introduce latency in the execution flow.\\n\\nAs durable execution grows to be a fundamental driver of distributed computing, some of the solutions which use this architecture are\\n\\n- [Temporal](https://temporal.io/)\\n- [Uber Cadence](https://cadenceworkflow.io/)\\n\\nAmong these, [Temporal](https://temporal.io/) has grown in influence, used by companies like SnapChat, HashiCorp, Stripe, DoorDash, and DataDog. Its success is driven by its practical application in real-world scenarios and the expertise of its founders.\\n\\nAt Metatype, we recognize the value of durable execution and are committed to making it accessible. Our [Temporal Runtime](/docs/reference/runtimes/temporal) integrates seamlessly into our declarative API development platform, enabling users to harness the power of Temporal directly within Metatype. For those interested in exploring further, our documentation provides a detailed guide on getting started with [Temporal Runtime](/docs/reference/runtimes/temporal).\\n\\nBelow is an example of how you can build a simple API to interact with an order delivery temporal workflow within Metatype.\\n\\n:::note\\nIf you are new to Metatype or haven\u2019t set it up yet in your development environment. You can follow this [guideline](/docs/tutorials/quick-start).\\n:::\\n\\nFor this example, the order delivery system will have few components/services such as Payment, Inventory and Delivery.\\n\\nYour temporal workflow definition should look similar to the one below.\\n\\n\\n\\n \\n\\n
\\n\\nActivities definition inside `src/activities.ts`:`\\n\\n```typescript\\nasync function sleep(time: number) {\\n return new Promise((resolve) => {\\n setTimeout(resolve, time);\\n });\\n}\\n\\nexport async function processPayment(orderId: string): Promise {\\n console.log(`Processing payment for order ${orderId}`);\\n // Simulate payment processing logic\\n await sleep(2);\\n return \\"Payment processed\\";\\n}\\n\\nexport async function checkInventory(orderId: string): Promise {\\n console.log(`Checking inventory for order ${orderId}`);\\n // Simulate inventory check logic\\n await sleep(2);\\n return \\"Inventory available\\";\\n}\\n\\nexport async function deliverOrder(orderId: string): Promise {\\n console.log(`Delivering order ${orderId}`);\\n // Simulate delivery logic\\n await sleep(5);\\n return \\"Order delivered\\";\\n}\\n```\\n\\n
\\n\\n
\\n\\nWorkflow definition inside `src/workflows.ts`:\\n```typescript import {proxyActivities} from \\"@temporalio/workflow\\";\\n\\nexport const { processPayment, checkInventory, deliverOrder } =\\n proxyActivities<{\\n processPayment(orderId: string): Promise;\\n checkInventory(orderId: string): Promise;\\n deliverOrder(orderId: string): Promise;\\n }>({\\n startToCloseTimeout: \\"10 seconds\\",\\n });\\n\\nexport async function OrderWorkflow(orderId: string): Promise {\\n const paymentResult = await processPayment(orderId);\\n const inventoryResult = await checkInventory(orderId);\\n const deliveryResult = await deliverOrder(orderId);\\n return `Order ${orderId} completed with results: ${paymentResult}, ${inventoryResult}, ${deliveryResult}`;\\n}\\n```\\n
\\n\\n
\\nWorker definintion inside `src/worker.ts`:\\n\\n```typescript\\nimport { NativeConnection, Worker } from \\"@temporalio/worker\\";\\nimport * as activities from \\"./activities\\";\\nimport { TASK_QUEUE_NAME } from \\"./shared\\";\\n\\nasync function run() {\\n const connection = await NativeConnection.connect({\\n address: \\"localhost:7233\\",\\n });\\n\\n const worker = await Worker.create({\\n connection,\\n namespace: \\"default\\",\\n taskQueue: TASK_QUEUE_NAME,\\n workflowsPath: require.resolve(\\"./workflows\\"),\\n activities,\\n });\\n\\n await worker.run();\\n}\\n\\nrun().catch((err) => {\\n console.error(err);\\n process.exit(1);\\n});\\n```\\n\\n
\\n\\nAfter you have setup the above components, now you need a client to start of any `OrderWorkflow`. Here is where metatype comes in, through the simple APIs [Temporal Runtime](/docs/reference/runtimes/temporal) exposes, you can communicate with your temporal cluster.\\nDown below is the workflow communication bridge for this system expressed within a [typegraph](/docs/reference/typegraph) which includes endpoints to start a new workflow and describe an existing one.\\n\\n```typescript\\nimport { Policy, t, typegraph } from \\"@typegraph/sdk/index.ts\\";\\nimport { TemporalRuntime } from \\"@typegraph/sdk/providers/temporal.ts\\";\\n\\ntypegraph(\\n {\\n name: \\"order_delivery\\",\\n },\\n (g: any) => {\\n const pub = Policy.public();\\n\\n const temporal = new TemporalRuntime({\\n name: \\"order_delivery\\",\\n hostSecret: \\"HOST\\",\\n namespaceSecret: \\"NAMESPACE\\",\\n });\\n\\n const workflow_id = \\"order-delivery-1\\";\\n\\n const order_id = t.string();\\n\\n g.expose(\\n {\\n start: temporal.startWorkflow(\\"OrderWorkflow\\", order_id),\\n describe: workflow_id\\n ? temporal.describeWorkflow().reduce({ workflow_id })\\n : temporal.describeWorkflow(),\\n },\\n pub,\\n );\\n },\\n);\\n```\\n\\n
\\n\\n {/* break */}\\n \\n\\n
\\nActivities definition inside `activities.py`.\\n\\n```python\\nfrom temporalio import activity\\nimport time\\n\\n@activity.defn\\nasync def process_payment(order_id: str) -> str:\\n print(f\\"Processing payment for order {order_id}\\")\\n # Simulate payment processing logic\\n time.sleep(5)\\n return \\"Payment processed\\"\\n\\n@activity.defn\\nasync def check_inventory(order_id: str) -> str:\\n print(f\\"Checking inventory for order {order_id}\\")\\n # Simulate inventory check logic\\n time.sleep(4)\\n return \\"Inventory available\\"\\n\\n@activity.defn\\nasync def deliver_order(order_id: str) -> str:\\n print(f\\"Delivering order {order_id}\\")\\n time.sleep(8)\\n # Simulate delivery logic\\n return \\"Order delivered\\"\\n```\\n\\n
\\n\\n
\\nWorker defintion inside `run_worker.py`.\\n\\n```python\\nimport asyncio\\n\\nfrom temporalio.client import Client\\nfrom temporalio.worker import Worker\\n\\nfrom activities import process_payment, deliver_order, check_inventory\\nfrom shared import ORDER_DELIVERY_QUEUE\\nfrom workflows import OrderWorkflow\\n\\n\\nasync def main() -> None:\\n client: Client = await Client.connect(\\"localhost:7233\\", namespace=\\"default\\")\\n worker: Worker = Worker(\\n client,\\n task_queue=ORDER_DELIVERY_QUEUE,\\n workflows=[OrderWorkflow],\\n activities=[process_payment, check_inventory, deliver_order],\\n )\\n await worker.run()\\n\\n\\nif __name__ == \\"__main__\\":\\n asyncio.run(main())\\n```\\n\\n
\\n\\nAfter you have setup the above components, now you need a client to start of any `OrderWorkflow`. Here is where metatype comes in, through the simple APIs [Temporal Runtime](/docs/reference/runtimes/temporal) exposes, you can communicate with your temporal cluster.\\nDown below is the workflow communication bridge for this system expressed within a [typegraph](/docs/reference/typegraph) which includes endpoints to start a new workflow and describe an existing one.\\n\\n```python\\nfrom typegraph import t, typegraph, Policy, Graph\\nfrom typegraph.providers.temporal import TemporalRuntime\\n\\n\\n@typegraph()\\ndef example(g: Graph):\\n public = Policy.public()\\n\\n temporal = TemporalRuntime(\\n \\"example\\", \\"HOST\\", namespace_secret=\\"NAMESPACE\\"\\n )\\n\\n workflow_id = \\"order-delivery-1\\"\\n\\n order_id = t.string()\\n\\n g.expose(\\n public,\\n start=temporal.start_workflow(\\"OrderWorkflow\\", order_id),\\n describe=temporal.describe_workflow().reduce({\\"workflow_id\\": workflow_id})\\n if workflow_id\\n else temporal.describe_workflow(),\\n )\\n```\\n\\n
\\n\\n
\\n\\nYou need to add the secrets `HOST` and `NAMESPACE` under your typegraph name inside the `metatype.yaml` file. These secrets are important to connect with your temporal cluster and can be safely stored in the config file as shown below.\\n\\n
\\nmetatype.yaml\\n\\n```yaml\\ntypegate:\\n dev:\\n url: \\"http://localhost:7890\\"\\n username: admin\\n password: password\\n secrets:\\n example:\\n POSTGRES: \\"postgresql://postgres:password@postgres:5432/db\\"\\n HOST: \\"http://localhost:7233\\"\\n NAMESPACE: \\"default\\"\\n```\\n\\n
\\n\\nYou need to add only the last two lines as the others are auto-generated. Note that secrets are defined under the `example` parent, which is the name of your typegraph. If the name doesn\'t match, you will face secret not found issues when deploying your typegraph.\\n\\nBefore deploying the above typegraph, you need to start the temporal server and the worker. You need to have [temporal](https://learn.temporal.io/getting_started/typescript/dev_environment/#set-up-a-local-temporal-service-for-development-with-temporal-cli) installed on your machine.\\n\\n
\\nBoot up temporal\\n\\nStart the temporal server.\\n\\n```bash\\ntemporal server start-dev\\n```\\n\\nStart the worker.\\n\\n\\n\\n\\n ```typescript npx ts-node src/worker.ts ```\\n\\n\\n```python python run_worker.py ```\\n\\n\\n
\\n\\nAfter booting the temporal server, run the command down below to get a locally spinning [typegate](/docs/reference/typegate) instance with your typegraph deployed.\\n\\n```bash\\nmeta dev\\n```\\n\\nAfter completing the above steps, you can access the web GraphQL client of the typegate at [`http://localhost:7890/example`](http://localhost:7890/example). Run this query inside the client to start your workflow.\\n\\n```graphql\\nmutation {\\n start(\\n workflow_id: \\"order-delivery-3\\"\\n task_queue: \\"order-delivery-queue\\"\\n args: [\\"order12\\"]\\n )\\n}\\n```\\n\\nAfter a successful run, you will get the following result which includes the `run_id` of the workflow which has just been started.\\n\\n\\n\\nYou can also check the temporal web UI to monitor your workflows and you should see a result similar to this one.\\n\\n\\n\\nYou can explore the [Temporal Runtime](/docs/reference/runtimes/temporal) for more info.\\n\\nThis wraps up the blog, thanks for reading until the end :)"},{"id":"/2024/08/26/python-on-webassembly","metadata":{"permalink":"/blog/2024/08/26/python-on-webassembly","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-08-26-python-on-webassembly/index.mdx","source":"@site/blog/2024-08-26-python-on-webassembly/index.mdx","title":"Python on WebAssembly: How?","description":"Metatype\'s different language runtimes are nice, but integrating one is an entire story. Let\'s discover how we managed to implement one for Python.","date":"2024-08-26T00:00:00.000Z","tags":[],"readingTime":11.125,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Distributed execution flow paradigms","permalink":"/blog/2024/08/27/distributed-execution-flow-paradigms"},"nextItem":{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment"}},"content":"Metatype\'s different language runtimes are nice, but integrating one is an entire story. Let\'s discover how we managed to implement one for Python.\\n\\n## Why?\\n\\nYou have probably heard of \\"Function as a Service\\" or FaaS. \\nIn simple terms, FaaS are platforms that allow users to run code in response to events without the hassle of managing the underlying infrastructure. \\nUsers submit their programs and the platform takes care of the rest including, usually, scaling, availability, and configuration.\\nAWS Lambda is one such example and FaaS as a whole are a popular implementation of the serverless model.\\n\\nMetatype has this model at heart with applications composed of small functions that respond to events like http requests and authorization checks. \\nThis is achieved through runtimes like the [`DenoRuntime`](/docs/reference/runtimes/deno) which implements a way to execute functions authored in Typescript using Web Workers as implemented by [Deno](https://docs.deno.com/runtime/manual/runtime/workers/) (not based on Deno Deploy). \\n\\n:::note\\nMetatype supports running multiple apps or typegraphs on a single deployed cluster but we\'re still in the kitchen on a hosted cloud solution. \\nSubscribe to the [blog](https://metatype.dev/blog/rss.xml) or the [Github](https://github.com/metatypedev/metatype) repository for updates.\\n:::\\n\\nImplementing the `DenoRuntime` was a very straightforward affair as the Typegate (the engine at the heart of Metatype) is primarily written in Typescript and runs on a slightly modified version of the Deno runtime.\\nWhat\'s more, JavaScript has single threaded and asynchronous semantics and the v8 engine that it commonly runs on is of very high-quality by all regards. \\nThese qualities lend themselves very well to the requirements of running a serverless platform like security (good sandboxing) and performance (low start-up latencies).\\nThis fact is reflected in the dominance of JavaScript in the serverless market though it doesn\'t hurt that it\'s also the most popular language in use today.\\n\\nAnother very popular language is Python; and its standard library can be quite resourceful for this type of use case.\\nHowever, as we shall see, integrating the Python runtime isn\'t as simple as integrating Deno.\\n\\n## What are the requirements?\\n\\nThere are a number of Python runtimes available but a set of extra factors limit what we can achieve.\\n\\n1. **Security**: functions should have limited access to the execution environment. Python doesn\'t have built-in features for sandboxing out of the box unlike Deno.\\n2. **Speed**: functions should run fast and with low latency. We\'re interested in metrics like cold-start latency and overhead of any cross process/system communication.\\n3. **User-friendliness**: functionalities provided in any of the languages supported by Metatype should, within reason, mirror each other and maintain a degree of uniformity. We support inline code snippets and external file references for `DenoRuntime` and this should be the case for Python as well.\\n4. **Interoperability**: functions running in Python will need to have access to other parts of the app running on the Typegate like being able to invoke other functions.\\n\\nThe Typegate is a TypeScript program with a bit of Rust sprinkled in. \\nIt runs as a traditional POSIX process. \\nThink Linux containers. \\nThis fact renders multi-processing, one of the readily apparent approaches, undesirable as it would require investing is robust worker process management and distribution schemes.\\nIt\'d be great if we could keep everything inside the Typegate process.\\n\\nOne solution that presents itself here is the [PyO3](https://pyo3.rs/) project which provide Rust bindings to different Python runtimes like CPython and PyPy.\\nIt\'d not only allow us to run Python code in-process but it also provide an easy way to expose the functions written in Rust to Python and vice-versa. \\nA good solution for the bidirectional communication needed for our interoperability requirements.\\n\\nUnfortunately, PyO3 doesn\'t have any provisions for sandboxing which is critical for our use case.\\nThis is where WebAssembly enters into the picture. \\nWebAssembly or Wasm for short is a executable bytecode format that originates from the web world and is designed for applications that run inside web-browsers. \\nThis use case shares most of our requirements and the Wasm world promises excellent sandboxing properties that should be perfect for our use case.\\nWe just have to find a way to run Python inside of it.\\n\\n## An aside on WASI \\n\\nWebAssembly System Interface (WASI) is an additional spec for the bytecode format that formalizes how Wasm programs access their host environment.\\nA lot like POSIX, this generally means OS capabilities such as file system access and networking but also, in it\'s latest iteration extends to any custom host defined functionality.\\n\\nWasm + WASI fits very well to our use case. As opposed to mutli-processing, we can instantiate, manage, and expose resources programmatically with ease.\\nAnd as luck would have it, some [community work](https://github.com/vmware-labs/webassembly-language-runtimes) has already been done at the time that led to wasm builds of CPython being available.\\n\\nUnfortunately, the WASI spec itself is a work in progress.\\nWhen we started out, only the limited \\"[preview1](https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md)\\" implementation was supported by most runtimes.\\n`preview1` only focused on a standard set of host functionalities much like a `libc` implementation.\\nWell enough but any custom functionality meant having to rely on simple C ABI alike functions for _intra_-process communication.\\nIn order to make this work easier, we elected to bring PyO3 back into the picture so that all the IPC stuff is written in Rust, the language with the most support in the Wasm ecosystem today.\\n\\nAll in all, this would mean the python interpreter wrapped in a PyO3 based native API.\\nAn assembly that accepts user code as strings and then invokes them in response to events.\\nAll of this would be running inside a Wasm runtime, [WasmEdge](https://wasmedge.org/) in this case, which ticks of all of the sandboxing and security requirements.\\nThis approach is well described as the [Reactor pattern](https://wasmcloud.com/blog/webassembly-patterns-command-reactor-library#the-reactor-pattern), a common pattern used in Wasm land.\\n\\n\\"FIRST\\n\\n### File system access\\n\\nSince the PyO3 project doesn\'t support [statically linking](https://github.com/PyO3/pyo3/issues/416) the Python runtime, we\'ll need to find a way dynamically link `libpython`.\\nThankfully, Wasm does support [dynamic linking](https://github.com/WebAssembly/design/blob/main/DynamicLinking.md) and wasm builds of [`libpython`](https://github.com/vmware-labs/webassembly-language-runtimes/tree/main/python) are available curtsy of the WebAssembly Language Runtimes project. \\nBringing all of this together isn\'t as simple though as PyO3\'s tries to load `libpython` from certain _paths_, a concept that isn\'t exactly clearly defined in Wasm\'s post POSIX webtopia.\\n\\nOur first solution was to use [wasi-vfs](https://github.com/kateinoigakukun/wasi-vfs), a tool which allows you to embed a virtual file system, accessible through preview1 APIs, directly into your wasm binaries.\\nThis way, we could prepare a single wasm artifact that contains both the `libpython` build and the custom glue code.\\n\\nThis approach turned out to be quite hacky though and after encountering several issues, we ultimately decided to go with **preopens**.\\nPreopens are another virtual file-system solution where you map an actual file-system directory to a virtual directory visible to a running Wasm instance.\\nThis means we\'ll need to prepare the `libpython` Wasm file on disk before running the instance but it was an acceptable solution.\\nWe also use preopens to provide some of the user submitted code to our custom python runtime.\\n\\nThe following rust snippet demonstrates the preopens looked like in use:\\n\\n```rust\\nfn init_Python_vm() -> Result {\\n let preopens = vec![\\n // User script will be uploaded at ./src/Python which is virtually seen as /app\\n // Each script has access only to /app\\n \\"/app:./src/Python:readonly\\".to_owned()\\n ];\\n\\n // This follow the same idea as above, but for clarity\'s sake we decided to separate it\\n let pylib = PathBuf::from(\\"./vendor/libpython/usr/local/lib\\");\\n\\n // This is our wasm module reponsible for running Python scripts at runtime\\n // It assumes /app and libpython to be available in its world\\n let wasi_mod = PathBuf::from(\\"./build/Python-wasi-reactor.wasm\\");\\n\\n // Now we can instantiate the WASI module with all the configurations above\\n let rt = instantiate_custom_python_runtime(preopens, pylib, wasi_mod)?;\\n rt.run_func(None, \\"init_Python\\", params!())?;\\n\\n // ..\\n\\n Ok(rt)\\n}\\n```\\n\\n### WASI 0.2\\n\\nThe solution described above worked well to an extent but the limitations of preview1 and all the wrangling with PyO3 resulted in complexity that we were always ready to get rid of.\\nThis was exactly what we did after the Bytecode Alliance finalized [WASI 0.2](https://bytecodealliance.org/articles/WASI-0.2) back in January 2024 and with it, a slew of new opportunuties.\\n\\nWASI 0.2 introduces a whole new concept of components, wasm modules that come with pre-specifed interfaces using the [Wit](https://github.com/WebAssembly/component-model/blob/main/design/mvp/WIT.md) format and based on a whole new [ABI](https://github.com/WebAssembly/component-model/blob/main/design/mvp/CanonicalABI.md) to boot.\\nThese new capabilities suggest that it should possible to replace our PyO3 based glue code with the WASI based layer. \\nLet\'s see how.\\n\\nWe first used the new found WASI powers to implement support for Wasm based functions through the [`WasmRuntime`](/docs/reference/runtimes/wasm).\\nThis lead us to implement the [`wit_wire`](https://github.com/metatypedev/metatype/blob/2e692b9ae9e48b6e1a863130fc1bfbdd004cb631/src/wit/wit-wire.wit) protocol, a simple JSON based WIT interface that\'d be used by any wasm component that intenteds to run on the `WasmRuntime`.\\nSimple enough that it\'s reproduced down below in it\'s entirety.\\n\\n```wit\\npackage metatype:wit-wire;\\n\\n// what the host provides\\ninterface typegate-wire {\\n hostcall: func(op-name: string, json: string) -> result;\\n}\\n\\n// what\'s expected from the guest\\ninterface mat-wire {\\n\\n // init function called when we first make the component\\n init: func(args: init-args) -> result;\\n // general purpose event handler\\n handle: func(req: handle-req) -> result;\\n\\n type json-str = string;\\n\\n record init-args {\\n // the list of operations the application is expecting\\n // from this component\\n expected-ops: list\\n metatype-version: string,\\n }\\n\\n record mat-info {\\n op-name: string,\\n mat-title: string,\\n mat-data-json: string,\\n }\\n\\n record init-response {\\n ok: bool\\n }\\n\\n variant init-error {\\n version-mismatch(string),\\n unexpected-mat(mat-info),\\n other(string)\\n }\\n\\n record handle-req {\\n op-name: string,\\n in-json: json-str,\\n }\\n\\n variant handle-err {\\n no-handler,\\n in-json-err(string),\\n handler-err(string),\\n }\\n}\\n\\n// a world defines what interfaces get imported\\n// and exported\\nworld wit-wire {\\n import typegate-wire;\\n\\n export mat-wire;\\n}\\n\\n```\\n\\nSquint your eyes tight enough and the `wit_wire` protocol as implemented wasn\'t far off from what the PyO3 based glue code was doing in the previous implementation.\\nSpecifically, register a list of operations that the Typegate is expecting from the module and execute them for incoming event.\\nWe just need to add support for the operation metadata to contain extra items.\\nIn the case of the [`PythonRuntime`](/docs/reference/runtimes/python), this would be the Python code itself.\\n\\nNow that we have the `wit_wire` implementation taking care of bidirectional communication, we have little reason to keep the PyO3 based glue code around.\\nThis glue was doing a bit more than acting as a boundary though.\\nIt was also responsible for setting up the operating environment for the Python code.\\nFor example, we\'d need some kind of initialization to execute the user\'s Python snippets which are in free standing `lambda` form. \\nHow does one create components out of Python anyways?\\n\\n[componentize-py](https://github.com/bytecodealliance/componentize-py) is a tool authored by the Bytecode Alliance that allows you to produce WASI components that are authored in Python.\\nIt has code generation suite that emits guest bindings in Python for any WIT specification you feed it.\\nIt then takes your Python code written against these bindings and embeds them in a Wasm build of the Python interpreter to produce a component that supports the specified Wit.\\n\\nUnsurprisingly, componentize-py relies on PyO3 and preopens itself in addition to [component-init](https://github.com/dicej/component-init), a solution to pre-intialize components up to a certain point for improved startup latencies.\\nThis pre-intialization means we won\'t need to provide the actual preopens for the resulting component, baking the `libpython` object code directly into it as PyO3 will have dynamically loaded the object code by that point.\\nUltimately, this allows us to write all of our glue code in Python itself.\\n\\nWe still need a bit of Rust to support the `wit_wire` interface on the Typegate but this implementation is general across both the `PythonRuntime` and `WasmRuntime`.\\nWe\'d also moved to the [Wasmtime](https://wasmtime.dev/), also by Bytecode Alliance, for our wasm workloads at this point and their Rust bindings are a pleasure to use.\\nIt\'s all smooth sailing from here.\\n\\n## Cloudy skies?\\n\\nA final stumbling block for this approach was the many seconds Wasmtime spends cooking all your CPU cores when it compiles the fat wasm module that contains the Python interpreter, Pyo3 bindings and more.\\nThis happens because Wasmtime does\'t ([yet](https://github.com/bytecodealliance/rfcs/blob/main/accepted/wasmtime-baseline-compilation.md)) implement any schemes for tiered compilation, all code being greeted by their optimizing compiler, Cranelift.\\nAnd optimizations take time.\\nSure, you only pay this cost the first time you load the Python runtime module as Wasmtime has great support for caching including on-disk caching.\\nBut, 10+ second cold-starts, as measured on one developer\'s machine, are unacceptable in a system that primarily serves HTTP requests.\\nWhat to do?\\n\\nWasmtime has just the feature for this problem, [pre-compilation](https://docs.wasmtime.dev/cli-options.html#compile).\\nAhead-of-time compilation of wasm bytecode into a native instruction set.\\nSuch files are commonly given the `.cwasm` extesion, _c_ for compiled, and they are not a standalone executable but inteded to be run within Wasmtime\'s sandbox.\\nThis eliminates the compliation cost but the semantics of the source wasm bytecode and the runtime safe-guards means that this should be just as safe as JITting it (just-in-time compilation).\\nWe then statically embed this pre-compiled wasm artifact, after compressing it, in the Typegate binary removing the need for sidecar files while ensuring minimal cold-starts for our python workloads.\\nTo be concrete, this means _roughly_ around 200 ms of overhead for a cold function and 5 ms for a warm one.\\nGood enough.\\n\\nThis post describes the technical journey we took to arrive to the current implementation of the `PythonRuntime`. Hopefully, all details were clear enough and please direct any feedback, questions, and thoughts to the comments down below and our Github issues/discussion board."},{"id":"/2024/05/09/programmatic-deployment","metadata":{"permalink":"/blog/2024/05/09/programmatic-deployment","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-05-09-programmatic-deployment/index.mdx","source":"@site/blog/2024-05-09-programmatic-deployment/index.mdx","title":"Programmatic deployment (v0.4.x)","description":"A new approach to deploying typegraphs has been introduced starting with version 0.4.0. This aims to facilitate the development of automation tools around the APIs you build within the Metatype ecosystem.","date":"2024-05-09T00:00:00.000Z","tags":[],"readingTime":3.405,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Python on WebAssembly: How?","permalink":"/blog/2024/08/26/python-on-webassembly"},"nextItem":{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility"}},"content":"import SDKTabs from \\"@site/src/components/SDKTabs\\";\\nimport TabItem from \\"@theme/TabItem\\";\\nimport UpgradePythonSDK from \\"../../shared/upgrade/python-sdk.mdx\\";\\nimport UpgradeTsSDK from \\"../../shared/upgrade/typescript-sdk.mdx\\";\\n\\n\\nA new approach to deploying typegraphs has been introduced starting with version 0.4.0. This aims to facilitate the development of automation tools around the APIs you build within the Metatype ecosystem.\\n\\n## What has changed?\\n\\nBefore v0.4.x, we had to entirely rely on the [meta cli](/docs/reference/meta-cli) to deploy typegraphs to a typegate instance.\\n\\nThis is no longer the case, as all core logic has been moved to the TypeScript/Python typegraph SDKs, both of which share the same WebAssembly-based **typegraph-core** behind the scenes. This provides some degree of assurance that you will have nearly identical experiences with each SDK.\\n\\n## What are the use-cases?\\n\\nSince typegraphs can be written using the programming language your preferred SDK is based on, you can dynamically create typegraphs with ease.\\n\\nThe missing piece was having an interface natively backed inside the SDK for doing deployment programmatically.\\n\\n### Programmatic deployment\\n\\n### Initial setup\\n\\nJust like any other dependency in your favorite programming language, each SDKs can be installed with your favorite package manager.\\n\\nYou can use one of the commands below to get started with the latest available version.\\n\\n\\n \\n \\n \\n \\n \\n \\n\\n\\n#### Configuration\\n\\nThis is analoguous to the yaml configuration file when you are using [meta cli](/docs/reference/meta-cli).\\n\\nIt\'s the place where you tell which typegate you want to deploy to, how you want the artifacts to be resolved, among other settings.\\n\\n\\n \\n\\n```python\\nconfig: TypegraphDeployParams = TypegraphDeployParams(\\n typegate=TypegateConnectionOptions(url=\\"\\", auth=BasicAuth(\\"\\", \\"\\")),\\n typegraph_path=os.path.join(cwd, \\"path-to-typegraph\\"),\\n prefix=\\"\\",\\n secrets={},\\n migrations_dir=path.join(\\"prisma-migrations\\", example.name),\\n migration_actions=None,\\n default_migration_action=MigrationAction(\\n apply=True,\\n reset=True, # allow destructive migrations\\n create=True,\\n ),\\n )\\n```\\n\\n \\n \\n\\n```typescript\\nconst config = {\\n typegate: {\\n url: \\"\\",\\n auth: new BasicAuth(\\"\\", \\"\\"),\\n },\\n typegraphPath: path.join(cwd, \\"path-to-typegraph.ts\\"),\\n prefix: \\"\\",\\n secrets: { POSTGRES: \\"\\" },\\n migrationsDir: path.join(\\"prisma-migrations\\", tg.name),\\n defaultMigrationAction: {\\n create: true,\\n reset: true, // allow destructive migrations\\n },\\n};\\n```\\n\\n \\n\\n\\n\\n### Deploy/remove\\n\\nNow, picture this, you have a lot of typegraphs and one or more typegate instance(s) running, you can easily make small scripts that does any specific job you want.\\n\\n```typescript\\n// ..\\nimport { tgDeploy, tgRemove } from \\"@typegraph/sdk/tg_deploy.js\\";\\n// ..\\n\\nconst BASIC_AUTH = loadMyAuthsFromSomeSource();\\nconst TYPEGATE_URL = \\"...\\";\\n\\nexport async function getTypegraphs() {\\n // Suppose we have these typegraphs..\\n // Let\'s enumerate them like this to simplify\\n return [\\n {\\n tg: await import(\\"path/to/shop-finances\\"),\\n location: \\"path/to/shop-finances.ts\\",\\n },\\n {\\n tg: await import(\\"path/to/shop-stats\\"),\\n location: \\"path/to/shop-stats.ts\\",\\n },\\n ];\\n}\\n\\nexport function getConfig(tgName: string, tgLocation: string) {\\n // Note: You can always develop various ways of constructing the configuration,\\n // like loading it from a file.\\n return {\\n typegate: {\\n url: \\"\\",\\n auth: new BasicAuth(\\"\\", \\"\\"),\\n },\\n typegraphPath: path.join(cwd, \\"path-to-typegraph.ts\\"),\\n prefix: \\"\\",\\n secrets: { POSTGRES: \\"\\" },\\n migrationsDir: path.join(\\"prisma-migrations\\", tg.name),\\n defaultMigrationAction: {\\n create: true,\\n reset: true, // allow destructive migrations\\n },\\n };\\n}\\n\\nexport async function deployAll() {\\n const typegraphs = await getTypegraphs();\\n for (const { tg, location } of typegraphs) {\\n try {\\n const config = getConfig(tg.name, location);\\n // use tgDeploy to deploy typegraphs, it will contain the response from typegate\\n const { typegate } = await tgDeploy(tg, config);\\n const selection = typegate?.data?.addTypegraph;\\n if (selection) {\\n const { messages } = selection;\\n console.log(messages.map(({ text }) => text).join(\\"\\\\n\\"));\\n } else {\\n throw new Error(JSON.stringify(typegate));\\n }\\n } catch (e) {\\n console.error(\\"[!] Failed deploying\\", tg.name);\\n console.error(e);\\n }\\n }\\n}\\n\\nexport async function undeployAll() {\\n const typegraphs = await getTypegraphs();\\n for (const { tg } of typegraphs) {\\n try {\\n // use tgRemove to remove typegraphs\\n const { typegate } = await tgRemove(\\"\\", {\\n baseUrl: TYPEGATE_URL,\\n auth: BASIC_AUTH,\\n });\\n console.log(typegate);\\n } catch (e) {\\n console.error(\\"Failed removing\\", tg.name);\\n console.error(e);\\n }\\n }\\n}\\n```\\n\\n### Going beyond\\n\\nWith these new additions, you can automate virtually anything programmatically on the typegraph side. Starting from having highly dynamic APIs to providing ways to deploy and configure them, you can even build a custom framework around the ecosystem!\\n\\nPlease tell us what you think and report any issues you found on [Github](https://github.com/metatypedev/metatype/issues).\\n\\n:::info Notes\\n\\nYou can check the [Programmatic deployment](/docs/guides/programmatic-deployment) reference page for more information.\\n\\n:::"},{"id":"/2023/11/27/node-compatibility","metadata":{"permalink":"/blog/2023/11/27/node-compatibility","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-11-27-node-compatibility/index.mdx","source":"@site/blog/2023-11-27-node-compatibility/index.mdx","title":"The Node/Deno SDK is now available","description":"We are happy to announce that we have redesigned our SDKs to support Node/Deno and facilitate the integration of future languages. Most of the typegraph SDK is now written in Rust and shaped around a core interface running in WebAssembly.","date":"2023-11-27T00:00:00.000Z","tags":[],"readingTime":1.7,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Programmatic deployment (v0.4.x)","permalink":"/blog/2024/05/09/programmatic-deployment"},"nextItem":{"title":"Programmable glue for developers","permalink":"/blog/2023/06/18/programmable-glue"}},"content":"We are happy to announce that we have redesigned our SDKs to support Node/Deno and facilitate the integration of future languages. Most of the [typegraph SDK](/docs/reference/typegraph) is now written in Rust and shaped around a core interface running in WebAssembly.\\n\\n## Meet `wit`\\n\\nIn the realm of WebAssembly, the [wit-bindgen](https://github.com/bytecodealliance/wit-bindgen) project emerges as the most mature tool to create and maintain the language bindings for WebAssembly modules. This tool introduces WIT (WebAssembly Interface Types) as an Interface Definition Language (IDL) to describe the imports, exports, and capabilities of WebAssembly components seamlessly.\\n\\nFor example, Metatype implements the reactor pattern to handle requests as they come and delegate part of their execution in correct WASM runtime. The wit-bindgen helps there to define the interfaces between the guest (the Metatype runtime) and the host (the typegate) to ensure the correct serialization of the payloads. The `wit` definition could look like this:\\n\\n```\\npackage metatype:wit-wire;\\n\\ninterface typegate-wire {\\n hostcall: func(op-name: string, json: string) -> result;\\n}\\n\\ninterface mat-wire {\\n record handle-req {\\n op-name: string,\\n in-json: string,\\n }\\n\\n handle: func(req: handle-req) -> result;\\n}\\n\\nworld wit-wire {\\n import typegate-wire;\\n\\n export mat-wire;\\n}\\n```\\n\\nThe `wit` file is then used to generate the bindings for the host and the guest in Rust, TypeScript, Python, and other languages. The host bindings are used in the typegate to call the WASM runtime, and the guest bindings are used in the WASM runtime to call the typegate.\\n\\n## Install the v0.2.x series\\n\\nThe documentation contains now examples for Node and Deno.\\n\\n### Upgrade with Node\\n\\n```bash\\nnpm install @typegraph/sdk\\nmeta new --template node .\\n```\\n\\n### Upgrade with Deno\\n\\n```bash\\nmeta new --template deno .\\n```\\n\\n```typescript\\nimport { typegraph } from \\"npm:@typegraph/sdk/index.js\\";\\n```\\n\\n### Upgrade with Python\\n\\n```python\\npip3 install --upgrade typegraph\\npoetry add typegraph@latest\\n```\\n\\n## Give us feedback!\\n\\nThis new release enables us to provide a consistent experience across all languages and reduce the work to maintain the existing Python SDK.\\n\\nAs always, report issues and let us know what you think on [GitHub](https://github.com/metatypedev/metatype/discussions)."},{"id":"/2023/06/18/programmable-glue","metadata":{"permalink":"/blog/2023/06/18/programmable-glue","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-06-18-programmable-glue/index.mdx","source":"@site/blog/2023-06-18-programmable-glue/index.mdx","title":"Programmable glue for developers","description":"We are introducing Metatype, a new project that allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.","date":"2023-06-18T00:00:00.000Z","tags":[],"readingTime":1.295,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"The Node/Deno SDK is now available","permalink":"/blog/2023/11/27/node-compatibility"},"nextItem":{"title":"Emulating your server nodes locally","permalink":"/blog/2023/03/15/emulating-servers"}},"content":"import { CompareLandscape } from \\"@site/src/components/CompareLandscape\\";\\nimport Metatype from \\"@site/shared/metatype-intro.mdx\\";\\nimport TGExample from \\"@site/src/components/TGExample\\";\\n\\n\\nWe are introducing Metatype, a new project that allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.\\n\\n## What is Metatype?\\n\\n\\n\\n## What are virtual graphs?\\n\\nTypegraphs are a declarative way to expose all APIs, storage and business logic of your stack as a single graph. They take inspiration from domain-driven design principles and in the idea that the relation between of the data is as important as data itself, even though they might be in different locations or shapes.\\n\\n\\n\\nThese elements can then be combined and composed together similarly on how you would compose web components to create an interface in modern frontend practices. This allows developers to build modular and strongly typed APIs using typegraph as a programmable glue.\\n\\n## Where does this belong in the tech landscape?\\n\\nBefore Metatype, there was a gap in the technological landscape for a solution that specifically addressed the transactional, short-lived use cases. While there were existing tools for analytical or long-running use cases, such as Trino and Temporal, there was no generic engine for handling transactional, short-lived tasks.\\n\\n \\n\\n## Give it a try!\\n\\nLet us know what you think! Metatype is open source and we welcome any feedback or contributions. The community primarily lives on [GitHub](https://github.com/metatypedev/metatype).\\n\\n:::info Next steps\\n\\n[Build your first typegraph](/docs/tutorials/metatype-basics) or read more about the [concepts behind Metatype](/docs/concepts/mental-model).\\n\\n:::"},{"id":"/2023/03/15/emulating-servers","metadata":{"permalink":"/blog/2023/03/15/emulating-servers","editUrl":"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2023-03-15-emulating-servers/index.mdx","source":"@site/blog/2023-03-15-emulating-servers/index.mdx","title":"Emulating your server nodes locally","description":"Introducing the Embedded Typegate","date":"2023-03-15T00:00:00.000Z","tags":[],"readingTime":3.07,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"unlisted":false,"prevItem":{"title":"Programmable glue for developers","permalink":"/blog/2023/06/18/programmable-glue"}},"content":"import BlogIntro from \\"@site/src/components/BlogIntro\\";\\nimport UpgradeMetatype from \\"../../shared/upgrade/index.mdx\\";\\n\\n\\n\\n\\n## Introducing the Embedded Typegate\\n\\nThe embedded typegate is a feature that comes with the [Meta CLI](/docs/reference/meta-cli) which provides the option of spinning a typegate instance from the CLI with minimum configurations and installations needed from the developer. All that is required to access the _Embedded Typegate_ is to install _Meta CLI_. The spawned typegate instance behaves similarly to cloud-deployed typegates.\\n\\n## The motive\\n\\nThere are more than a couple of reasons why a developer would be tempted to use an emedded typegate. While developers can start a typegate instance using docker compose, the developer needs to install docker as a dependency to run the typegate container. Even though docker is familiar among many developers, it can sometimes be tricky and unbeknownst to some developers. We at metatype highly value the developer experience and one reason for adding the _embedded typegate_ feature to the _Meta CLI_ is for users to have a smooth experience with our system by providing a docker compose free experience.\\nThis feature provides a great utility for developers to author and test typegraphs in their local machine before deploying them to production level typegate instances on the cloud.\\nAdditionally, developers need not concern themselves with deployment configurations which are needed only during deployment. The only need to focus their energy and time in developing the right application and easily test them on _embedded typegate_ running from the terminal. To add more to what is said, as the typegate engine keeps evolving, users will be abstracted away from the different configurations which might be added on the future. The _Meta CLI_ will abstract much of what\'s not needed in a dev environment. Thus, leaving less headaches to developers on new changes.\\nUltimately, The _embedded typegate_ is designed to be a good dev environment friendly tool which faciliates development time.\\n\\n## Quick First hand example\\n\\n### Install the v0.3.x series\\n\\nEither of the two [Typegraph](/docs/reference/typegraph) SDKs are needed to author typegraphs. For this example, the node SDK will be used.\\n\\nFirst, make sure the _Meta CLI_ is installed.\\n\\n```shell\\ncurl -fsSL https://raw.githubusercontent.com/metatypedev/metatype/main/installer.sh | bash\\n```\\n\\nNext, create a new node project using this command.\\n\\n```shell\\nmeta new --template node\\n```\\n\\nThe above command will create a sample typegraph which you can use to test the embedded typegate.\\n\\nNow, you need to install the typegraph SDK by running the command down below. The previous command generates a `package.json` with the SDK specified as a dependency.\\n\\n```shell\\nnpm install\\n```\\n\\nBefore deploying the typegraph to the embedded typegate, Run the following commands below.\\n\\n```shell\\nmeta dev\\n```\\n\\nNow that there is running instance of a typegate, you can deploy the example typegraph. From another terminal, run the command below.\\n\\n```shell\\nmeta deploy -f api/example.ts --allow-dirty --create-migration --target dev --gate http://localhost:7890\\n```\\n\\nThe typegate runs on port 7890 by default. If you access [http://localhost:7890/example](http://localhost:7890/example) on your browser, you can see an GraphQL interface to interact with the deployed typegraph. You can test the example typegraph using the following graphql query below.\\n\\n```graphql\\nquery {\\n multilpy(first: 3, second: 5)\\n}\\n```\\n\\n\\n\\n## Learn more about Metatype\\n\\nWanna dive deep into the basics of _Metaype_? check our interactive [tutorial](/docs/tutorials/metatype-basics) revolving around the core features of the system."}]}}')}}]); \ No newline at end of file diff --git a/assets/js/fbf1744f.b0e8818b.js b/assets/js/fbf1744f.b0e8818b.js new file mode 100644 index 0000000000..7b12106d39 --- /dev/null +++ b/assets/js/fbf1744f.b0e8818b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[6959],{77275:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>p,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var i=n(86070),r=n(25710);const s={},o="Introducing gRPC Runtime",a={permalink:"/blog/2024/09/26/introducing-grpc-runtime",editUrl:"https://github.com/metatypedev/metatype/tree/main/docs/metatype.dev/blog/2024-09-26-introducing-grpc-runtime/index.mdx",source:"@site/blog/2024-09-26-introducing-grpc-runtime/index.mdx",title:"Introducing gRPC Runtime",description:"We're excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform's ability to create versatile and powerful backends through typegraphs.",date:"2024-09-26T00:00:00.000Z",tags:[],readingTime:4.4,hasTruncateMarker:!1,authors:[],frontMatter:{},unlisted:!1,nextItem:{title:"Distributed execution flow paradigms",permalink:"/blog/2024/08/27/distributed-execution-flow-paradigms"}},l={authorsImageUrls:[]},c=[{value:"What is gRPC?",id:"what-is-grpc",level:2},{value:"Why gRPC Matters for Metatype",id:"why-grpc-matters-for-metatype",level:2},{value:"Diagram: gRPC and Metatype Integration",id:"diagram-grpc-and-metatype-integration",level:2},{value:"Introducing gRPC Runtime in Metatype",id:"introducing-grpc-runtime-in-metatype",level:2},{value:"Key Technical Details",id:"key-technical-details",level:2},{value:"Architecture",id:"architecture",level:3},{value:"Implementation",id:"implementation",level:3},{value:"Benefits for Developers",id:"benefits-for-developers",level:2},{value:"Getting Started",id:"getting-started",level:2},{value:"Conclusion",id:"conclusion",level:2}];function h(e){const t={a:"a",code:"code",em:"em",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(t.p,{children:"We're excited to announce the new gRPC Runtime feature in Metatype, further enhancing our platform's ability to create versatile and powerful backends through typegraphs."}),"\n",(0,i.jsx)(t.h2,{id:"what-is-grpc",children:"What is gRPC?"}),"\n",(0,i.jsxs)(t.p,{children:["gRPC, or ",(0,i.jsx)(t.strong,{children:"g"}),"oogle ",(0,i.jsx)(t.strong,{children:"R"}),"emote ",(0,i.jsx)(t.strong,{children:"P"}),"rocedure ",(0,i.jsx)(t.strong,{children:"C"}),"all, is a high-performance, open-source communication framework initially developed by Google. It enables ",(0,i.jsx)(t.strong,{children:"efficient and fast communication between microservices"})," in a distributed system, making it ideal for modern backend architectures."]}),"\n",(0,i.jsxs)(t.p,{children:["Unlike traditional HTTP APIs that use JSON, gRPC relies on ",(0,i.jsx)(t.strong,{children:"Protocol Buffers"})," (protobufs) for serializing data, which are more compact and faster to process. This approach allows gRPC to support high-throughput, low-latency communication, which is crucial for applications where speed and efficiency matter, such as in real-time data processing or large-scale distributed systems."]}),"\n",(0,i.jsx)(t.p,{children:"Key benefits of gRPC include:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Cross-language support"}),": gRPC supports multiple programming languages, allowing services written in different languages to communicate seamlessly."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Strong type safety"}),": Protocol Buffers ensure type-safe communication, catching errors early and improving reliability."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Bidirectional streaming"}),": gRPC allows for client and server streaming, enabling continuous data transfer in both directions, ideal for applications like real-time analytics."]}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"In short, gRPC is well-suited for high-performance, scalable backend systems where speed and type safety are essential."}),"\n",(0,i.jsx)(t.h2,{id:"why-grpc-matters-for-metatype",children:"Why gRPC Matters for Metatype"}),"\n",(0,i.jsxs)(t.p,{children:["Metatype is a platform that enables developers to create ",(0,i.jsx)(t.strong,{children:"typegraphs"}),"\u2014strongly-typed, composable backend structures that can support multiple protocols and runtime environments. With the introduction of the gRPC Runtime, Metatype allows developers to incorporate gRPC services into these typegraphs, further enhancing the platform\u2019s versatility."]}),"\n",(0,i.jsx)(t.p,{children:"By integrating gRPC, Metatype empowers developers to:"}),"\n",(0,i.jsxs)(t.ul,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Expose gRPC services via GraphQL or HTTP endpoints"}),", making them accessible to clients in a way that best suits their needs."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Compose gRPC services with other backend components"}),", such as databases or other APIs, to create powerful and cohesive backend systems."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"diagram-grpc-and-metatype-integration",children:"Diagram: gRPC and Metatype Integration"}),"\n",(0,i.jsx)("center",{children:(0,i.jsx)(t.p,{children:(0,i.jsx)(t.img,{alt:"gRPC and Metatype Integration Diagram",src:n(15602).A+"",width:"161",height:"681"})})}),"\n",(0,i.jsx)(t.p,{children:(0,i.jsx)(t.em,{children:"Metatype\u2019s gRPC Runtime allows developers to integrate gRPC services into their typegraphs, enabling seamless interaction with gRPC services in the backend."})}),"\n",(0,i.jsx)(t.h2,{id:"introducing-grpc-runtime-in-metatype",children:"Introducing gRPC Runtime in Metatype"}),"\n",(0,i.jsx)(t.p,{children:"The new gRPC Runtime is the latest addition to Metatype's suite of runtimes, joining existing options like the HTTP runtime. This expansion allows you to incorporate gRPC services into your typegraphs, further enhancing the versatility of your Metatype-powered backends."}),"\n",(0,i.jsx)(t.h2,{id:"key-technical-details",children:"Key Technical Details"}),"\n",(0,i.jsx)(t.h3,{id:"architecture",children:"Architecture"}),"\n",(0,i.jsx)(t.p,{children:"The gRPC Runtime integrates seamlessly with Metatype's existing architecture. It acts as a bridge between your typegraph and external gRPC services, allowing you to incorporate gRPC calls alongside other runtime operations in your backend logic."}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"GrpcRuntime Class"}),": The main interface for defining gRPC interactions within your typegraph."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"proto_file"}),": Path to the .proto file that defines the gRPC service."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"endpoint"}),": The gRPC server address in the format ",(0,i.jsx)(t.code,{children:"tcp://:"}),"."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"call method"}),": Creates a typegraph function for gRPC method calls."]}),"\n"]}),"\n",(0,i.jsx)(t.h3,{id:"implementation",children:"Implementation"}),"\n",(0,i.jsx)(t.p,{children:"Here's how the gRPC Runtime fits into a Metatype typegraph:"}),"\n",(0,i.jsx)(t.pre,{children:(0,i.jsx)(t.code,{className:"language-python",children:'from typegraph import Graph, Policy, typegraph\nfrom typegraph.graph.params import Cors\nfrom typegraph.runtimes.grpc import GrpcRuntime\n\n@typegraph(\n cors=Cors(allow_origin=["https://metatype.dev", "http://localhost:3000"]),\n)\ndef create_grpc_typegraph(g: Graph):\n # The GrpcRuntime acts as a bridge between your typegraph and external gRPC services\n grpc_runtime = GrpcRuntime(\n # proto_file: Path to the .proto file that defines the gRPC service\n proto_file="proto/helloworld.proto",\n # endpoint: The gRPC server address in the format tcp://:\n endpoint="tcp://localhost:4770"\n )\n \n # Expose the gRPC service within your typegraph\n # This allows you to incorporate gRPC calls alongside other runtime operations\n g.expose(\n Policy.public(),\n # call method: Creates a typegraph function for gRPC method calls\n # It uses the full path to the gRPC method: /package_name.service_name/method_name\n greet=grpc_runtime.call("/helloworld.Greeter/SayHello"),\n )\n\n# The typegraph can now be exposed via GraphQL or HTTP, \n# allowing clients to interact with the gRPC service through Metatype\'s unified interface\n'})}),"\n",(0,i.jsx)(t.p,{children:"This implementation demonstrates how the gRPC Runtime integrates with your typegraph, allowing you to:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Define gRPC service connections using the GrpcRuntime class"}),"\n",(0,i.jsx)(t.li,{children:"Expose gRPC methods as part of your typegraph"}),"\n",(0,i.jsx)(t.li,{children:"Combine gRPC functionality with other Metatype features and runtimes"}),"\n"]}),"\n",(0,i.jsx)(t.p,{children:"By structuring your gRPC interactions this way, you can seamlessly incorporate gRPC services into your larger Metatype-powered backend, alongside other data sources and business logic."}),"\n",(0,i.jsx)(t.h2,{id:"benefits-for-developers",children:"Benefits for Developers"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Unified Backend Structure"}),": Incorporate gRPC services alongside other protocols and data sources in a single, coherent typegraph."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Type Safety"}),": Leverage Metatype's strong typing system in conjunction with gRPC's protocol buffers for end-to-end type safety."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Flexible Exposure"}),": Easily expose your gRPC services via GraphQL or HTTP endpoints, allowing clients to interact with them using their preferred protocol."]}),"\n",(0,i.jsxs)(t.li,{children:[(0,i.jsx)(t.strong,{children:"Composability"}),": Combine gRPC calls with other runtime operations, database queries, or business logic within your typegraph."]}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,i.jsx)(t.p,{children:"To start using the gRPC Runtime in your Metatype project:"}),"\n",(0,i.jsxs)(t.ol,{children:["\n",(0,i.jsx)(t.li,{children:"Ensure you have the latest version of Metatype installed."}),"\n",(0,i.jsx)(t.li,{children:"Prepare your .proto files for the gRPC services you want to integrate."}),"\n",(0,i.jsx)(t.li,{children:"Set up your typegraph as shown in the example above, incorporating the GrpcRuntime."}),"\n",(0,i.jsx)(t.li,{children:"Configure your Metatype backend to expose the typegraph via GraphQL or HTTP as needed."}),"\n"]}),"\n",(0,i.jsx)(t.h2,{id:"conclusion",children:"Conclusion"}),"\n",(0,i.jsx)(t.p,{children:"The addition of the gRPC Runtime to Metatype further solidifies its position as a comprehensive platform for building robust, type-safe backends. By allowing seamless integration of gRPC services alongside other protocols and data sources, Metatype empowers developers to create versatile and powerful backend systems with ease."}),"\n",(0,i.jsxs)(t.p,{children:["For more detailed documentation, code examples, and best practices, check out our ",(0,i.jsx)(t.a,{href:"https://metatype.dev/docs",children:"official Metatype docs"}),"#."]})]})}function p(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,i.jsx)(t,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},15602:(e,t,n)=>{n.d(t,{A:()=>i});const i=n.p+"assets/images/GrpcMetatype.drawio-e6e626affae448f5b44a48ab82805ee9.png"}}]); \ No newline at end of file diff --git a/assets/js/main.48955abc.js b/assets/js/main.48955abc.js deleted file mode 100644 index 2beb3d4bf4..0000000000 --- a/assets/js/main.48955abc.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.48955abc.js.LICENSE.txt */ -(self.webpackChunkwebsite=self.webpackChunkwebsite||[]).push([[8792],{45433:(e,t,n)=>{var r={"./":46532};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=45433},68384:(e,t,n)=>{"use strict";n.d(t,{A:()=>p});n(30758);var r=n(57316),o=n.n(r),a=n(84054);const i={"058898d2":[()=>n.e(8595).then(n.t.bind(n,50568,19)),"@generated/docusaurus-plugin-content-docs/use-cases/p/use-cases-fc6.json",50568],"05cbd4da":[()=>Promise.all([n.e(1869),n.e(2076),n.e(9568)]).then(n.bind(n,17981)),"@site/docs/reference/runtimes/kv/index.mdx",17981],"062e3798":[()=>Promise.all([n.e(2076),n.e(2311)]).then(n.bind(n,66578)),"@site/docs/guides/self-hosting.md",66578],"068acb3c":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8789)]).then(n.bind(n,31281)),"@site/blog/2023-06-18-programmable-glue/index.mdx?truncated=true",31281],"0c88aa32":[()=>Promise.all([n.e(1869),n.e(2076),n.e(1201)]).then(n.bind(n,88079)),"@site/docs/reference/typegate/authentication/index.mdx",88079],"10a64d3a":[()=>Promise.all([n.e(2076),n.e(8977)]).then(n.bind(n,68234)),"@site/docs/concepts/comparisons/index.mdx",68234],"127f5bd6":[()=>Promise.all([n.e(2076),n.e(3610)]).then(n.bind(n,13543)),"@site/blog/2024-08-26-python-on-webassembly/index.mdx?truncated=true",13543],"16d8d440":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7330)]).then(n.bind(n,90079)),"@site/docs/reference/types/parameter-transformations.mdx",90079],17896441:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4145),n.e(8401)]).then(n.bind(n,75936)),"@theme/DocItem",75936],"18b50fbb":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7401)]).then(n.bind(n,42684)),"@site/docs/reference/runtimes/s3/index.mdx",42684],"1d6f08a2":[()=>Promise.all([n.e(2076),n.e(8461)]).then(n.bind(n,95370)),"@site/docs/concepts/RFCs/index.mdx",95370],"1df93b7f":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8271),n.e(4583)]).then(n.bind(n,26175)),"@site/src/pages/index.tsx",26175],"1f391b9e":[()=>Promise.all([n.e(1869),n.e(2076),n.e(4145),n.e(6061)]).then(n.bind(n,43685)),"@theme/MDXPage",43685],"1f54f6f7":[()=>Promise.all([n.e(1869),n.e(2076),n.e(4404)]).then(n.bind(n,43053)),"@site/docs/guides/external-functions/index.mdx",43053],"26137cf5":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7050)]).then(n.bind(n,52897)),"@site/docs/guides/files-upload/index.mdx",52897],"289ade6e":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7525)]).then(n.bind(n,92809)),"@site/use-cases/programmable-api-gateway/index.mdx",92809],"295b9a18":[()=>Promise.all([n.e(2076),n.e(3052)]).then(n.bind(n,18668)),"@site/docs/reference/meta-cli/available-commands.mdx",18668],"2df24393":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8598)]).then(n.bind(n,77162)),"@site/docs/reference/policies/index.mdx",77162],"2fbc816e":[()=>Promise.all([n.e(2076),n.e(3680)]).then(n.bind(n,31940)),"@site/docs/concepts/RFCs/M0-template.mdx",31940],"3169f45d":[()=>Promise.all([n.e(1869),n.e(2076),n.e(3597)]).then(n.bind(n,16678)),"@site/docs/reference/runtimes/http/index.mdx",16678],"32f95329":[()=>n.e(7956).then(n.t.bind(n,93279,19)),"@generated/docusaurus-plugin-content-docs/use-cases/__plugin.json",93279],"33e4627d":[()=>Promise.all([n.e(1869),n.e(2076),n.e(2731)]).then(n.bind(n,62719)),"@site/use-cases/graphql-server/index.mdx",62719],"3f66bcd5":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7868)]).then(n.bind(n,34801)),"@site/docs/reference/runtimes/graphql/index.mdx",34801],"42ecd3be":[()=>Promise.all([n.e(1869),n.e(2076),n.e(2829)]).then(n.bind(n,23233)),"@site/docs/guides/securing-requests/index.mdx",23233],"474845f3":[()=>Promise.all([n.e(1869),n.e(2076),n.e(5364)]).then(n.bind(n,16086)),"@site/docs/reference/runtimes/deno/index.mdx",16086],"49f06b57":[()=>n.e(912).then(n.t.bind(n,82028,19)),"~blog/blog/blogMetadata-blog.json",82028],"4ab57ea6":[()=>Promise.all([n.e(1869),n.e(2076),n.e(96)]).then(n.bind(n,88570)),"@site/docs/reference/meta-cli/index.mdx",88570],"4b100ba1":[()=>n.e(6838).then(n.t.bind(n,54415,19)),"@generated/docusaurus-plugin-content-docs/docs/__plugin.json",54415],"4edc808e":[()=>Promise.all([n.e(1869),n.e(2076),n.e(308)]).then(n.bind(n,39223)),"@site/docs/index.mdx",39223],"4f68146b":[()=>Promise.all([n.e(1869),n.e(2076),n.e(1732)]).then(n.bind(n,53919)),"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx?truncated=true",53919],"5360c792":[()=>Promise.all([n.e(2076),n.e(986)]).then(n.bind(n,73519)),"@site/docs/reference/runtimes/index.mdx",73519],"5622ed62":[()=>Promise.all([n.e(2076),n.e(7417)]).then(n.bind(n,36037)),"@site/blog/2023-11-27-node-compatibility/index.mdx?truncated=true",36037],"56e37303":[()=>Promise.all([n.e(1869),n.e(2076),n.e(2903)]).then(n.bind(n,68962)),"@site/docs/reference/typegraph/client/index.mdx",68962],"5a33aa61":[()=>Promise.all([n.e(2076),n.e(4902)]).then(n.bind(n,99848)),"@site/docs/reference/runtimes/python/index.mdx",99848],"5e023c59":[()=>Promise.all([n.e(1869),n.e(2076),n.e(2091)]).then(n.bind(n,2738)),"@site/docs/reference/rest/index.mdx",2738],"5e95c892":[()=>n.e(9647).then(n.bind(n,77704)),"@theme/DocsRoot",77704],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,4784)),"@generated/docusaurus.config",4784],"6baad3d0":[()=>Promise.all([n.e(1869),n.e(2076),n.e(7010)]).then(n.bind(n,51092)),"@site/use-cases/automatic-crud-validation/index.mdx",51092],"6c4588a6":[()=>Promise.all([n.e(1869),n.e(2076),n.e(6686)]).then(n.bind(n,49447)),"@site/docs/tutorials/quick-start/index.mdx",49447],"6c5c337a":[()=>Promise.all([n.e(2076),n.e(2280)]).then(n.bind(n,2597)),"@site/blog/2024-08-26-python-on-webassembly/index.mdx",2597],"6dc80b66":[()=>Promise.all([n.e(1869),n.e(2076),n.e(6650)]).then(n.bind(n,87409)),"@site/docs/guides/import-external-modules/index.mdx",87409],"6e544dd5":[()=>Promise.all([n.e(1869),n.e(2076),n.e(3126)]).then(n.bind(n,2845)),"@site/blog/2024-08-27-distributed-execution-flow-paradigms/index.mdx",2845],"6f622e55":[()=>Promise.all([n.e(2076),n.e(2606)]).then(n.bind(n,36233)),"@site/docs/reference/typegate/index.mdx",36233],"80eba989":[()=>Promise.all([n.e(1869),n.e(2076),n.e(6101)]).then(n.bind(n,21153)),"@site/blog/2023-03-15-emulating-servers/index.mdx",21153],"878e8ee7":[()=>n.e(6800).then(n.t.bind(n,49362,19)),"@generated/docusaurus-plugin-content-docs/docs/p/docs-175.json",49362],"8cfb3d68":[()=>Promise.all([n.e(1869),n.e(2076),n.e(3599)]).then(n.bind(n,37214)),"@site/docs/concepts/features-overview/index.mdx",37214],"929c1f2b":[()=>Promise.all([n.e(1869),n.e(2076),n.e(619)]).then(n.bind(n,68642)),"@site/docs/reference/runtimes/prisma/index.mdx",68642],"95183ce9":[()=>Promise.all([n.e(1869),n.e(2076),n.e(6574)]).then(n.bind(n,28350)),"@site/docs/guides/programmatic-deployment/index.mdx",28350],"95b96bb9":[()=>n.e(6405).then(n.t.bind(n,7057,19)),"~blog/blog/blog-post-list-prop-blog.json",7057],"97787cbd":[()=>n.e(1922).then(n.t.bind(n,63961,19)),"@generated/docusaurus-plugin-content-blog/blog/p/blog-bd9.json",63961],"98537bc7":[()=>Promise.all([n.e(1869),n.e(2076),n.e(4877)]).then(n.bind(n,77031)),"@site/docs/concepts/mental-model/index.mdx",77031],"99c4cb86":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8237)]).then(n.bind(n,68305)),"@site/use-cases/iam-provider/index.mdx",68305],"9cca6528":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8102)]).then(n.bind(n,67076)),"@site/blog/2024-05-09-programmatic-deployment/index.mdx?truncated=true",67076],"9d3370bc":[()=>Promise.all([n.e(1869),n.e(2076),n.e(9594)]).then(n.bind(n,49079)),"@site/docs/reference/types/index.mdx",49079],"9e4087bc":[()=>n.e(2711).then(n.bind(n,95028)),"@theme/BlogArchivePage",95028],"9ef5846e":[()=>Promise.all([n.e(1869),n.e(2076),n.e(8097)]).then(n.bind(n,39615)),"@site/blog/2023-06-18-programmable-glue/index.mdx",39615],"9f09fab9":[()=>Promise.all([n.e(2076),n.e(9835)]).then(n.bind(n,99481)),"@site/docs/concepts/architecture/index.mdx",99481],a0248338:[()=>Promise.all([n.e(1869),n.e(2076),n.e(5028)]).then(n.bind(n,3894)),"@site/docs/guides/rest/index.mdx",3894],a4f64869:[()=>Promise.all([n.e(1869),n.e(2076),n.e(1723)]).then(n.bind(n,33454)),"@site/docs/reference/runtimes/substantial/index.mdx",33454],a6aa9e1f:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4145),n.e(8860),n.e(7643)]).then(n.bind(n,42938)),"@theme/BlogListPage",42938],a70287ac:[()=>Promise.all([n.e(2076),n.e(2058)]).then(n.bind(n,77487)),"@site/docs/reference/changelog.mdx",77487],a7456010:[()=>n.e(1235).then(n.t.bind(n,88552,19)),"@generated/docusaurus-plugin-content-pages/default/__plugin.json",88552],a7bd4aaa:[()=>n.e(7098).then(n.bind(n,35861)),"@theme/DocVersionRoot",35861],a94703ab:[()=>Promise.all([n.e(1869),n.e(9048)]).then(n.bind(n,7173)),"@theme/DocRoot",7173],aac7f9f5:[()=>Promise.all([n.e(2076),n.e(1995)]).then(n.bind(n,94508)),"@site/docs/guides/contributing.mdx",94508],aafba6b7:[()=>Promise.all([n.e(2076),n.e(681)]).then(n.bind(n,42321)),"@site/docs/reference/meta-cli/configuration-file.mdx",42321],ac075c54:[()=>Promise.all([n.e(1869),n.e(2076),n.e(3855)]).then(n.bind(n,12728)),"@site/blog/2024-05-09-programmatic-deployment/index.mdx",12728],ad20ab3b:[()=>Promise.all([n.e(2076),n.e(3916)]).then(n.bind(n,11040)),"@site/docs/reference/ecosystem/index.mdx",11040],ad5e0346:[()=>Promise.all([n.e(1869),n.e(2076),n.e(11)]).then(n.bind(n,95459)),"@site/docs/tutorials/metatype-basics/index.mdx",95459],af072c69:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4039)]).then(n.bind(n,31285)),"@site/use-cases/backend-for-frontend/index.mdx",31285],b3219b4c:[()=>n.e(3099).then(n.t.bind(n,83890,19)),"@generated/docusaurus-plugin-content-blog/blog/p/blog-archive-f05.json",83890],b8f4db82:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4619)]).then(n.bind(n,96996)),"@site/docs/reference/runtimes/temporal/index.mdx",96996],bbc54dbf:[()=>Promise.all([n.e(1869),n.e(2076),n.e(2427)]).then(n.bind(n,10148)),"@site/use-cases/orm-for-the-edge/index.mdx",10148],c02ff0d2:[()=>Promise.all([n.e(1869),n.e(2076),n.e(5190)]).then(n.bind(n,78294)),"@site/docs/reference/runtimes/wasm/index.mdx",78294],c1c441c4:[()=>Promise.all([n.e(2076),n.e(8958)]).then(n.bind(n,12)),"@site/docs/reference/types/functions.mdx",12],c2bbfad4:[()=>Promise.all([n.e(2076),n.e(8103)]).then(n.bind(n,29836)),"@site/docs/reference/types/comparison.mdx",29836],c367b882:[()=>Promise.all([n.e(1869),n.e(2076),n.e(7100)]).then(n.bind(n,66922)),"@site/docs/reference/runtimes/grpc/index.mdx",66922],c523e930:[()=>Promise.all([n.e(2076),n.e(6941)]).then(n.bind(n,88156)),"@site/docs/reference/typegate/synchronization/index.mdx",88156],c843538e:[()=>Promise.all([n.e(1869),n.e(2076),n.e(2384)]).then(n.bind(n,15404)),"@site/use-cases/faas-runner/index.mdx",15404],ccc49370:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4145),n.e(8860),n.e(3249)]).then(n.bind(n,57440)),"@theme/BlogPostPage",57440],cd86e9b3:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4947)]).then(n.bind(n,98143)),"@site/docs/reference/metagen/index.mdx",98143],cda5b2c7:[()=>Promise.all([n.e(1869),n.e(2076),n.e(9742)]).then(n.bind(n,75431)),"@site/use-cases/microservice-orchestration/index.mdx",75431],d2f8c7b3:[()=>Promise.all([n.e(2076),n.e(5140)]).then(n.bind(n,95411)),"@site/blog/2023-11-27-node-compatibility/index.mdx",95411],d89a9c00:[()=>Promise.all([n.e(1869),n.e(2076),n.e(5253)]).then(n.bind(n,24331)),"@site/docs/reference/typegate/cors/index.mdx",24331],d8f8b671:[()=>Promise.all([n.e(1869),n.e(2076),n.e(8349)]).then(n.bind(n,37860)),"@site/docs/reference/typegate/rate-limiting/index.mdx",37860],da9cdc83:[()=>Promise.all([n.e(1869),n.e(2076),n.e(2378)]).then(n.bind(n,18224)),"@site/blog/2023-03-15-emulating-servers/index.mdx?truncated=true",18224],dce22fdb:[()=>Promise.all([n.e(2076),n.e(8343)]).then(n.bind(n,90707)),"@site/src/pages/legal/terms.md",90707],e1da19f3:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4191)]).then(n.bind(n,48372)),"@site/docs/guides/wasm-functions/index.mdx",48372],e3ef7410:[()=>Promise.all([n.e(1869),n.e(2076),n.e(9164)]).then(n.bind(n,22004)),"@site/docs/reference/typegraph/index.mdx",22004],e66bdb87:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4591)]).then(n.bind(n,4391)),"@site/docs/reference/runtimes/random/index.mdx",4391],e8113c3c:[()=>Promise.all([n.e(2076),n.e(2254)]).then(n.bind(n,46127)),"@site/src/pages/legal/privacy-policy.md",46127],eb6f68a0:[()=>Promise.all([n.e(2076),n.e(4991)]).then(n.bind(n,38189)),"@site/docs/reference/meta-cli/embedded-typegate/index.mdx",38189],efb264ae:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4834)]).then(n.bind(n,97649)),"@site/docs/reference/types/injections.mdx",97649],f1c506b7:[()=>n.e(2467).then(n.t.bind(n,6737,19)),"@generated/docusaurus-plugin-content-blog/blog/__plugin.json",6737],fd15d584:[()=>Promise.all([n.e(1869),n.e(2076),n.e(4762)]).then(n.bind(n,55303)),"@site/docs/guides/test-your-typegraph/index.mdx",55303]};var s=n(86070);function l(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,s.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,s.jsx)("p",{children:String(t)}),(0,s.jsx)("div",{children:(0,s.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,s.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,s.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,s.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,s.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,s.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,s.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,s.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(7771),u=n(17832);function d(e,t){if("*"===e)return o()({loading:l,loader:()=>n.e(2940).then(n.bind(n,32940)),modules:["@theme/NotFound"],webpack:()=>[32940],render(e,t){const n=e.default;return(0,s.jsx)(u.W,{value:{plugin:{name:"native",id:"default"}},children:(0,s.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},p=[],f=[],h=(0,c.A)(r);return Object.entries(h).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],p.push(r[1]),f.push(r[2]))})),o().Map({loading:l,loader:d,modules:p,webpack:()=>f,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const s=n.split(".");s.slice(0,-1).forEach((e=>{i=i[e]})),i[s[s.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;delete o.__context;const l=o.__props;return delete o.__props,(0,s.jsx)(u.W,{value:i,children:(0,s.jsx)(a,{...o,...l,...n})})}})}const p=[{path:"/blog",component:d("/blog","b71"),exact:!0},{path:"/blog/2023/03/15/emulating-servers",component:d("/blog/2023/03/15/emulating-servers","0e6"),exact:!0},{path:"/blog/2023/06/18/programmable-glue",component:d("/blog/2023/06/18/programmable-glue","3bd"),exact:!0},{path:"/blog/2023/11/27/node-compatibility",component:d("/blog/2023/11/27/node-compatibility","b09"),exact:!0},{path:"/blog/2024/05/09/programmatic-deployment",component:d("/blog/2024/05/09/programmatic-deployment","c79"),exact:!0},{path:"/blog/2024/08/26/python-on-webassembly",component:d("/blog/2024/08/26/python-on-webassembly","d29"),exact:!0},{path:"/blog/2024/08/27/distributed-execution-flow-paradigms",component:d("/blog/2024/08/27/distributed-execution-flow-paradigms","ca6"),exact:!0},{path:"/blog/archive",component:d("/blog/archive","d1d"),exact:!0},{path:"/legal/privacy-policy",component:d("/legal/privacy-policy","4fe"),exact:!0},{path:"/legal/terms",component:d("/legal/terms","aed"),exact:!0},{path:"/docs",component:d("/docs","153"),routes:[{path:"/docs",component:d("/docs","509"),routes:[{path:"/docs",component:d("/docs","dc3"),routes:[{path:"/docs",component:d("/docs","e81"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/architecture",component:d("/docs/concepts/architecture","5a3"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/comparisons",component:d("/docs/concepts/comparisons","c09"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/features-overview",component:d("/docs/concepts/features-overview","196"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/mental-model",component:d("/docs/concepts/mental-model","0a9"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/RFCs",component:d("/docs/concepts/RFCs","301"),exact:!0,sidebar:"docs"},{path:"/docs/concepts/RFCs/M0-template",component:d("/docs/concepts/RFCs/M0-template","c4e"),exact:!0,sidebar:"docs"},{path:"/docs/guides/contributing",component:d("/docs/guides/contributing","39f"),exact:!0,sidebar:"docs"},{path:"/docs/guides/external-functions",component:d("/docs/guides/external-functions","bde"),exact:!0,sidebar:"docs"},{path:"/docs/guides/files-upload",component:d("/docs/guides/files-upload","0b9"),exact:!0,sidebar:"docs"},{path:"/docs/guides/import-external-modules",component:d("/docs/guides/import-external-modules","495"),exact:!0,sidebar:"docs"},{path:"/docs/guides/programmatic-deployment",component:d("/docs/guides/programmatic-deployment","0b9"),exact:!0,sidebar:"docs"},{path:"/docs/guides/rest",component:d("/docs/guides/rest","433"),exact:!0,sidebar:"docs"},{path:"/docs/guides/securing-requests",component:d("/docs/guides/securing-requests","86e"),exact:!0,sidebar:"docs"},{path:"/docs/guides/self-hosting",component:d("/docs/guides/self-hosting","f2f"),exact:!0,sidebar:"docs"},{path:"/docs/guides/test-your-typegraph",component:d("/docs/guides/test-your-typegraph","abf"),exact:!0,sidebar:"docs"},{path:"/docs/guides/wasm-functions",component:d("/docs/guides/wasm-functions","c76"),exact:!0,sidebar:"docs"},{path:"/docs/reference/changelog",component:d("/docs/reference/changelog","783"),exact:!0,sidebar:"docs"},{path:"/docs/reference/ecosystem",component:d("/docs/reference/ecosystem","343"),exact:!0,sidebar:"docs"},{path:"/docs/reference/meta-cli",component:d("/docs/reference/meta-cli","b6c"),exact:!0,sidebar:"docs"},{path:"/docs/reference/meta-cli/available-commands",component:d("/docs/reference/meta-cli/available-commands","a05"),exact:!0,sidebar:"docs"},{path:"/docs/reference/meta-cli/configuration-file",component:d("/docs/reference/meta-cli/configuration-file","549"),exact:!0,sidebar:"docs"},{path:"/docs/reference/meta-cli/embedded-typegate",component:d("/docs/reference/meta-cli/embedded-typegate","86d"),exact:!0,sidebar:"docs"},{path:"/docs/reference/metagen",component:d("/docs/reference/metagen","293"),exact:!0,sidebar:"docs"},{path:"/docs/reference/policies",component:d("/docs/reference/policies","113"),exact:!0,sidebar:"docs"},{path:"/docs/reference/rest",component:d("/docs/reference/rest","870"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes",component:d("/docs/reference/runtimes","86b"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/deno",component:d("/docs/reference/runtimes/deno","7ef"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/graphql",component:d("/docs/reference/runtimes/graphql","cfd"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/grpc",component:d("/docs/reference/runtimes/grpc","dae"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/http",component:d("/docs/reference/runtimes/http","d1d"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/kv",component:d("/docs/reference/runtimes/kv","927"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/prisma",component:d("/docs/reference/runtimes/prisma","637"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/python",component:d("/docs/reference/runtimes/python","c7a"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/random",component:d("/docs/reference/runtimes/random","a6c"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/s3",component:d("/docs/reference/runtimes/s3","5f4"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/substantial",component:d("/docs/reference/runtimes/substantial","a9d"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/temporal",component:d("/docs/reference/runtimes/temporal","0d3"),exact:!0,sidebar:"docs"},{path:"/docs/reference/runtimes/wasm",component:d("/docs/reference/runtimes/wasm","b3e"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegate",component:d("/docs/reference/typegate","1fd"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegate/authentication",component:d("/docs/reference/typegate/authentication","e71"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegate/cors",component:d("/docs/reference/typegate/cors","a93"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegate/rate-limiting",component:d("/docs/reference/typegate/rate-limiting","5b3"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegate/synchronization",component:d("/docs/reference/typegate/synchronization","de4"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegraph",component:d("/docs/reference/typegraph","6d7"),exact:!0,sidebar:"docs"},{path:"/docs/reference/typegraph/client",component:d("/docs/reference/typegraph/client","4cb"),exact:!0,sidebar:"docs"},{path:"/docs/reference/types",component:d("/docs/reference/types","eb9"),exact:!0,sidebar:"docs"},{path:"/docs/reference/types/comparison",component:d("/docs/reference/types/comparison","67a"),exact:!0,sidebar:"docs"},{path:"/docs/reference/types/functions",component:d("/docs/reference/types/functions","ee1"),exact:!0,sidebar:"docs"},{path:"/docs/reference/types/injections",component:d("/docs/reference/types/injections","5c1"),exact:!0,sidebar:"docs"},{path:"/docs/reference/types/parameter-transformations",component:d("/docs/reference/types/parameter-transformations","8e5"),exact:!0,sidebar:"docs"},{path:"/docs/tutorials/metatype-basics",component:d("/docs/tutorials/metatype-basics","35a"),exact:!0,sidebar:"docs"},{path:"/docs/tutorials/quick-start",component:d("/docs/tutorials/quick-start","1ba"),exact:!0,sidebar:"docs"}]}]}]},{path:"/use-cases",component:d("/use-cases","922"),routes:[{path:"/use-cases",component:d("/use-cases","4f9"),routes:[{path:"/use-cases",component:d("/use-cases","e5c"),routes:[{path:"/use-cases/automatic-crud-validation",component:d("/use-cases/automatic-crud-validation","da8"),exact:!0,sidebar:"useCases"},{path:"/use-cases/backend-for-frontend",component:d("/use-cases/backend-for-frontend","9b1"),exact:!0,sidebar:"useCases"},{path:"/use-cases/faas-runner",component:d("/use-cases/faas-runner","cfd"),exact:!0,sidebar:"useCases"},{path:"/use-cases/graphql-server",component:d("/use-cases/graphql-server","68c"),exact:!0,sidebar:"useCases"},{path:"/use-cases/iam-provider",component:d("/use-cases/iam-provider","940"),exact:!0,sidebar:"useCases"},{path:"/use-cases/microservice-orchestration",component:d("/use-cases/microservice-orchestration","c6e"),exact:!0,sidebar:"useCases"},{path:"/use-cases/orm-for-the-edge",component:d("/use-cases/orm-for-the-edge","e3f"),exact:!0,sidebar:"useCases"},{path:"/use-cases/programmable-api-gateway",component:d("/use-cases/programmable-api-gateway","a64"),exact:!0,sidebar:"useCases"}]}]}]},{path:"/",component:d("/","e5f"),exact:!0},{path:"*",component:d("*")}]},95143:(e,t,n)=>{"use strict";n.d(t,{o:()=>a,x:()=>i});var r=n(30758),o=n(86070);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},7881:(e,t,n)=>{"use strict";var r=n(30758),o=n(99576),a=n(70248),i=n(41742),l=n(4784),c=n(25283);const u=[n(94127),n(16636),n(58493),n(96213),n(98222)];var d=n(68384),p=n(25557),f=n(70389),h={561:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getAttributes=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:["id","class","length"],n=e.attributes;return[].concat(function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t-1||e.push("["+n.nodeName+'="'+n.value+'"]'),e}),[])}},770:(e,t)=>{function n(e){if(!e.hasAttribute("class"))return[];try{return Array.prototype.slice.call(e.classList).filter((function(e){return/^[a-z_-][a-z\d_-]*$/i.test(e)?e:null}))}catch(n){var t=e.getAttribute("class");return(t=t.trim().replace(/\s+/g," ")).split(" ")}}Object.defineProperty(t,"__esModule",{value:!0}),t.getClasses=n,t.getClassSelectors=function(e){return n(e).filter(Boolean).map((function(e){return"."+e}))}},584:(e,t)=>{function n(e,t,r,o,a,i,s){if(i!==s)for(var l=o;l<=a&&a-l+1>=s-i;++l)r[i]=t[l],n(e,t,r,l+1,a,i+1,s);else e.push(r.slice(0,i).join(""))}Object.defineProperty(t,"__esModule",{value:!0}),t.getCombinations=function(e,t){for(var r=[],o=e.length,a=[],i=1;i<=t;++i)n(r,e,a,0,o-1,0,i);return r}},169:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getID=function(e){var t=e.getAttribute("id");return null!==t&&""!==t?t.match(/(?:^\d|:)/)?'[id="'+t+'"]':"#"+t:null}},64:(e,t,n)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getNthChild=function(e){var t=0,n=void 0,o=void 0,a=e.parentNode;if(Boolean(a)){var i=a.childNodes,s=i.length;for(n=0;n{Object.defineProperty(t,"__esModule",{value:!0}),t.getParents=function(e){for(var t=[],n=e;(0,r.isElement)(n);)t.push(n),n=n.parentNode;return t};var r=n(440)},970:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.getTag=function(e){return e.tagName.toLowerCase().replace(/:/g,"\\:")}},924:(e,t,n)=>{t.A=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=t.selectorTypes,r=void 0===n?["ID","Class","Tag","NthChild"]:n,o=t.attributesToIgnore,a=void 0===o?["id","class","length"]:o,i=t.excludeRegex,s=void 0===i?null:i,l=[],d=(0,u.getParents)(e),p=!0,f=!1,m=void 0;try{for(var g,v=d[Symbol.iterator]();!(p=(g=v.next()).done);p=!0){var y=h(g.value,r,a,s);Boolean(y)&&l.push(y)}}catch(L){f=!0,m=L}finally{try{!p&&v.return&&v.return()}finally{if(f)throw m}}var b=[],w=!0,x=!1,k=void 0;try{for(var S,C=l[Symbol.iterator]();!(w=(S=C.next()).done);w=!0){var E=S.value;b.unshift(E);var T=b.join(" > ");if((0,c.isUnique)(e,T))return T}}catch(L){x=!0,k=L}finally{try{!w&&C.return&&C.return()}finally{if(x)throw k}}return null};var r=n(169),o=n(770),a=n(584),i=n(561),s=n(64),l=n(970),c=n(213),u=n(175);function d(e,t){var n=e.parentNode.querySelectorAll(t);return 1===n.length&&n[0]===e}function p(e,t){return t.find(d.bind(null,e))}function f(e,t,n){var r=(0,a.getCombinations)(t,3),o=p(e,r);return Boolean(o)||Boolean(n)&&(o=p(e,r=r.map((function(e){return n+e}))),Boolean(o))?o:null}function h(e,t,n,a){var c=void 0,u=function(e,t,n){var a={Tag:l.getTag,NthChild:s.getNthChild,Attributes:function(e){return(0,i.getAttributes)(e,n)},Class:o.getClassSelectors,ID:r.getID};return t.reduce((function(t,n){return t[n]=a[n](e),t}),{})}(e,t,n);a&&a instanceof RegExp&&(u.ID=a.test(u.ID)?null:u.ID,u.Class=u.Class.filter((function(e){return!a.test(e)})));var p=!0,h=!1,m=void 0;try{for(var g,v=t[Symbol.iterator]();!(p=(g=v.next()).done);p=!0){var y=g.value,b=u.ID,w=u.Tag,x=u.Class,k=u.Attributes,S=u.NthChild;switch(y){case"ID":if(Boolean(b)&&d(e,b))return b;break;case"Tag":if(Boolean(w)&&d(e,w))return w;break;case"Class":if(Boolean(x)&&x.length&&(c=f(e,x,w)))return c;break;case"Attributes":if(Boolean(k)&&k.length&&(c=f(e,k,w)))return c;break;case"NthChild":if(Boolean(S))return S}}}catch(C){h=!0,m=C}finally{try{!p&&v.return&&v.return()}finally{if(h)throw m}}return"*"}},440:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0});var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e};t.isElement=function(e){return"object"===("undefined"==typeof HTMLElement?"undefined":n(HTMLElement))?e instanceof HTMLElement:!!e&&"object"===(void 0===e?"undefined":n(e))&&1===e.nodeType&&"string"==typeof e.nodeName}},213:(e,t)=>{Object.defineProperty(t,"__esModule",{value:!0}),t.isUnique=function(e,t){if(!Boolean(t))return!1;var n=e.ownerDocument.querySelectorAll(t);return 1===n.length&&n[0]===e}}},m={};function g(e){var t=m[e];if(void 0!==t)return t.exports;var n=m[e]={exports:{}};return h[e](n,n.exports,g),n.exports}g.d=(e,t)=>{for(var n in t)g.o(t,n)&&!g.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},g.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t);var v={};(()=>{function e(t){return(e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e})(t)}function t(e,t){for(var n=0;nvo});var o=function(){function e(){!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),n(this,"feedbackButton",null),n(this,"injectedFeedbackButton",!1),n(this,"buttonHidden",null),n(this,"lastButtonIcon",null)}var r,o,a;return r=e,a=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],(o=[{key:"toggleFeedbackButton",value:function(t){this.buttonHidden=!t,e.getInstance().updateFeedbackButtonState(),ur.getInstance().updateContainerStyle()}},{key:"feedbackButtonPressed",value:function(){var e=It.getInstance();e.isOpened()?e.hideWidget():(e.setAppMode("widget"),e.showWidget())}},{key:"injectFeedbackButton",value:function(){var e=this;if(!this.injectedFeedbackButton){this.injectedFeedbackButton=!0;var t=document.createElement("div");t.addEventListener("click",(function(){e.feedbackButtonPressed()})),document.body.appendChild(t),this.feedbackButton=t,this.updateFeedbackButtonState()}}},{key:"updateNotificationBadge",value:function(e){var t=document.querySelector(".bb-notification-bubble");if(t){var n="bb-notification-bubble--hidden";e>0?(t.classList.remove(n),t.innerText=e):t.classList.add(n)}}},{key:"refresh",value:function(){document.querySelector(".bb-feedback-button")?(this.updateFeedbackButtonText(),this.updateFeedbackButtonState()):(this.injectedFeedbackButton=!1,this.feedbackButton=null,this.buttonHidden=null,this.lastButtonIcon=null,this.injectFeedbackButton())}},{key:"updateFeedbackButtonText",value:function(){var t=Qe.getInstance().getFlowConfig();if(t.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC||t.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC_BOTTOM||t.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC_LEFT){var n=document.querySelector(".bb-feedback-button-classic");n&&(n.innerText=t.widgetButtonText)}}},{key:"updateFeedbackButtonState",value:function(){if(null!==this.feedbackButton){var t,n=Qe.getInstance().getFlowConfig();t=n.buttonLogo?''):u("button","#fff"),this.feedbackButton.className="bb-feedback-button gleap-font gl-block",this.feedbackButton.setAttribute("dir",Zn.getInstance().isRTLLayout?"rtl":"ltr"),n.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC||n.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC_BOTTOM||n.feedbackButtonPosition===e.FEEDBACK_BUTTON_CLASSIC_LEFT?(this.feedbackButton.classList.add("bb-feedback-button--classic-button-style"),this.feedbackButton.innerHTML='
').concat(n.widgetButtonText,"
")):t!==this.lastButtonIcon&&(this.feedbackButton.innerHTML='
'.concat(t).concat(u("arrowdown","#fff"),'
')),this.lastButtonIcon=t;var r=!1;null===e.getInstance().buttonHidden?n.feedbackButtonPosition===e.FEEDBACK_BUTTON_NONE&&(r=!0):e.getInstance().buttonHidden&&(r=!0),r&&this.feedbackButton.classList.add("bb-feedback-button--disabled"),n.feedbackButtonPosition===e.FEEDBACK_BUTTON_BOTTOM_LEFT&&this.feedbackButton.classList.add("bb-feedback-button--bottomleft"),It.getInstance().isOpened()&&this.feedbackButton.classList.add("bb-feedback-button--open");var o=It.getInstance().appMode;"survey"!==o&&"survey_full"!==o&&"survey_web"!==o||this.feedbackButton.classList.add("bb-feedback-button--survey"),!0!==n.hideForGuests||qe.getInstance().isUser()||this.feedbackButton.classList.add("bb-feedback-button--hidden")}}}])&&t(r.prototype,o),a&&t(r,a),Object.defineProperty(r,"prototype",{writable:!1}),e}();function a(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,s=[],l=!0,c=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);l=!0);}catch(e){c=!0,o=e}finally{try{if(!l&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(c)throw o}}return s}}(e,t)||function(e,t){if(e){if("string"==typeof e)return i(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?i(e,t):void 0}}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function i(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n=160?"#000000":"#ffffff"},u=function(e,t){return"button"===e?'':"unmute"===e?'':"mute"===e?'':"replay"===e?'\n \n ':"dismiss"===e?'':"blur"===e?'\n \n':"pen"===e?'\n \n \n \n \n \n \n \n \n \n \n \n \n':"rect"===e?'\n \n \n \n \n \n \n \n \n \n \n':"pointer"===e?'\n \n ':"clip"===e?'\n \n \n \n \n \n':"mic"===e?'\n \n \n \n \n ':"camera"===e?'\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n':"recorderon"===e?'\n \n \n \n \n \n \n \n \n \n \n \n':"recorderoff"===e?'\n \n \n \n \n \n \n \n \n ':"arrowdown"===e?'\n \n '):"arrowleft"===e?'\n \n '):"close"===e?'\n \n '):"undo"===e?'\n \n \n \n \n \n \n \n \n \n ':"circle-dot"===e?''):"circle-question"===e?''):"circle-info"===e?''):"circle-exclamation"===e?''):"circle-up"===e?''):"circle-right"===e?''):""};function d(e){return d="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},d(e)}function p(e,t){for(var n=0;n0&&(e=e.concat(this.externalRequests)),this.filters&&this.filters.length>0)for(var t=0;t-1)&&!e.find((function(e){return e.url===c.name}))&&e.push({type:"RESOURCE",date:new Date(this.startTimestamp+c.startTime),url:c.name,duration:Math.round(c.duration),initiatorType:c.initiatorType})}}}catch(l){}var u=this.blacklist.concat(this.defaultBlacklist);if(u&&u.length>0)try{e=e.filter((function(e){for(var t=0;t70&&(e=70),this.maxRequests=e}},{key:"setStopped",value:function(e){this.stopped=e}},{key:"setFilters",value:function(e){this.filters=this.filters.concat(e||[])}},{key:"setBlacklist",value:function(e){this.blacklist=this.blacklist.concat(e||[])}},{key:"cleanRequests",value:function(){var e=Object.keys(this.requests);if(e.length>this.maxRequests)for(var t=e.slice(0,e.length-this.maxRequests),n=0;n.15?"":e}},{key:"cleanupPayload",value:function(e){if(null==e)return"{}";try{if(void 0!==("undefined"==typeof TextDecoder?"undefined":d(TextDecoder))&&ArrayBuffer.isView(e))return(new TextDecoder).decode(e)}catch(t){}return e}},{key:"preparePayload",value:function(e){var t=this.cleanupPayload(e);return this.cleanupContentSize(t)}},{key:"start",value:function(){var e=this;if(!this.initialized){this.initialized=!0;var t=this;this.interceptNetworkRequests({onFetch:function(n,r){if(!e.stopped&&r&&e.requests){if(n.length>0&&void 0!==n[0]&&void 0!==n[0].url)e.requests[r]={url:n[0].url,date:new Date,request:{payload:"",headers:void 0!==n[0].headers?Object.fromEntries(n[0].headers.entries()):{}},type:void 0!==n[0].method?n[0].method:""};else if(n.length>=2&&n[1]){var o=n[1]&&n[1].method?n[1].method:"GET";e.requests[r]={request:{payload:t.preparePayload(n[1].body),headers:n[1].headers},type:o,url:n[0],date:new Date}}else e.requests[r]={url:n[0],date:new Date};e.cleanRequests()}},onFetchLoad:function(n,o){if(!e.stopped&&o&&e.requests&&e.requests[o]){try{e.requests[o].success=!0,e.requests[o].response={status:n.status,statusText:"",responseText:""},e.calcRequestTime(o)}catch(r){}try{var a="";n.headers&&void 0!==n.headers.get&&(a=n.headers.get("content-type")),e.isContentTypeSupported(a)?n.text().then((function(r){e.requests[o]&&(e.requests[o].success=!0,e.requests[o].response={status:n.status,statusText:n.statusText,responseText:t.cleanupContentSize(r)}),e.calcRequestTime(o),e.cleanRequests()})).catch((function(t){e.cleanRequests()})):(e.requests[o]&&(e.requests[o].success=!0,e.requests[o].response={status:n.status,statusText:n.statusText,responseText:""}),e.calcRequestTime(o),e.cleanRequests())}catch(r){}}},onFetchFailed:function(t,n){!e.stopped&&n&&e.requests&&e.requests[n]&&(e.requests[n].success=!1,e.calcRequestTime(n),e.cleanRequests())},onOpen:function(t,n){e.stopped||(t&&t.bbRequestId&&n.length>=2&&e.requests&&(e.requests[t.bbRequestId]={type:n[0],url:n[1],date:new Date}),e.cleanRequests())},onSend:function(t,n){e.stopped||(t&&t.bbRequestId&&e.requests&&e.requests[t.bbRequestId]&&(e.requests[t.bbRequestId].request={payload:e.preparePayload(n.length>0?n[0]:"{}"),headers:t.requestHeaders}),e.cleanRequests())},onError:function(t,n){!e.stopped&&e.requests&&t&&t.currentTarget&&t.currentTarget.bbRequestId&&e.requests[t.currentTarget.bbRequestId]&&(e.requests[t.currentTarget.bbRequestId].success=!1,e.calcRequestTime(t.bbRequestId)),e.cleanRequests()},onLoad:function(t,n){if(!e.stopped){if(t&&t.currentTarget&&t.currentTarget.bbRequestId&&e.requests&&e.requests[t.currentTarget.bbRequestId]){var r=t.currentTarget,o=r.responseType,a="<"+o+">";""!==o&&"text"!==o||(a=e.cleanupContentSize(r.responseText)),e.requests[r.bbRequestId].success=!0,e.requests[r.bbRequestId].response={status:r.status,statusText:r.statusText,responseText:a},e.calcRequestTime(r.bbRequestId)}e.cleanRequests()}}})}}},{key:"interceptNetworkRequests",value:function(e){var t,n=this,r=XMLHttpRequest.prototype.open,o=XMLHttpRequest.prototype.send;return void 0===XMLHttpRequest.prototype.gleapSetRequestHeader&&(XMLHttpRequest.prototype.gleapSetRequestHeader=XMLHttpRequest.prototype.setRequestHeader),XMLHttpRequest.prototype.gleapSetRequestHeader&&(XMLHttpRequest.prototype.setRequestHeader=function(e,t){this.requestHeaders||(this.requestHeaders={}),this.requestHeaders&&this.requestHeaders.hasOwnProperty(e)||(this.requestHeaders[e]||(this.requestHeaders[e]=[]),this.requestHeaders[e].push(t),this.gleapSetRequestHeader(e,t))}),XMLHttpRequest.prototype.open=function(){return this.bbRequestId=++n.requestId,e.onOpen&&e.onOpen(this,arguments),e.onLoad&&this.addEventListener("load",e.onLoad.bind(e)),e.onError&&this.addEventListener("error",e.onError.bind(e)),r.apply(this,arguments)},XMLHttpRequest.prototype.send=function(){return e.onSend&&e.onSend(this,arguments),o.apply(this,arguments)},window.fetch&&(t=window.fetch,window.fetch=function(){var r=++n.requestId;return e.onFetch(arguments,r),t.apply(this,arguments).then((function(t){if(t&&"function"==typeof t.clone){var n=t.clone();e.onFetchLoad(n,r)}return t})).catch((function(t){throw e.onFetchFailed(t,r),t}))}),e}},{key:"blobToTextPromise",value:function(e){return new Promise((function(t,n){var r=new FileReader;r.onload=function(e){e&&e.target&&e.target.result?t(e.target.result):n()},r.onerror=function(e){n(e)},r.readAsText(e)}))}}],o=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],n&&p(t.prototype,n),o&&p(t,o),Object.defineProperty(t,"prototype",{writable:!1}),e}();f(m,"instance",void 0);const y=m;var b=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:400,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:400;return new Promise((function(r,o){var a=0===e.indexOf("data:image/jpeg"),i=new Image;i.src=e,i.onerror=function(){o()},i.onload=function(){var e=document.createElement("canvas"),o=t,s=n;t>i.width/4&&(o=i.width/4),n>i.height/4&&(s=i.height/4);var l=i.width,c=i.height;l>c?l>o&&(c*=o/l,l=o):c>s&&(l*=s/c,c=s),e.width=l,e.height=c,e.getContext("2d").drawImage(i,0,0,l,c),r(a?e.toDataURL("image/jpeg",.7):e.toDataURL())}}))},w=function(){return!(!/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent)&&!/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(navigator.userAgent.substr(0,4)))},x=function(e){if("string"==typeof e||e instanceof String)try{return JSON.parse(e)}catch(t){return{}}return e},k=function(e,t){return e.length>t?e.slice(0,t)+"...":e},S=function(e){try{var t=e.split("."),r=!1,o=t[t.length-2];return"co"!==o&&"com"!==o&&"gv"!==o&&"ac"!==o&&"edu"!==o&&"gov"!==o&&"mil"!==o&&"net"!==o&&"org"!==o||(r=!0),(t=t.slice(r?-3:-2)).join(".")}catch(n){}return e},C=function(e){try{var t=localStorage.getItem("gleap-widget-".concat(e));if(t)return JSON.parse(t)}catch(g){}return null},E=function(e,t){var n="gleap-widget-".concat(e);if(t)try{localStorage.setItem(n,JSON.stringify(t))}catch(v){}else localStorage.removeItem(n)},T=function(e){"complete"===document.readyState||"loaded"===document.readyState||"interactive"===document.readyState?e():document.addEventListener("DOMContentLoaded",(function(){e()}))};const L=Math.min,I=Math.max,A=Math.round,O=Math.floor,_=e=>({x:e,y:e}),P={left:"right",right:"left",bottom:"top",top:"bottom"},M={start:"end",end:"start"};function R(e,t,n){return I(e,L(t,n))}function N(e,t){return"function"==typeof e?e(t):e}function j(e){return e.split("-")[0]}function D(e){return e.split("-")[1]}function F(e){return"x"===e?"y":"x"}function B(e){return"y"===e?"height":"width"}function z(e){return["top","bottom"].includes(j(e))?"y":"x"}function U(e){return F(z(e))}function q(e){return e.replace(/start|end/g,(e=>M[e]))}function H(e){return e.replace(/left|right|bottom|top/g,(e=>P[e]))}function W(e){return"number"!=typeof e?function(e){return{top:0,right:0,bottom:0,left:0,...e}}(e):{top:e,right:e,bottom:e,left:e}}function $(e){return{...e,top:e.y,left:e.x,right:e.x+e.width,bottom:e.y+e.height}}function G(e,t,n){let{reference:r,floating:o}=e;const a=z(t),i=U(t),s=B(i),l=j(t),c="y"===a,u=r.x+r.width/2-o.width/2,d=r.y+r.height/2-o.height/2,p=r[s]/2-o[s]/2;let f;switch(l){case"top":f={x:u,y:r.y-o.height};break;case"bottom":f={x:u,y:r.y+r.height};break;case"right":f={x:r.x+r.width,y:d};break;case"left":f={x:r.x-o.width,y:d};break;default:f={x:r.x,y:r.y}}switch(D(t)){case"start":f[i]-=p*(n&&c?-1:1);break;case"end":f[i]+=p*(n&&c?-1:1)}return f}async function V(e,t){var n;void 0===t&&(t={});const{x:r,y:o,platform:a,rects:i,elements:s,strategy:l}=e,{boundary:c="clippingAncestors",rootBoundary:u="viewport",elementContext:d="floating",altBoundary:p=!1,padding:f=0}=N(t,e),h=W(f),m=s[p?"floating"===d?"reference":"floating":d],g=$(await a.getClippingRect({element:null==(n=await(null==a.isElement?void 0:a.isElement(m)))||n?m:m.contextElement||await(null==a.getDocumentElement?void 0:a.getDocumentElement(s.floating)),boundary:c,rootBoundary:u,strategy:l})),v="floating"===d?{...i.floating,x:r,y:o}:i.reference,y=await(null==a.getOffsetParent?void 0:a.getOffsetParent(s.floating)),b=await(null==a.isElement?void 0:a.isElement(y))&&await(null==a.getScale?void 0:a.getScale(y))||{x:1,y:1},w=$(a.convertOffsetParentRelativeRectToViewportRelativeRect?await a.convertOffsetParentRelativeRectToViewportRelativeRect({elements:s,rect:v,offsetParent:y,strategy:l}):v);return{top:(g.top-w.top+h.top)/b.y,bottom:(w.bottom-g.bottom+h.bottom)/b.y,left:(g.left-w.left+h.left)/b.x,right:(w.right-g.right+h.right)/b.x}}const K=function(e){return void 0===e&&(e=0),{name:"offset",options:e,async fn(t){var n,r;const{x:o,y:a,placement:i,middlewareData:s}=t,l=await async function(e,t){const{placement:n,platform:r,elements:o}=e,a=await(null==r.isRTL?void 0:r.isRTL(o.floating)),i=j(n),s=D(n),l="y"===z(n),c=["left","top"].includes(i)?-1:1,u=a&&l?-1:1,d=N(t,e);let{mainAxis:p,crossAxis:f,alignmentAxis:h}="number"==typeof d?{mainAxis:d,crossAxis:0,alignmentAxis:null}:{mainAxis:0,crossAxis:0,alignmentAxis:null,...d};return s&&"number"==typeof h&&(f="end"===s?-1*h:h),l?{x:f*u,y:p*c}:{x:p*c,y:f*u}}(t,e);return i===(null==(n=s.offset)?void 0:n.placement)&&null!=(r=s.arrow)&&r.alignmentOffset?{}:{x:o+l.x,y:a+l.y,data:{...l,placement:i}}}}};function Z(e){return J(e)?(e.nodeName||"").toLowerCase():"#document"}function Y(e){var t;return(null==e||null==(t=e.ownerDocument)?void 0:t.defaultView)||window}function X(e){var t;return null==(t=(J(e)?e.ownerDocument:e.document)||window.document)?void 0:t.documentElement}function J(e){return e instanceof Node||e instanceof Y(e).Node}function Q(e){return e instanceof Element||e instanceof Y(e).Element}function ee(e){return e instanceof HTMLElement||e instanceof Y(e).HTMLElement}function te(e){return"undefined"!=typeof ShadowRoot&&(e instanceof ShadowRoot||e instanceof Y(e).ShadowRoot)}function ne(e){const{overflow:t,overflowX:n,overflowY:r,display:o}=se(e);return/auto|scroll|overlay|hidden|clip/.test(t+r+n)&&!["inline","contents"].includes(o)}function re(e){return["table","td","th"].includes(Z(e))}function oe(e){const t=ae(),n=se(e);return"none"!==n.transform||"none"!==n.perspective||!!n.containerType&&"normal"!==n.containerType||!t&&!!n.backdropFilter&&"none"!==n.backdropFilter||!t&&!!n.filter&&"none"!==n.filter||["transform","perspective","filter"].some((e=>(n.willChange||"").includes(e)))||["paint","layout","strict","content"].some((e=>(n.contain||"").includes(e)))}function ae(){return!("undefined"==typeof CSS||!CSS.supports)&&CSS.supports("-webkit-backdrop-filter","none")}function ie(e){return["html","body","#document"].includes(Z(e))}function se(e){return Y(e).getComputedStyle(e)}function le(e){return Q(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.pageXOffset,scrollTop:e.pageYOffset}}function ce(e){if("html"===Z(e))return e;const t=e.assignedSlot||e.parentNode||te(e)&&e.host||X(e);return te(t)?t.host:t}function ue(e){const t=ce(e);return ie(t)?e.ownerDocument?e.ownerDocument.body:e.body:ee(t)&&ne(t)?t:ue(t)}function de(e,t,n){var r;void 0===t&&(t=[]),void 0===n&&(n=!0);const o=ue(e),a=o===(null==(r=e.ownerDocument)?void 0:r.body),i=Y(o);return a?t.concat(i,i.visualViewport||[],ne(o)?o:[],i.frameElement&&n?de(i.frameElement):[]):t.concat(o,de(o,[],n))}function pe(e){const t=se(e);let n=parseFloat(t.width)||0,r=parseFloat(t.height)||0;const o=ee(e),a=o?e.offsetWidth:n,i=o?e.offsetHeight:r,s=A(n)!==a||A(r)!==i;return s&&(n=a,r=i),{width:n,height:r,$:s}}function fe(e){return Q(e)?e:e.contextElement}function he(e){const t=fe(e);if(!ee(t))return _(1);const n=t.getBoundingClientRect(),{width:r,height:o,$:a}=pe(t);let i=(a?A(n.width):n.width)/r,s=(a?A(n.height):n.height)/o;return i&&Number.isFinite(i)||(i=1),s&&Number.isFinite(s)||(s=1),{x:i,y:s}}const me=_(0);function ge(e){const t=Y(e);return ae()&&t.visualViewport?{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}:me}function ve(e,t,n,r){void 0===t&&(t=!1),void 0===n&&(n=!1);const o=e.getBoundingClientRect(),a=fe(e);let i=_(1);t&&(r?Q(r)&&(i=he(r)):i=he(e));const s=function(e,t,n){return void 0===t&&(t=!1),!(!n||t&&n!==Y(e))&&t}(a,n,r)?ge(a):_(0);let l=(o.left+s.x)/i.x,c=(o.top+s.y)/i.y,u=o.width/i.x,d=o.height/i.y;if(a){const e=Y(a),t=r&&Q(r)?Y(r):r;let n=e,o=n.frameElement;for(;o&&r&&t!==n;){const e=he(o),t=o.getBoundingClientRect(),r=se(o),a=t.left+(o.clientLeft+parseFloat(r.paddingLeft))*e.x,i=t.top+(o.clientTop+parseFloat(r.paddingTop))*e.y;l*=e.x,c*=e.y,u*=e.x,d*=e.y,l+=a,c+=i,n=Y(o),o=n.frameElement}}return $({width:u,height:d,x:l,y:c})}const ye=[":popover-open",":modal"];function be(e){return ye.some((t=>{try{return e.matches(t)}catch(g){return!1}}))}function we(e){return ve(X(e)).left+le(e).scrollLeft}function xe(e,t,n){let r;if("viewport"===t)r=function(e,t){const n=Y(e),r=X(e),o=n.visualViewport;let a=r.clientWidth,i=r.clientHeight,s=0,l=0;if(o){a=o.width,i=o.height;const e=ae();(!e||e&&"fixed"===t)&&(s=o.offsetLeft,l=o.offsetTop)}return{width:a,height:i,x:s,y:l}}(e,n);else if("document"===t)r=function(e){const t=X(e),n=le(e),r=e.ownerDocument.body,o=I(t.scrollWidth,t.clientWidth,r.scrollWidth,r.clientWidth),a=I(t.scrollHeight,t.clientHeight,r.scrollHeight,r.clientHeight);let i=-n.scrollLeft+we(e);const s=-n.scrollTop;return"rtl"===se(r).direction&&(i+=I(t.clientWidth,r.clientWidth)-o),{width:o,height:a,x:i,y:s}}(X(e));else if(Q(t))r=function(e,t){const n=ve(e,!0,"fixed"===t),r=n.top+e.clientTop,o=n.left+e.clientLeft,a=ee(e)?he(e):_(1);return{width:e.clientWidth*a.x,height:e.clientHeight*a.y,x:o*a.x,y:r*a.y}}(t,n);else{const n=ge(e);r={...t,x:t.x-n.x,y:t.y-n.y}}return $(r)}function ke(e,t){const n=ce(e);return!(n===t||!Q(n)||ie(n))&&("fixed"===se(n).position||ke(n,t))}function Se(e,t,n){const r=ee(t),o=X(t),a="fixed"===n,i=ve(e,!0,a,t);let s={scrollLeft:0,scrollTop:0};const l=_(0);if(r||!r&&!a)if(("body"!==Z(t)||ne(o))&&(s=le(t)),r){const e=ve(t,!0,a,t);l.x=e.x+t.clientLeft,l.y=e.y+t.clientTop}else o&&(l.x=we(o));return{x:i.left+s.scrollLeft-l.x,y:i.top+s.scrollTop-l.y,width:i.width,height:i.height}}function Ce(e,t){return ee(e)&&"fixed"!==se(e).position?t?t(e):e.offsetParent:null}function Ee(e,t){const n=Y(e);if(!ee(e)||be(e))return n;let r=Ce(e,t);for(;r&&re(r)&&"static"===se(r).position;)r=Ce(r,t);return r&&("html"===Z(r)||"body"===Z(r)&&"static"===se(r).position&&!oe(r))?n:r||function(e){let t=ce(e);for(;ee(t)&&!ie(t);){if(oe(t))return t;t=ce(t)}return null}(e)||n}const Te={convertOffsetParentRelativeRectToViewportRelativeRect:function(e){let{elements:t,rect:n,offsetParent:r,strategy:o}=e;const a="fixed"===o,i=X(r),s=!!t&&be(t.floating);if(r===i||s&&a)return n;let l={scrollLeft:0,scrollTop:0},c=_(1);const u=_(0),d=ee(r);if((d||!d&&!a)&&(("body"!==Z(r)||ne(i))&&(l=le(r)),ee(r))){const e=ve(r);c=he(r),u.x=e.x+r.clientLeft,u.y=e.y+r.clientTop}return{width:n.width*c.x,height:n.height*c.y,x:n.x*c.x-l.scrollLeft*c.x+u.x,y:n.y*c.y-l.scrollTop*c.y+u.y}},getDocumentElement:X,getClippingRect:function(e){let{element:t,boundary:n,rootBoundary:r,strategy:o}=e;const a=[..."clippingAncestors"===n?function(e,t){const n=t.get(e);if(n)return n;let r=de(e,[],!1).filter((e=>Q(e)&&"body"!==Z(e))),o=null;const a="fixed"===se(e).position;let i=a?ce(e):e;for(;Q(i)&&!ie(i);){const t=se(i),n=oe(i);n||"fixed"!==t.position||(o=null),(a?!n&&!o:!n&&"static"===t.position&&o&&["absolute","fixed"].includes(o.position)||ne(i)&&!n&&ke(e,i))?r=r.filter((e=>e!==i)):o=t,i=ce(i)}return t.set(e,r),r}(t,this._c):[].concat(n),r],i=a[0],s=a.reduce(((e,n)=>{const r=xe(t,n,o);return e.top=I(r.top,e.top),e.right=L(r.right,e.right),e.bottom=L(r.bottom,e.bottom),e.left=I(r.left,e.left),e}),xe(t,i,o));return{width:s.right-s.left,height:s.bottom-s.top,x:s.left,y:s.top}},getOffsetParent:Ee,getElementRects:async function(e){const t=this.getOffsetParent||Ee,n=this.getDimensions;return{reference:Se(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,...await n(e.floating)}}},getClientRects:function(e){return Array.from(e.getClientRects())},getDimensions:function(e){const{width:t,height:n}=pe(e);return{width:t,height:n}},getScale:he,isElement:Q,isRTL:function(e){return"rtl"===se(e).direction}};const Le=function(e){return void 0===e&&(e={}),{name:"shift",options:e,async fn(t){const{x:n,y:r,placement:o}=t,{mainAxis:a=!0,crossAxis:i=!1,limiter:s={fn:e=>{let{x:t,y:n}=e;return{x:t,y:n}}},...l}=N(e,t),c={x:n,y:r},u=await V(t,l),d=z(j(o)),p=F(d);let f=c[p],h=c[d];if(a){const e="y"===p?"bottom":"right";f=R(f+u["y"===p?"top":"left"],f,f-u[e])}if(i){const e="y"===d?"bottom":"right";h=R(h+u["y"===d?"top":"left"],h,h-u[e])}const m=s.fn({...t,[p]:f,[d]:h});return{...m,data:{x:m.x-n,y:m.y-r}}}}},Ie=function(e){return void 0===e&&(e={}),{name:"flip",options:e,async fn(t){var n,r;const{placement:o,middlewareData:a,rects:i,initialPlacement:s,platform:l,elements:c}=t,{mainAxis:u=!0,crossAxis:d=!0,fallbackPlacements:p,fallbackStrategy:f="bestFit",fallbackAxisSideDirection:h="none",flipAlignment:m=!0,...g}=N(e,t);if(null!=(n=a.arrow)&&n.alignmentOffset)return{};const v=j(o),y=j(s)===s,b=await(null==l.isRTL?void 0:l.isRTL(c.floating)),w=p||(y||!m?[H(s)]:function(e){const t=H(e);return[q(e),t,q(t)]}(s));p||"none"===h||w.push(...function(e,t,n,r){const o=D(e);let a=function(e,t,n){const r=["left","right"],o=["right","left"],a=["top","bottom"],i=["bottom","top"];switch(e){case"top":case"bottom":return n?t?o:r:t?r:o;case"left":case"right":return t?a:i;default:return[]}}(j(e),"start"===n,r);return o&&(a=a.map((e=>e+"-"+o)),t&&(a=a.concat(a.map(q)))),a}(s,m,h,b));const x=[s,...w],k=await V(t,g),S=[];let C=(null==(r=a.flip)?void 0:r.overflows)||[];if(u&&S.push(k[v]),d){const e=function(e,t,n){void 0===n&&(n=!1);const r=D(e),o=U(e),a=B(o);let i="x"===o?r===(n?"end":"start")?"right":"left":"start"===r?"bottom":"top";return t.reference[a]>t.floating[a]&&(i=H(i)),[i,H(i)]}(o,i,b);S.push(k[e[0]],k[e[1]])}if(C=[...C,{placement:o,overflows:S}],!S.every((e=>e<=0))){var E,T;const e=((null==(E=a.flip)?void 0:E.index)||0)+1,t=x[e];if(t)return{data:{index:e,overflows:C},reset:{placement:t}};let n=null==(T=C.filter((e=>e.overflows[0]<=0)).sort(((e,t)=>e.overflows[1]-t.overflows[1]))[0])?void 0:T.placement;if(!n)switch(f){case"bestFit":{var L;const e=null==(L=C.map((e=>[e.placement,e.overflows.filter((e=>e>0)).reduce(((e,t)=>e+t),0)])).sort(((e,t)=>e[1]-t[1]))[0])?void 0:L[0];e&&(n=e);break}case"initialPlacement":n=s}if(o!==n)return{reset:{placement:n}}}return{}}}},Ae=e=>({name:"arrow",options:e,async fn(t){const{x:n,y:r,placement:o,rects:a,platform:i,elements:s,middlewareData:l}=t,{element:c,padding:u=0}=N(e,t)||{};if(null==c)return{};const d=W(u),p={x:n,y:r},f=U(o),h=B(f),m=await i.getDimensions(c),g="y"===f,v=g?"top":"left",y=g?"bottom":"right",b=g?"clientHeight":"clientWidth",w=a.reference[h]+a.reference[f]-p[f]-a.floating[h],x=p[f]-a.reference[f],k=await(null==i.getOffsetParent?void 0:i.getOffsetParent(c));let S=k?k[b]:0;S&&await(null==i.isElement?void 0:i.isElement(k))||(S=s.floating[b]||a.floating[h]);const C=w/2-x/2,E=S/2-m[h]/2-1,T=L(d[v],E),I=L(d[y],E),A=T,O=S-m[h]-I,_=S/2-m[h]/2+C,P=R(A,_,O),M=!l.arrow&&null!=D(o)&&_!==P&&a.reference[h]/2-(_e.length)&&(t=e.length);for(var n=0,r=new Array(t);n'):""),a.appendChild(i),t.repositionHotspot(e,n),o=i,t.elementToTooltipMap.set(e,n)}else o=e;var s=t.createTooltip(o,n.html,n);t.elementToFloatingUIMap.set(e,s)}}})),Pe(this,"updateFilteredTooltips",(function(){t.filteredTooltips=t.getFilteredTooltips(),t.checkForTooltips()})),Pe(this,"getFilteredTooltips",(function(){if(!t.tooltips)return[];var e=window.location.href;return t.tooltips.filter((function(t){if(!t.page||0===t.page.length)return!0;var n=t.pageType,r=t.page;switch(n){case"is":return e===r;case"isnot":return e!==r;case"contains":return e.includes(r);case"notcontains":return!e.includes(r);case"startswith":return e.startsWith(r);case"endswith":return e.endsWith(r);default:return!1}}))})),Pe(this,"checkForTooltips",(function(){for(var e=0;e0&&this.filteredTooltips.forEach((function(n){n.selector&&e.matches(n.selector)&&t.linkTooltip(e,n)}))}},{key:"start",value:function(){var e=this,t=this;if(window){var n,r,o=(n=t.updateHotspotPositions.bind(t),r=null,function(){if(!r){var e=this,t=arguments;r=setTimeout((function(){n.call.apply(n,[e].concat(function(e){return function(e){if(Array.isArray(e))return Re(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Re(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Re(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(t))),r=null}),250)}});window.addEventListener("resize",o),this.observer=new MutationObserver((function(n){t.lastUrl!==window.location.href&&(t.lastUrl=window.location.href,t.filteredTooltips=t.getFilteredTooltips()),n.forEach((function(n){n.addedNodes.forEach((function(e){e.nodeType===Node.ELEMENT_NODE&&t.processNodeInsertion(e)})),n.removedNodes.forEach((function(t){if(t.nodeType===Node.ELEMENT_NODE&&e.elementToFloatingUIMap.has(t)){var n=e.elementToFloatingUIMap.get(t);n&&(n.tooltip&&n.tooltip.remove(),n.cleanup(),e.elementToFloatingUIMap.delete(t))}e.elementToTooltipMap.has(t)&&e.elementToTooltipMap.delete(t)}))}))})),this.observer.observe(document.body,{childList:!0,subtree:!0})}}},{key:"updateHotspotPositions",value:function(){var e=this;document.querySelectorAll("[data-gleap-tooltip-mode='hotspot']").forEach((function(t){var n=e.elementToTooltipMap.get(t);n&&e.repositionHotspot(t,n)}))}},{key:"createTooltip",value:function(e,t,n){var r=document.createElement("div");r.className="gleap-tooltip",r.innerHTML='
\n '.concat(t,'\n
\n \n \n \n
\n
'),document.body.appendChild(r);var o,a=r.querySelector(".gleap-tooltip-arrow"),i=function(e,t,n,r){void 0===r&&(r={});const{ancestorScroll:o=!0,ancestorResize:a=!0,elementResize:i="function"==typeof ResizeObserver,layoutShift:s="function"==typeof IntersectionObserver,animationFrame:l=!1}=r,c=fe(e),u=o||a?[...c?de(c):[],...de(t)]:[];u.forEach((e=>{o&&e.addEventListener("scroll",n,{passive:!0}),a&&e.addEventListener("resize",n)}));const d=c&&s?function(e,t){let n,r=null;const o=X(e);function a(){var e;clearTimeout(n),null==(e=r)||e.disconnect(),r=null}return function i(s,l){void 0===s&&(s=!1),void 0===l&&(l=1),a();const{left:c,top:u,width:d,height:p}=e.getBoundingClientRect();if(s||t(),!d||!p)return;const f={rootMargin:-O(u)+"px "+-O(o.clientWidth-(c+d))+"px "+-O(o.clientHeight-(u+p))+"px "+-O(c)+"px",threshold:I(0,L(1,l))||1};let m=!0;function g(e){const t=e[0].intersectionRatio;if(t!==l){if(!m)return i();t?i(!1,t):n=setTimeout((()=>{i(!1,1e-7)}),100)}m=!1}try{r=new IntersectionObserver(g,{...f,root:o.ownerDocument})}catch(h){r=new IntersectionObserver(g,f)}r.observe(e)}(!0),a}(c,n):null;let p,f=-1,m=null;i&&(m=new ResizeObserver((e=>{let[r]=e;r&&r.target===c&&m&&(m.unobserve(t),cancelAnimationFrame(f),f=requestAnimationFrame((()=>{var e;null==(e=m)||e.observe(t)}))),n()})),c&&!l&&m.observe(c),m.observe(t));let g=l?ve(e):null;return l&&function t(){const r=ve(e);!g||r.x===g.x&&r.y===g.y&&r.width===g.width&&r.height===g.height||n(),g=r,p=requestAnimationFrame(t)}(),n(),()=>{var e;u.forEach((e=>{o&&e.removeEventListener("scroll",n),a&&e.removeEventListener("resize",n)})),null==d||d(),null==(e=m)||e.disconnect(),m=null,l&&cancelAnimationFrame(p)}}(e,r,(function(){((e,t,n)=>{const r=new Map,o={platform:Te,...n},a={...o.platform,_c:r};return(async(e,t,n)=>{const{placement:r="bottom",strategy:o="absolute",middleware:a=[],platform:i}=n,s=a.filter(Boolean),l=await(null==i.isRTL?void 0:i.isRTL(t));let c=await i.getElementRects({reference:e,floating:t,strategy:o}),{x:u,y:d}=G(c,r,l),p=r,f={},h=0;for(let m=0;m0&&void 0!==arguments[0]?arguments[0]:0,r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];t.session&&t.session.gleapHash&&rn.notifyEvent("unregister-pushmessage-group","gleapuser-".concat(t.session.gleapHash));try{E("session-".concat(t.sdkKey),null)}catch(n){}if(t.useCookies)try{!function(e){try{var t=S(window.location.host.split(":")[0]);document.cookie=e+"=; Path=/; Expires=Thu, 01 Jan 1970 00:00:01 GMT; Domain="+t}catch(n){}}("session-".concat(t.sdkKey))}catch(n){}if(t.ready=!1,t.session={gleapId:null,gleapHash:null,name:"",email:"",userId:"",phone:"",value:0},It.getInstance().sendMessage({name:"session-cleared"},!0),ur.getInstance().clearAllNotifications(!1),ur.getInstance().setNotificationCount(0),vr.getInstance().removeBannerUI(),r&&!isNaN(e)){var o=10*Math.pow(e,2);setTimeout((function(){t.startSession(e+1)}),1e3*o)}})),ze(this,"validateSession",(function(e){e&&e.gleapId&&(t.session&&t.session.gleapHash&&rn.notifyEvent("unregister-pushmessage-group","gleapuser-".concat(t.session.gleapHash)),E("session-".concat(t.sdkKey),e),t.useCookies&&function(e,t,n){try{var r="",a=new Date;a.setTime(a.getTime()+31536e6),r="; expires="+a.toUTCString();var i=S(window.location.host.split(":")[0]);document.cookie=e+"="+(t||"")+r+"; path=/; domain="+i}catch(o){}}("session-".concat(t.sdkKey),encodeURIComponent(JSON.stringify(e))),t.session=e,t.ready=!0,t.session&&t.session.gleapHash&&rn.notifyEvent("register-pushmessage-group","gleapuser-".concat(t.session.gleapHash)),t.notifySessionReady())})),ze(this,"startSession",(function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;try{if(t.useCookies){var n=function(e){try{for(var t=e+"=",n=document.cookie.split(";"),r=0;r0)){var o=C("session-".concat(t.sdkKey));o&&t.validateSession(o)}var a=t,i=new XMLHttpRequest;i.open("POST",a.apiUrl+"/sessions"),i.setRequestHeader("Content-Type","application/json;charset=UTF-8"),i.setRequestHeader("Api-Token",a.sdkKey);try{t.session&&t.session.gleapId&&t.session.gleapHash&&(i.setRequestHeader("Gleap-Id",t.session.gleapId),i.setRequestHeader("Gleap-Hash",t.session.gleapHash))}catch(s){}i.onreadystatechange=function(t){if(4===i.readyState)if(200===i.status||201===i.status)try{var n=JSON.parse(i.responseText);a.validateSession(n),Ve.getInstance().restart(),Ne.getInstance().load()}catch(s){}else 429!==i.status&&a.clearSession(e,!0)},i.send(JSON.stringify({lang:Zn.getInstance().getActiveLanguage()}))})),ze(this,"checkIfSessionNeedsUpdate",(function(e,n){if(!t.session||!t.session.userId||!e)return!0;try{if(t.session.userId.toString()!==e.toString())return!0}catch(o){}if(n)for(var r=Object.keys(n),a=0;a0)for(var e=0;e2)&&0!==t.streamedEventArray.length&&t.socket&&t.socket.readyState===t.socket.OPEN){var e=t;t.streamingEvents=!0;var n=new XMLHttpRequest;n.open("POST",qe.getInstance().apiUrl+"/sessions/ping"),n.setRequestHeader("Content-Type","application/json;charset=UTF-8"),qe.getInstance().injectSession(n),n.onerror=function(){e.errorCount++,e.streamingEvents=!1},n.onreadystatechange=function(t){4===n.readyState&&(200===n.status||201===n.status?e.errorCount=0:e.errorCount++,e.streamingEvents=!1)};var r=Mt.getInstance().getSessionDuration();n.send(JSON.stringify({time:r,events:t.streamedEventArray,opened:It.getInstance().isOpened(),type:"js",sdkVersion:"13.7.9",ws:!0})),t.streamedEventArray=[]}})),this.handleOpenBound=this.handleOpen.bind(this),this.handleErrorBound=this.handleError.bind(this),this.handleMessageBound=this.handleMessage.bind(this),this.handleCloseBound=this.handleClose.bind(this)}var t,r,o;return t=e,o=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],(r=[{key:"cleanupWebSocket",value:function(){this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.pingWS&&clearInterval(this.pingWS),this.socket&&(this.socket.removeEventListener("open",this.handleOpenBound),this.socket.removeEventListener("error",this.handleErrorBound),this.socket.removeEventListener("message",this.handleMessageBound),this.socket.removeEventListener("close",this.handleCloseBound),this.socket.close(),this.socket=null)}},{key:"initWebSocket",value:function(){this.cleanupWebSocket(),this.connectedWebSocketGleapId=qe.getInstance().session.gleapId,qe.getInstance().session&&qe.getInstance().sdkKey&&(this.socket=new WebSocket("".concat(qe.getInstance().wsApiUrl,"?gleapId=").concat(qe.getInstance().session.gleapId,"&gleapHash=").concat(qe.getInstance().session.gleapHash,"&apiKey=").concat(qe.getInstance().sdkKey,"&sdkVersion=").concat("13.7.9")),this.socket.addEventListener("open",this.handleOpenBound),this.socket.addEventListener("message",this.handleMessageBound),this.socket.addEventListener("error",this.handleErrorBound),this.socket.addEventListener("close",this.handleCloseBound))}},{key:"handleOpen",value:function(e){var t=this;this.pingWS=setInterval((function(){t.socket.readyState===t.socket.OPEN&&(t.socket.send("PING"),t.socket.send(9))}),1e4),this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null)}},{key:"handleMessage",value:function(e){this.processMessage(JSON.parse(e.data))}},{key:"handleError",value:function(e){}},{key:"handleClose",value:function(e){var t=this;setTimeout((function(){t.initWebSocket()}),5e3)}},{key:"processMessage",value:function(e){try{if("update"===e.name){var t=e.data,r=t.a,o=t.u;It.getInstance().isOpened()||(r&&go.getInstance().performActions(r),null!=o&&ur.getInstance().setNotificationCount(o))}}catch(n){}}},{key:"getEventArray",value:function(){return this.eventArray}},{key:"stop",value:function(){this.cleanupMainLoop()}},{key:"resetErrorCountLoop",value:function(){var e=this;setInterval((function(){e.errorCount=0}),6e4)}},{key:"cleanupMainLoop",value:function(){this.mainLoopTimeout&&(clearInterval(this.mainLoopTimeout),this.mainLoopTimeout=null)}},{key:"restart",value:function(){this.connectedWebSocketGleapId!==qe.getInstance().session.gleapId&&this.initWebSocket(),this.cleanupMainLoop(),this.trackInitialEvents(),this.runEventStreamLoop()}},{key:"start",value:function(){this.startPageListener(),this.resetErrorCountLoop()}},{key:"trackInitialEvents",value:function(){e.getInstance().logEvent("sessionStarted"),e.getInstance().logCurrentPage()}},{key:"logCurrentPage",value:function(){if(!go.getInstance().disablePageTracking){var e=window.location.href;e&&e!==this.lastUrl&&(this.lastUrl=e,this.logEvent("pageView",{page:e}))}}},{key:"startPageListener",value:function(){var e=this;setInterval((function(){e.logCurrentPage()}),1e3)}},{key:"logEvent",value:function(e,t){var n={name:e,date:new Date};t&&(n.data=x(t)),this.eventArray.push(n),this.streamedEventArray.push(n),this.eventArray.length>this.eventMaxLength&&this.eventArray.shift(),this.streamedEventArray.length>this.eventMaxLength&&this.streamedEventArray.shift()}}])&&We(t.prototype,r),o&&We(t,o),Object.defineProperty(t,"prototype",{writable:!1}),e}();function Ke(e){return Ke="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Ke(e)}function Ze(e,t){for(var n=0;n0)for(var e=0;e=0;--a){var i=this.tryEntries[a],s=i.completion;if("root"===i.tryLoc)return o("end");if(i.tryLoc<=this.prev){var l=r.call(i,"catchLoc"),c=r.call(i,"finallyLoc");if(l&&c){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),A(n),g}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;A(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:_(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}function rt(e,t,n,r,o,a,s){try{var l=e[a](s),c=l.value}catch(i){return void n(i)}l.done?t(c):Promise.resolve(c).then(r,o)}var ot=function(e){return new Promise((function(t,n){if(e){var r=new XMLHttpRequest;r.onload=function(){var e=new FileReader;e.onloadend=function(){t(e.result)},e.onerror=function(){n()},e.readAsDataURL(r.response)},r.onerror=function(e){t()},r.open("GET",e),r.responseType="blob",r.send()}else t()}))},at=function(e){return new Promise((function(t,n){if(e&&e.src){if(function(e){if(!e)return!1;for(var t=0;t1?t-1:0),o=1;o0||r.scrollLeft>0)&&(s.setAttribute("bb-scrollpos",!0),s.setAttribute("bb-scrolltop",r.scrollTop),s.setAttribute("bb-scrollleft",r.scrollLeft)),"SELECT"!==u&&"TEXTAREA"!==u&&"INPUT"!==u||(p=r.value,("value"===r.getAttribute("gleap-ignore")||r.classList.contains("gl-mask"))&&(p=new Array(p.length+1).join("*")),s.setAttribute("bb-data-value",p),"checkbox"!==r.type&&"radio"!==r.type||!r.checked||s.setAttribute("bb-data-checked",!0))),o.appendChild(s),r.shadowRoot&&(f=t,t++,i(r.shadowRoot.firstChild,s,f),ct(r.shadowRoot,s,f),void 0!==s.setAttribute&&s.setAttribute("bb-shadow-parent",f)),i(r.firstChild,s);case 22:case"end":return e.stop()}}),e,null,[[5,15]])})),function(){var t=this,n=arguments;return new Promise((function(r,o){var a=e.apply(t,n);function i(e){rt(a,r,o,i,s,"next",e)}function s(e){rt(a,r,o,i,s,"throw",e)}i(void 0)}))});return function(e,t,n){return r.apply(this,arguments)}}(),r=document.createDocumentFragment();n(e,r);var o=r.querySelector("head");return o||(o=r),ct(window.document,o),r}(window.document.documentElement),i=a.querySelectorAll("link[rel=import]");for(o=0;o0){for(var l=s.childNodes;l.length>0;)s.parentNode.insertBefore(l[0],s);s.remove()}}var c=a.querySelectorAll("script, noscript");for(o=0;o"),e&&e.childNodes&&e.childNodes.length>0)for(var r=0;r0?o.innerHTML=n.formatTime(e):(o.innerHTML="2:00",n.stopScreenRecording())}),1e3),this.mediaRecorder.ondataavailable=function(e){e.data.size>0&&r.push(e.data)},t.getVideoTracks()[0].onended=function(){n.prepareRecording(r)},this.mediaRecorder.onstop=function(){n.prepareRecording(r)},this.mediaRecorder.start(200),n.rerender()})),ft(this,"prepareRecording",(function(e){var t=new Blob(e,{type:this.getSupportedMimeType()});this.file=new File([t],"screen-recording.".concat("video/mp4"===this.getSupportedMimeType()?"mp4":"webm"),{type:this.getSupportedMimeType()});var n=document.querySelector(".bb-capture-preview video");n&&(n.src=URL.createObjectURL(t),this.audioAvailable=!0,this.isRecording=!1,this.rerender())})),this.rerender=t,this.permissionErrorText=n,navigator.mediaDevices&&navigator.mediaDevices.getDisplayMedia||(this.available=!1),setTimeout((function(){r.rerender()}),100)}var t,n;return t=e,(n=[{key:"getSupportedMimeType",value:function(){return MediaRecorder.isTypeSupported("video/mp4")?"video/mp4":MediaRecorder.isTypeSupported("video/webm;codecs=h264")?"video/webm;codecs=h264":"video/webm"}},{key:"formatTime",value:function(e){return(e-(e%=60))/60+(90&&(e.tags=t),this.excludeData)for(var n=Object.keys(this.excludeData),r=0;re.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&(t?window.open(e,"_blank").focus():window.location.href=e)})),Tt(this,"autoWhiteListCookieManager",(function(){window&&window.cmp_block_ignoredomains&&window.cmp_block_ignoredomains.concat(["messenger-app.gleap.io"])})),Tt(this,"injectFrame",(function(){t.injectedFrame||(t.injectedFrame=!0,t.autoWhiteListCookieManager(),T((function(){Qe.getInstance().onConfigLoaded((function(){Qe.getInstance().applyStylesFromConfig();var e=document.createElement("div");e.className="gleap-frame-container gleap-frame-container--hidden gl-block",e.innerHTML='
'),document.body.appendChild(e),t.gleapFrameContainer=e,t.gleapFrame=document.querySelector(".gleap-frame"),t.updateFrameStyle(),"widget"===t.appMode&&t.showFrameContainer(!0)}))})))})),Tt(this,"showImage",(function(e){T((function(){var t=document.createElement("div");t.className="gleap-image-view",t.innerHTML='
\n \n
'),document.body.appendChild(t);var n=function(){t.remove()};t.querySelector(".gleap-image-view-close").addEventListener("click",(function(){n()})),t.addEventListener("click",(function(e){e.target===t&&n()}))}))})),Tt(this,"updateFrameStyle",(function(){if(t.gleapFrameContainer){for(var e="gleap-frame-container--survey",n="gleap-frame-container--extended",r="gleap-frame-container--survey-full",a="gleap-frame-container--classic",i="gleap-frame-container--classic-left",s="gleap-frame-container--modern-left",l="gleap-frame-container--no-button",c=[a,i,n,s,l,e,r],u=0;u1&&void 0!==arguments[1]&&arguments[1];try{this.gleapFrame=document.querySelector(".gleap-frame"),this.gleapFrame&&this.gleapFrame.contentWindow?this.gleapFrame.contentWindow.postMessage(JSON.stringify(e),"*"):t&&this.queue.push(e)}catch(r){}}},{key:"sendSessionUpdate",value:function(){this.sendMessage({name:"session-update",data:{sessionData:qe.getInstance().getSession(),apiUrl:qe.getInstance().apiUrl,sdkKey:qe.getInstance().sdkKey}})}},{key:"sendConfigUpdate",value:function(){this.sendMessage({name:"config-update",data:{config:Qe.getInstance().getFlowConfig(),aiTools:Qe.getInstance().getAiTools(),overrideLanguage:Zn.getInstance().getOverrideLanguage()}}),this.updateFrameStyle()}},{key:"showDrawingScreen",value:function(e){var t=this;this.hideWidget(),this.markerManager=new Wn(e),this.markerManager.show((function(e){e||t.hideMarkerManager(),t.showWidget()}))}},{key:"workThroughQueue",value:function(){var e=function(e){return function(e){if(Array.isArray(e))return Ct(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return Ct(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?Ct(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}(this.queue);this.queue=[];for(var t=0;t0&&(n.tags=r),e.sendMessage({name:"collect-ticket-data",data:n})}if("height-update"===t.name){e.frameHeight=t.data;var o=document.querySelector(".gleap-frame-container-inner");"survey"!==e.appMode&&"survey_full"!==e.appMode&&"survey_web"!==e.appMode||!o||(o.style.maxHeight="".concat(e.frameHeight,"px"))}if("notify-event"===t.name&&rn.notifyEvent(t.data.type,t.data.data),"cleanup-drawings"===t.name&&e.hideMarkerManager(),"open-url"===t.name){var a=t.data,i=!!t.newTab;e.urlHandler(a,i)}if("run-custom-action"===t.name&&cn.triggerCustomAction(t.data),"close-widget"===t.name&&e.hideWidget(),"tool-execution"===t.name&&rn.notifyEvent("tool-execution",t.data),"send-feedback"===t.name){var s=t.data.formData,l=t.data.action,c=t.data.outboundId,u=t.data.spamToken;new kt(l.feedbackType,"MEDIUM",s,!1,l.excludeData,c,u).sendFeedback().then((function(t){e.sendMessage({name:"feedback-sent",data:t}),rn.notifyEvent("feedback-sent",s)})).catch((function(t){e.sendMessage({name:"feedback-sending-failed",data:"Something went wrong, please try again."}),rn.notifyEvent("error-while-sending")}))}"start-screen-drawing"===t.name&&e.showDrawingScreen(t.data)})),window.addEventListener("message",(function(t){if(t.origin===e.frameUrl||t.origin===vr.getInstance().bannerUrl)try{for(var r=JSON.parse(t.data),o=0;o1&&void 0!==arguments[1]?arguments[1]:"INFO";!e||e.length<=0||(this.logArray.push({log:k(e,1e3),date:new Date,priority:t}),this.logArray.length>this.logMaxLength&&this.logArray.shift())}},{key:"addLogWithArgs",value:function(e,t){if(e&&!(e.length<=0)){var r="";try{for(var o=0;o1&&void 0!==arguments[1])||arguments[1],n=k(e.innerText||"",40).replace(/(\r\n|\n|\r)/gm,"").replace(/ +(?= )/g,""),r="",o="";if(void 0!==e.getAttribute){var a=e.getAttribute("id");a&&(r=' id="'.concat(a,'"'));var i=e.getAttribute("class");i&&(o=' class="'.concat(i,'"'))}var s=(e.tagName||"").toLowerCase(),l="<",c=">";return t||(l="[",c="]"),"".concat(l).concat(s).concat(r).concat(o).concat(c).concat(n).concat(l,"/").concat(s).concat(c)}(e.target),"CLICK")}}))}}],r=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],n&&qt(t.prototype,n),r&&qt(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function Kt(e){return Kt="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Kt(e)}function Zt(e,t){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:{};if("flow-started"===e){var n=go.getInstance();n.setGlobalDataItem("webReplay",null),n.setGlobalDataItem("screenRecordingData",null),n.takeCurrentReplay()}var r=this.getInstance().eventListeners[e];if(r)for(var o=0;o=0;--a){var i=this.tryEntries[a],s=i.completion;if("root"===i.tryLoc)return o("end");if(i.tryLoc<=this.prev){var l=r.call(i,"catchLoc"),c=r.call(i,"finallyLoc");if(l&&c){if(this.prev=0;--n){var o=this.tryEntries[n];if(o.tryLoc<=this.prev&&r.call(o,"finallyLoc")&&this.prev=0;--t){var n=this.tryEntries[t];if(n.finallyLoc===e)return this.complete(n.completion,n.afterLoc),A(n),g}},catch:function(e){for(var t=this.tryEntries.length-1;t>=0;--t){var n=this.tryEntries[t];if(n.tryLoc===e){var r=n.completion;if("throw"===r.type){var o=r.arg;A(n)}return o}}throw new Error("illegal catch attempt")},delegateYield:function(t,n,r){return this.delegate={iterator:_(t),resultName:n,nextLoc:r},"next"===this.method&&(this.arg=e),g}},t}function dn(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var n=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=n){var r,o,a,i,s=[],l=!0,c=!1;try{if(a=(n=n.call(e)).next,0===t){if(Object(n)!==n)return;l=!1}else for(;!(l=(r=a.call(n)).done)&&(s.push(r.value),s.length!==t);l=!0);}catch(e){c=!0,o=e}finally{try{if(!l&&null!=n.return&&(i=n.return(),Object(i)!==i))return}finally{if(c)throw o}}return s}}(e,t)||hn(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function pn(e){return function(e){if(Array.isArray(e))return mn(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||hn(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function fn(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=hn(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,a=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw a}}}}function hn(e,t){if(e){if("string"==typeof e)return mn(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?mn(e,t):void 0}}function mn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n-1?e.split("/").slice(0,3).join("/"):e.split("/")[0]).split("?")[0]}(t)+s).concat(l,")");var c=t.split("/"),u=s.split("/");c.pop();for(var d=0,p=u;d=t.length);){var a=r(b);if(","===a.slice(-1))a=x(e,a.substring(0,a.length-1)),o.push(a);else{var i="";a=x(e,a);for(var s=!1;;){var l=t.charAt(n);if(""===l){o.push((a+i).trim());break}if(s)")"===l&&(s=!1);else{if(","===l){n+=1,o.push((a+i).trim());break}"("===l&&(s=!0)}i+=l,n+=1}}}return o.join(", ")}(e,r):"style"===n&&r?y(r,S()):"object"===t&&"data"===n&&r?x(e,r):r}function E(e,t,n){if(!e)return!1;if(e.nodeType!==e.ELEMENT_NODE)return!!n&&E(e.parentNode,t,n);for(var r=e.classList.length;r--;){var o=e.classList[r];if(t.test(o))return!0}return!!n&&E(e.parentNode,t,n)}function T(e,t,n){var r=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(null===r)return!1;if("string"==typeof t){if(r.classList.contains(t)||r.closest(".".concat(t)))return!0}else if(E(r,t,!0))return!0;return!(!n||!r.matches(n)&&!r.closest(n))}function L(t,n){var r=n.doc,a=n.mirror,i=n.blockClass,c=n.blockSelector,d=n.maskTextClass,p=n.maskTextSelector,m=n.inlineStylesheet,g=n.maskInputOptions,v=void 0===g?{}:g,b=n.maskTextFn,w=n.maskInputFn,x=n.dataURLOptions,E=void 0===x?{}:x,L=n.inlineImages,I=n.recordCanvas,A=n.keepIframeSrcFn,O=n.newlyAddedElement,_=void 0!==O&&O,P=function(e,t){if(t.hasNode(e)){var n=t.getId(e);return 1===n?void 0:n}}(r,a);switch(t.nodeType){case t.DOCUMENT_NODE:return"CSS1Compat"!==t.compatMode?{type:e.Document,childNodes:[],compatMode:t.compatMode}:{type:e.Document,childNodes:[]};case t.DOCUMENT_TYPE_NODE:return{type:e.DocumentType,name:t.name,publicId:t.publicId,systemId:t.systemId,rootId:P};case t.ELEMENT_NODE:return function(t,n){for(var r=n.doc,a=n.inlineStylesheet,i=n.maskInputOptions,c=void 0===i?{}:i,d=n.maskInputFn,p=n.dataURLOptions,m=void 0===p?{}:p,g=n.inlineImages,v=n.recordCanvas,b=n.keepIframeSrcFn,w=n.newlyAddedElement,x=void 0!==w&&w,E=n.rootId,T=function(e,t,n){if("string"==typeof t){if(e.classList.contains(t))return!0}else for(var r=e.classList.length;r--;){var o=e.classList[r];if(t.test(o))return!0}return!!n&&e.matches(n)}(t,n.blockClass,n.blockSelector),L=function(e){if(e instanceof HTMLFormElement)return"form";var t=e.tagName.toLowerCase().trim();return u.test(t)?"div":t}(t),I={},A=t.attributes.length,O=0;O2&&void 0!==arguments[2]?arguments[2]:document,r={capture:!0,passive:!0};return n.addEventListener(e,t,r),function(){return n.removeEventListener(e,t,r)}}var _="Please stop import mirror directly. Instead of that,\r\nnow you can use replayer.getMirror() to access the mirror instance of a replayer,\r\nor you can use record.mirror to access the mirror instance during recording.",P={map:{},getId:function(){return console.error(_),-1},getNode:function(){return console.error(_),null},removeNodeFromMap:function(){console.error(_)},has:function(){return console.error(_),!1},reset:function(){console.error(_)}};function M(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{},r=null,o=0;return function(){for(var a=arguments.length,i=new Array(a),s=0;st?(r&&(clearTimeout(r),r=null),o=l,e.apply(u,i)):!r&&!1!==n.trailing&&(r=setTimeout((function(){o=!1===n.leading?0:Date.now(),r=null,e.apply(u,i)}),c))}}function R(e,t,n,r){var o=arguments.length>4&&void 0!==arguments[4]?arguments[4]:window,a=o.Object.getOwnPropertyDescriptor(e,t);return o.Object.defineProperty(e,t,r?n:{set:function(e){var t=this;setTimeout((function(){n.set.call(t,e)}),0),a&&a.set&&a.set.call(this,e)}}),function(){return R(e,t,a||{},!0)}}function N(e,t,n){try{if(!(t in e))return function(){};var r=e[t],o=n(r);return"function"==typeof o&&(o.prototype=o.prototype||{},Object.defineProperties(o,{__rrweb_original__:{enumerable:!1,value:r}})),e[t]=o,function(){e[t]=r}}catch(a){return function(){}}}function j(){return window.innerHeight||document.documentElement&&document.documentElement.clientHeight||document.body&&document.body.clientHeight}function D(){return window.innerWidth||document.documentElement&&document.documentElement.clientWidth||document.body&&document.body.clientWidth}function F(e,t,n,r){if(!e)return!1;var o=e.nodeType===e.ELEMENT_NODE?e:e.parentElement;if(!o)return!1;if("string"==typeof t){if(o.classList.contains(t)||r&&null!==o.closest("."+t))return!0}else if(E(o,t,r))return!0;return!(!n||!(e.matches(n)||r&&null!==o.closest(n)))}function B(e,t){return t.getId(e)===d}function z(e,t){if(n(e))return!1;var r=t.getId(e);return!t.has(r)||(!e.parentNode||e.parentNode.nodeType!==e.DOCUMENT_NODE)&&(!e.parentNode||z(e.parentNode,t))}function U(e){return Boolean(e.changedTouches)}function q(e,t){return Boolean("IFRAME"===e.nodeName&&t.getMeta(e))}function H(e,t){return Boolean("LINK"===e.nodeName&&e.nodeType===e.ELEMENT_NODE&&e.getAttribute&&"stylesheet"===e.getAttribute("rel")&&t.getMeta(e))}function W(e){return Boolean(null==e?void 0:e.shadowRoot)}("undefined"==typeof window?"undefined":wn(window))<"u"&&window.Proxy&&window.Reflect&&(P=new Proxy(P,{get:function(e,t,n){return"map"===t&&console.error(_),Reflect.get(e,t,n)}}));var $=function(){function e(){gn(this,e),this.id=1,this.styleIDMap=new WeakMap,this.idStyleMap=new Map}return yn(e,[{key:"getId",value:function(e){var t;return null!=(t=this.styleIDMap.get(e))?t:-1}},{key:"has",value:function(e){return this.styleIDMap.has(e)}},{key:"add",value:function(e,t){return this.has(e)?this.getId(e):(n=void 0===t?this.id++:t,this.styleIDMap.set(e,n),this.idStyleMap.set(n,e),n);var n}},{key:"getStyle",value:function(e){return this.idStyleMap.get(e)||null}},{key:"reset",value:function(){this.styleIDMap=new WeakMap,this.idStyleMap=new Map,this.id=1}},{key:"generateId",value:function(){return this.id++}}]),e}(),G=function(e){return e[e.DomContentLoaded=0]="DomContentLoaded",e[e.Load=1]="Load",e[e.FullSnapshot=2]="FullSnapshot",e[e.IncrementalSnapshot=3]="IncrementalSnapshot",e[e.Meta=4]="Meta",e[e.Custom=5]="Custom",e[e.Plugin=6]="Plugin",e}(G||{}),V=function(e){return e[e.Mutation=0]="Mutation",e[e.MouseMove=1]="MouseMove",e[e.MouseInteraction=2]="MouseInteraction",e[e.Scroll=3]="Scroll",e[e.ViewportResize=4]="ViewportResize",e[e.Input=5]="Input",e[e.TouchMove=6]="TouchMove",e[e.MediaInteraction=7]="MediaInteraction",e[e.StyleSheetRule=8]="StyleSheetRule",e[e.CanvasMutation=9]="CanvasMutation",e[e.Font=10]="Font",e[e.Log=11]="Log",e[e.Drag=12]="Drag",e[e.StyleDeclaration=13]="StyleDeclaration",e[e.Selection=14]="Selection",e[e.AdoptedStyleSheet=15]="AdoptedStyleSheet",e}(V||{}),K=function(e){return e[e.MouseUp=0]="MouseUp",e[e.MouseDown=1]="MouseDown",e[e.Click=2]="Click",e[e.ContextMenu=3]="ContextMenu",e[e.DblClick=4]="DblClick",e[e.Focus=5]="Focus",e[e.Blur=6]="Blur",e[e.TouchStart=7]="TouchStart",e[e.TouchMove_Departed=8]="TouchMove_Departed",e[e.TouchEnd=9]="TouchEnd",e[e.TouchCancel=10]="TouchCancel",e}(K||{}),Z=function(e){return e[e["2D"]=0]="2D",e[e.WebGL=1]="WebGL",e[e.WebGL2=2]="WebGL2",e}(Z||{}),Y=function(e){return e[e.Play=0]="Play",e[e.Pause=1]="Pause",e[e.Seeked=2]="Seeked",e[e.VolumeChange=3]="VolumeChange",e[e.RateChange=4]="RateChange",e}(Y||{}),X=function(e){return e.Start="start",e.Pause="pause",e.Resume="resume",e.Resize="resize",e.Finish="finish",e.FullsnapshotRebuilded="fullsnapshot-rebuilded",e.LoadStylesheetStart="load-stylesheet-start",e.LoadStylesheetEnd="load-stylesheet-end",e.SkipStart="skip-start",e.SkipEnd="skip-end",e.MouseInteraction="mouse-interaction",e.EventCast="event-cast",e.CustomEvent="custom-event",e.Flush="flush",e.StateChange="state-change",e.PlayBack="play-back",e.Destroy="destroy",e}(X||{});function J(e){return"__ln"in e}var Q=function(){function e(){gn(this,e),this.length=0,this.head=null}return yn(e,[{key:"get",value:function(e){if(e>=this.length)throw new Error("Position outside of list range");for(var t=this.head,n=0;n=0;v--){var y=r.get(v);if(y){var b=t.mirror.getId(y.value.parentNode);if(-1===o(y.value))continue;if(-1!==b){h=y;break}var w=y.value;if(w.parentNode&&w.parentNode.nodeType===Node.DOCUMENT_FRAGMENT_NODE){var x=w.parentNode.host;if(-1!==t.mirror.getId(x)){h=y;break}}}}if(!h){for(;r.head;)r.removeNode(r.head.value);break}f=h.previous,r.removeNode(h.value),a(h.value)}var k={texts:t.texts.map((function(e){return{id:t.mirror.getId(e.node),value:e.value}})).filter((function(e){return t.mirror.has(e.id)})),attributes:t.attributes.map((function(e){return{id:t.mirror.getId(e.node),attributes:e.attributes}})).filter((function(e){return t.mirror.has(e.id)})),removes:t.removes,adds:e};!k.texts.length&&!k.attributes.length&&!k.removes.length&&!k.adds.length||(t.texts=[],t.attributes=[],t.removes=[],t.addedSet=new Set,t.movedSet=new Set,t.droppedSet=new Set,t.movedMap={},t.mutationCb(k))}},this.processMutation=function(e){if(!B(e.target,t.mirror))switch(e.type){case"characterData":var o=e.target.textContent;!F(e.target,t.blockClass,t.blockSelector,!1)&&o!==e.oldValue&&t.texts.push({value:T(e.target,t.maskTextClass,t.maskTextSelector)&&o?t.maskTextFn?t.maskTextFn(o):o.replace(/[\S]/g,"*"):o,node:e.target});break;case"attributes":var a=e.target,i=e.target.getAttribute(e.attributeName);if("value"===e.attributeName&&(i=s({maskInputOptions:t.maskInputOptions,tagName:e.target.tagName,type:e.target.getAttribute("type"),value:i,maskInputFn:t.maskInputFn})),F(e.target,t.blockClass,t.blockSelector,!1)||i===e.oldValue)return;var l=t.attributes.find((function(t){return t.node===e.target}));if("IFRAME"===a.tagName&&"src"===e.attributeName&&!t.keepIframeSrcFn(i)){if(a.contentDocument)return;e.attributeName="rr_src"}if(l||(l={node:e.target,attributes:{}},t.attributes.push(l)),"style"===e.attributeName){var c=t.doc.createElement("span");e.oldValue&&c.setAttribute("style",e.oldValue),(void 0===l.attributes.style||null===l.attributes.style)&&(l.attributes.style={});for(var u=l.attributes.style,d=0,p=Array.from(a.style);d1&&void 0!==arguments[1]?arguments[1]:{},n=e.doc.defaultView;if(!n)return function(){};!function(e,t){var n=e.mutationCb,r=e.mousemoveCb,o=e.mouseInteractionCb,a=e.scrollCb,i=e.viewportResizeCb,s=e.inputCb,l=e.mediaInteractionCb,c=e.styleSheetRuleCb,u=e.styleDeclarationCb,d=e.canvasMutationCb,p=e.fontCb,f=e.selectionCb;e.mutationCb=function(){t.mutation&&t.mutation.apply(t,arguments),n.apply(void 0,arguments)},e.mousemoveCb=function(){t.mousemove&&t.mousemove.apply(t,arguments),r.apply(void 0,arguments)},e.mouseInteractionCb=function(){t.mouseInteraction&&t.mouseInteraction.apply(t,arguments),o.apply(void 0,arguments)},e.scrollCb=function(){t.scroll&&t.scroll.apply(t,arguments),a.apply(void 0,arguments)},e.viewportResizeCb=function(){t.viewportResize&&t.viewportResize.apply(t,arguments),i.apply(void 0,arguments)},e.inputCb=function(){t.input&&t.input.apply(t,arguments),s.apply(void 0,arguments)},e.mediaInteractionCb=function(){t.mediaInteaction&&t.mediaInteaction.apply(t,arguments),l.apply(void 0,arguments)},e.styleSheetRuleCb=function(){t.styleSheetRule&&t.styleSheetRule.apply(t,arguments),c.apply(void 0,arguments)},e.styleDeclarationCb=function(){t.styleDeclaration&&t.styleDeclaration.apply(t,arguments),u.apply(void 0,arguments)},e.canvasMutationCb=function(){t.canvasMutation&&t.canvasMutation.apply(t,arguments),d.apply(void 0,arguments)},e.fontCb=function(){t.font&&t.font.apply(t,arguments),p.apply(void 0,arguments)},e.selectionCb=function(){t.selection&&t.selection.apply(t,arguments),f.apply(void 0,arguments)}}(e,t);var r,o=ke(e,e.doc),a=function(e){var t=e.mousemoveCb,n=e.sampling,r=e.doc,o=e.mirror;if(!1===n.mousemove)return function(){};var a,i="number"==typeof n.mousemove?n.mousemove:50,s="number"==typeof n.mousemoveCallback?n.mousemoveCallback:500,l=[],c=M((function(e){var n=Date.now()-a;t(l.map((function(e){return e.timeOffset-=n,e})),e),l=[],a=null}),s),u=M((function(e){var t=xe(e),n=U(e)?e.changedTouches[0]:e,r=n.clientX,i=n.clientY;a||(a=Date.now()),l.push({x:r,y:i,id:o.getId(t),timeOffset:Date.now()-a}),c(("undefined"==typeof DragEvent?"undefined":wn(DragEvent))<"u"&&e instanceof DragEvent?V.Drag:e instanceof MouseEvent?V.MouseMove:V.TouchMove)}),i,{trailing:!1}),d=[O("mousemove",u,r),O("touchmove",u,r),O("drag",u,r)];return function(){d.forEach((function(e){return e()}))}}(e),i=function(e){var t=e.mouseInteractionCb,n=e.doc,r=e.mirror,o=e.blockClass,a=e.blockSelector,i=e.sampling;if(!1===i.mouseInteraction)return function(){};var s=!0===i.mouseInteraction||void 0===i.mouseInteraction?{}:i.mouseInteraction,l=[];return Object.keys(K).filter((function(e){return Number.isNaN(Number(e))&&!e.endsWith("_Departed")&&!1!==s[e]})).forEach((function(e){var i=e.toLowerCase(),s=function(e){return function(n){var i=xe(n);if(!F(i,o,a,!0)){var s=U(n)?n.changedTouches[0]:n;if(s){var l=r.getId(i),c=s.clientX,u=s.clientY;t({type:K[e],id:l,x:c,y:u})}}}}(e);l.push(O(i,s,n))})),function(){l.forEach((function(e){return e()}))}}(e),l=Se(e),c=function(e){var t=e.viewportResizeCb,n=-1,r=-1;return O("resize",M((function(){var e=j(),o=D();(n!==e||r!==o)&&(t({width:Number(o),height:Number(e)}),n=e,r=o)}),200),window)}(e),u=function(e){var t=e.inputCb,n=e.doc,r=e.mirror,o=e.blockClass,a=e.blockSelector,i=e.ignoreClass,l=e.maskInputOptions,c=e.maskInputFn,u=e.sampling,d=e.userTriggeredOnInput;function p(e){var t=xe(e),r=e.isTrusted;if(t&&"OPTION"===t.tagName&&(t=t.parentElement),t&&t.tagName&&!(Ee.indexOf(t.tagName)<0)&&!F(t,o,a,!0)){var u=t.type;if(!t.classList.contains(i)){var p=t.value,h=!1;"radio"===u||"checkbox"===u?h=t.checked:(l[t.tagName.toLowerCase()]||l[u])&&(p=s({maskInputOptions:l,tagName:t.tagName,type:u,value:p,maskInputFn:c})),f(t,Ce({text:p,isChecked:h,userTriggered:r},d));var m=t.name;"radio"===u&&m&&h&&n.querySelectorAll('input[type="radio"][name="'.concat(m,'"]')).forEach((function(e){e!==t&&f(e,Ce({text:e.value,isChecked:!h,userTriggered:!1},d))}))}}}function f(e,n){var o=Te.get(e);if(!o||o.text!==n.text||o.isChecked!==n.isChecked){Te.set(e,n);var a=r.getId(e);t(me(he({},n),{id:a}))}}var h=("last"===u.input?["change"]:["input","change"]).map((function(e){return O(e,p,n)})),m=n.defaultView;if(!m)return function(){h.forEach((function(e){return e()}))};var g=m.Object.getOwnPropertyDescriptor(m.HTMLInputElement.prototype,"value"),v=[[m.HTMLInputElement.prototype,"value"],[m.HTMLInputElement.prototype,"checked"],[m.HTMLSelectElement.prototype,"value"],[m.HTMLTextAreaElement.prototype,"value"],[m.HTMLSelectElement.prototype,"selectedIndex"],[m.HTMLOptionElement.prototype,"selected"]];return g&&g.set&&h.push.apply(h,pn(v.map((function(e){return R(e[0],e[1],{set:function(){p({target:this})}},!1,m)})))),function(){h.forEach((function(e){return e()}))}}(e),d=function(e){var t=e.mediaInteractionCb,n=e.blockClass,r=e.blockSelector,o=e.mirror,a=e.sampling,i=function(e){return M((function(a){var i=xe(a);if(i&&!F(i,n,r,!0)){var s=i.currentTime,l=i.volume,c=i.muted,u=i.playbackRate;t({type:e,id:o.getId(i),currentTime:s,volume:l,muted:c,playbackRate:u})}}),a.media||500)},s=[O("play",i(Y.Play)),O("pause",i(Y.Pause)),O("seeked",i(Y.Seeked)),O("volumechange",i(Y.VolumeChange)),O("ratechange",i(Y.RateChange))];return function(){s.forEach((function(e){return e()}))}}(e),p=function(e,t){var n=e.styleSheetRuleCb,r=e.mirror,o=e.stylesheetManager,a=t.win,i=a.CSSStyleSheet.prototype.insertRule;a.CSSStyleSheet.prototype.insertRule=function(e,t){var a=Ie(this,r,o.styleMirror),s=a.id,l=a.styleId;return(s&&-1!==s||l&&-1!==l)&&n({id:s,styleId:l,adds:[{rule:e,index:t}]}),i.apply(this,[e,t])};var s,l,c=a.CSSStyleSheet.prototype.deleteRule;a.CSSStyleSheet.prototype.deleteRule=function(e){var t=Ie(this,r,o.styleMirror),a=t.id,i=t.styleId;return(a&&-1!==a||i&&-1!==i)&&n({id:a,styleId:i,removes:[{index:e}]}),c.apply(this,[e])},a.CSSStyleSheet.prototype.replace&&(s=a.CSSStyleSheet.prototype.replace,a.CSSStyleSheet.prototype.replace=function(e){var t=Ie(this,r,o.styleMirror),a=t.id,i=t.styleId;return(a&&-1!==a||i&&-1!==i)&&n({id:a,styleId:i,replace:e}),s.apply(this,[e])}),a.CSSStyleSheet.prototype.replaceSync&&(l=a.CSSStyleSheet.prototype.replaceSync,a.CSSStyleSheet.prototype.replaceSync=function(e){var t=Ie(this,r,o.styleMirror),a=t.id,i=t.styleId;return(a&&-1!==a||i&&-1!==i)&&n({id:a,styleId:i,replaceSync:e}),l.apply(this,[e])});var u={};ve?u.CSSGroupingRule=a.CSSGroupingRule:(ye&&(u.CSSMediaRule=a.CSSMediaRule),we&&(u.CSSConditionRule=a.CSSConditionRule),be&&(u.CSSSupportsRule=a.CSSSupportsRule));var d={};return Object.entries(u).forEach((function(e){var t=dn(e,2),a=t[0],i=t[1];d[a]={insertRule:i.prototype.insertRule,deleteRule:i.prototype.deleteRule},i.prototype.insertRule=function(e,t){var i=Ie(this.parentStyleSheet,r,o.styleMirror),s=i.id,l=i.styleId;return(s&&-1!==s||l&&-1!==l)&&n({id:s,styleId:l,adds:[{rule:e,index:[].concat(pn(Le(this)),[t||0])}]}),d[a].insertRule.apply(this,[e,t])},i.prototype.deleteRule=function(e){var t=Ie(this.parentStyleSheet,r,o.styleMirror),i=t.id,s=t.styleId;return(i&&-1!==i||s&&-1!==s)&&n({id:i,styleId:s,removes:[{index:[].concat(pn(Le(this)),[e])}]}),d[a].deleteRule.apply(this,[e])}})),function(){a.CSSStyleSheet.prototype.insertRule=i,a.CSSStyleSheet.prototype.deleteRule=c,s&&(a.CSSStyleSheet.prototype.replace=s),l&&(a.CSSStyleSheet.prototype.replaceSync=l),Object.entries(u).forEach((function(e){var t=dn(e,2),n=t[0],r=t[1];r.prototype.insertRule=d[n].insertRule,r.prototype.deleteRule=d[n].deleteRule}))}}(e,{win:n}),f=Ae(e,e.doc),h=function(e,t){var n=e.styleDeclarationCb,r=e.mirror,o=e.ignoreCSSAttributes,a=e.stylesheetManager,i=t.win,s=i.CSSStyleDeclaration.prototype.setProperty;i.CSSStyleDeclaration.prototype.setProperty=function(e,t,i){var l;if(o.has(e))return s.apply(this,[e,t,i]);var c=Ie(null==(l=this.parentRule)?void 0:l.parentStyleSheet,r,a.styleMirror),u=c.id,d=c.styleId;return(u&&-1!==u||d&&-1!==d)&&n({id:u,styleId:d,set:{property:e,value:t,priority:i},index:Le(this.parentRule)}),s.apply(this,[e,t,i])};var l=i.CSSStyleDeclaration.prototype.removeProperty;return i.CSSStyleDeclaration.prototype.removeProperty=function(e){var t;if(o.has(e))return l.apply(this,[e]);var i=Ie(null==(t=this.parentRule)?void 0:t.parentStyleSheet,r,a.styleMirror),s=i.id,c=i.styleId;return(s&&-1!==s||c&&-1!==c)&&n({id:s,styleId:c,remove:{property:e},index:Le(this.parentRule)}),l.apply(this,[e])},function(){i.CSSStyleDeclaration.prototype.setProperty=s,i.CSSStyleDeclaration.prototype.removeProperty=l}}(e,{win:n}),m=e.collectFonts?function(e){var t=e.fontCb,n=e.doc,r=n.defaultView;if(!r)return function(){};var o=[],a=new WeakMap,i=r.FontFace;r.FontFace=function(e,t,n){var r=new i(e,t,n);return a.set(r,{family:e,buffer:"string"!=typeof t,descriptors:n,fontSource:"string"==typeof t?t:JSON.stringify(Array.from(new Uint8Array(t)))}),r};var s=N(n.fonts,"add",(function(e){return function(n){return setTimeout((function(){var e=a.get(n);e&&(t(e),a.delete(n))}),0),e.apply(this,[n])}}));return o.push((function(){r.FontFace=i})),o.push(s),function(){o.forEach((function(e){return e()}))}}(e):function(){},g=function(e){var t=e.doc,n=e.mirror,r=e.blockClass,o=e.blockSelector,a=e.selectionCb,i=!0,s=function(){var e=t.getSelection();if(!(!e||i&&null!=e&&e.isCollapsed)){i=e.isCollapsed||!1;for(var s=[],l=e.rangeCount||0,c=0;c0&&this.stylesheetManager.adoptStyleSheets(e.contentDocument.adoptedStyleSheets,this.mirror.getId(e.contentDocument))}},{key:"handleMessage",value:function(e){if("rrweb"===e.data.type){if(!e.source)return;var t=this.crossOriginIframeMap.get(e.source);if(!t)return;var n=this.transformCrossOriginEvent(t,e.data.event);n&&this.wrappedEmit(n,e.data.isCheckout)}}},{key:"transformCrossOriginEvent",value:function(e,t){var n,r=this;switch(t.type){case G.FullSnapshot:return this.crossOriginIframeMirror.reset(e),this.crossOriginIframeStyleMirror.reset(e),this.replaceIdOnNode(t.data.node,e),{timestamp:t.timestamp,type:G.IncrementalSnapshot,data:{source:V.Mutation,adds:[{parentId:this.mirror.getId(e),nextId:null,node:t.data.node}],removes:[],texts:[],attributes:[],isAttachIframe:!0}};case G.Meta:case G.Load:case G.DomContentLoaded:return!1;case G.Plugin:return t;case G.Custom:return this.replaceIds(t.data.payload,e,["id","parentId","previousId","nextId"]),t;case G.IncrementalSnapshot:switch(t.data.source){case V.Mutation:return t.data.adds.forEach((function(t){r.replaceIds(t,e,["parentId","nextId","previousId"]),r.replaceIdOnNode(t.node,e)})),t.data.removes.forEach((function(t){r.replaceIds(t,e,["parentId","id"])})),t.data.attributes.forEach((function(t){r.replaceIds(t,e,["id"])})),t.data.texts.forEach((function(t){r.replaceIds(t,e,["id"])})),t;case V.Drag:case V.TouchMove:case V.MouseMove:return t.data.positions.forEach((function(t){r.replaceIds(t,e,["id"])})),t;case V.ViewportResize:return!1;case V.MediaInteraction:case V.MouseInteraction:case V.Scroll:case V.CanvasMutation:case V.Input:return this.replaceIds(t.data,e,["id"]),t;case V.StyleSheetRule:case V.StyleDeclaration:return this.replaceIds(t.data,e,["id"]),this.replaceStyleIds(t.data,e,["styleId"]),t;case V.Font:return t;case V.Selection:return t.data.ranges.forEach((function(t){r.replaceIds(t,e,["start","end"])})),t;case V.AdoptedStyleSheet:return this.replaceIds(t.data,e,["id"]),this.replaceStyleIds(t.data,e,["styleIds"]),null==(n=t.data.styles)||n.forEach((function(t){r.replaceStyleIds(t,e,["styleId"])})),t}}}},{key:"replace",value:function(e,t,n,r){var o,a=fn(r);try{for(a.s();!(o=a.n()).done;){var i=o.value;!Array.isArray(t[i])&&"number"!=typeof t[i]||(Array.isArray(t[i])?t[i]=e.getIds(n,t[i]):t[i]=e.getId(n,t[i]))}}catch(s){a.e(s)}finally{a.f()}return t}},{key:"replaceIds",value:function(e,t,n){return this.replace(this.crossOriginIframeMirror,e,t,n)}},{key:"replaceStyleIds",value:function(e,t,n){return this.replace(this.crossOriginIframeStyleMirror,e,t,n)}},{key:"replaceIdOnNode",value:function(e,t){var n=this;this.replaceIds(e,t,["id"]),"childNodes"in e&&e.childNodes.forEach((function(e){n.replaceIdOnNode(e,t)}))}}]),e}(),Me=Object.defineProperty,Re=Object.defineProperties,Ne=Object.getOwnPropertyDescriptors,je=Object.getOwnPropertySymbols,De=Object.prototype.hasOwnProperty,Fe=Object.prototype.propertyIsEnumerable,Be=function(e,t,n){return t in e?Me(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n},ze=function(e,t){for(var n in t||(t={}))De.call(t,n)&&Be(e,n,t[n]);if(je){var r,o=fn(je(t));try{for(o.s();!(r=o.n()).done;)n=r.value,Fe.call(t,n)&&Be(e,n,t[n])}catch(a){o.e(a)}finally{o.f()}}return e},Ue=function(e,t){return Re(e,Ne(t))},qe=function(){function e(t){gn(this,e),this.shadowDoms=new WeakSet,this.restorePatches=[],this.mutationCb=t.mutationCb,this.scrollCb=t.scrollCb,this.bypassOptions=t.bypassOptions,this.mirror=t.mirror;var n=this;this.restorePatches.push(N(Element.prototype,"attachShadow",(function(e){return function(t){var r=e.call(this,t);return this.shadowRoot&&n.addShadowRoot(this.shadowRoot,this.ownerDocument),r}})))}return yn(e,[{key:"addShadowRoot",value:function(e,t){var n=this;!r(e)||this.shadowDoms.has(e)||(this.shadowDoms.add(e),ke(Ue(ze({},this.bypassOptions),{doc:t,mutationCb:this.mutationCb,mirror:this.mirror,shadowDomManager:this}),e),Se(Ue(ze({},this.bypassOptions),{scrollCb:this.scrollCb,doc:e,mirror:this.mirror})),setTimeout((function(){e.adoptedStyleSheets&&e.adoptedStyleSheets.length>0&&n.bypassOptions.stylesheetManager.adoptStyleSheets(e.adoptedStyleSheets,n.mirror.getId(e.host)),Ae({mirror:n.mirror,stylesheetManager:n.bypassOptions.stylesheetManager},e)}),0))}},{key:"observeAttachShadow",value:function(e){if(e.contentWindow){var t=this;this.restorePatches.push(N(e.contentWindow.HTMLElement.prototype,"attachShadow",(function(n){return function(r){var o=n.call(this,r);return this.shadowRoot&&t.addShadowRoot(this.shadowRoot,e.contentDocument),o}})))}}},{key:"reset",value:function(){this.restorePatches.forEach((function(e){return e()})),this.shadowDoms=new WeakSet}}]),e}(),He="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",We=("undefined"==typeof Uint8Array?"undefined":wn(Uint8Array))>"u"?[]:new Uint8Array(256),$e=0;$e<64;$e++)We[He.charCodeAt($e)]=$e;var Ge=new Map,Ve=function(e,t,n){if(e&&(Ye(e,t)||"object"==wn(e))){var r=function(e,t){var n=Ge.get(e);return n||(n=new Map,Ge.set(e,n)),n.has(t)||n.set(t,[]),n.get(t)}(n,e.constructor.name),o=r.indexOf(e);return-1===o&&(o=r.length,r.push(e)),o}};function Ke(e,t,n){if(e instanceof Array)return e.map((function(e){return Ke(e,t,n)}));if(null===e)return e;if(e instanceof Float32Array||e instanceof Float64Array||e instanceof Int32Array||e instanceof Uint32Array||e instanceof Uint8Array||e instanceof Uint16Array||e instanceof Int16Array||e instanceof Int8Array||e instanceof Uint8ClampedArray)return{rr_type:e.constructor.name,args:[Object.values(e)]};if(e instanceof ArrayBuffer){var r=e.constructor.name,o=function(e){var t,n=new Uint8Array(e),r=n.length,o="";for(t=0;t>2],o+=He[(3&n[t])<<4|n[t+1]>>4],o+=He[(15&n[t+1])<<2|n[t+2]>>6],o+=He[63&n[t+2]];return r%3==2?o=o.substring(0,o.length-1)+"=":r%3==1&&(o=o.substring(0,o.length-2)+"=="),o}(e);return{rr_type:r,base64:o}}return e instanceof DataView?{rr_type:e.constructor.name,args:[Ke(e.buffer,t,n),e.byteOffset,e.byteLength]}:e instanceof HTMLImageElement?{rr_type:e.constructor.name,src:e.src}:e instanceof HTMLCanvasElement?{rr_type:"HTMLImageElement",src:e.toDataURL()}:e instanceof ImageData?{rr_type:e.constructor.name,args:[Ke(e.data,t,n),e.width,e.height]}:Ye(e,t)||"object"==wn(e)?{rr_type:e.constructor.name,index:Ve(e,t,n)}:e}var Ze=function(e,t,n){return pn(e).map((function(e){return Ke(e,t,n)}))},Ye=function(e,t){var n=["WebGLActiveInfo","WebGLBuffer","WebGLFramebuffer","WebGLProgram","WebGLRenderbuffer","WebGLShader","WebGLShaderPrecisionFormat","WebGLTexture","WebGLUniformLocation","WebGLVertexArrayObject","WebGLVertexArrayObjectOES"].filter((function(e){return"function"==typeof t[e]}));return Boolean(n.find((function(n){return e instanceof t[n]})))};function Xe(e,t,n){var r=[];try{var o=N(e.HTMLCanvasElement.prototype,"getContext",(function(e){return function(r){for(var o=arguments.length,a=new Array(o>1?o-1:0),i=1;i0&&(r.styles=o),this.adoptedStyleSheetCb(r)}}},{key:"reset",value:function(){this.styleMirror.reset(),this.trackedLinkElements=new WeakSet}},{key:"trackStylesheetInLinkElement",value:function(e){}}]),e}(),at=Object.defineProperty,it=Object.defineProperties,st=Object.getOwnPropertyDescriptors,lt=Object.getOwnPropertySymbols,ct=Object.prototype.hasOwnProperty,ut=Object.prototype.propertyIsEnumerable,dt=function(e,t,n){return t in e?at(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n},pt=function(e,t){for(var n in t||(t={}))ct.call(t,n)&&dt(e,n,t[n]);if(lt){var r,o=fn(lt(t));try{for(o.s();!(r=o.n()).done;)n=r.value,ut.call(t,n)&&dt(e,n,t[n])}catch(a){o.e(a)}finally{o.f()}}return e},ft=function(e,t){return it(e,st(t))};function ht(e){return ft(pt({},e),{timestamp:Date.now()})}var mt,gt,vt,yt=!1,bt=new i;function wt(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e.emit,n=e.checkoutEveryNms,r=e.checkoutEveryNth,o=e.blockClass,a=void 0===o?"rr-block":o,s=e.blockSelector,l=void 0===s?null:s,c=e.ignoreClass,u=void 0===c?"rr-ignore":c,d=e.maskTextClass,p=void 0===d?"rr-mask":d,f=e.maskTextSelector,h=void 0===f?null:f,m=e.inlineStylesheet,g=void 0===m||m,v=e.maskAllInputs,y=e.maskInputOptions,b=e.slimDOMOptions,w=e.maskInputFn,x=e.maskTextFn,k=e.hooks,S=e.packFn,C=e.sampling,E=void 0===C?{}:C,T=e.dataURLOptions,L=void 0===T?{}:T,I=e.mousemoveWait,_=e.recordCanvas,P=void 0!==_&&_,M=e.recordCrossOriginIframes,R=void 0!==M&&M,N=e.userTriggeredOnInput,F=void 0!==N&&N,B=e.collectFonts,z=void 0!==B&&B,U=e.inlineImages,$=void 0!==U&&U,K=e.plugins,Z=e.keepIframeSrcFn,Y=void 0===Z?function(){return!1}:Z,X=e.ignoreCSSAttributes,J=void 0===X?new Set([]):X,Q=!R||window.parent===window,ee=!1;if(!Q)try{window.parent.document,ee=!1}catch(be){ee=!0}if(Q&&!t)throw new Error("emit function is required");void 0!==I&&void 0===E.mousemove&&(E.mousemove=I),bt.reset();var te=!0===v?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:void 0!==y?y:{password:!0},ne=!0===b||"all"===b?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaVerification:!0,headMetaAuthorship:"all"===b,headMetaDescKeywords:"all"===b}:b||{};!function(){var e=this,t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:window;"NodeList"in t&&!t.NodeList.prototype.forEach&&(t.NodeList.prototype.forEach=Array.prototype.forEach),"DOMTokenList"in t&&!t.DOMTokenList.prototype.forEach&&(t.DOMTokenList.prototype.forEach=Array.prototype.forEach),Node.prototype.contains||(Node.prototype.contains=function(){for(var t=arguments.length,n=new Array(t),r=0;r=r,l=n&&e.timestamp-re.timestamp>n;(s||l)&>(!0)}};var ie,se=function(e){mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.Mutation},e)}))},le=function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.Scroll},e)}))},ce=function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.CanvasMutation},e)}))},ue=new ot({mutationCb:se,adoptedStyleSheetCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.AdoptedStyleSheet},e)}))}}),de=new Pe({mirror:bt,mutationCb:se,stylesheetManager:ue,recordCrossOriginIframes:R,wrappedEmit:mt}),pe=fn(K||[]);try{for(pe.s();!(ie=pe.n()).done;){var fe=ie.value;fe.getMirror&&fe.getMirror({nodeMirror:bt,crossOriginIframeMirror:de.crossOriginIframeMirror,crossOriginIframeStyleMirror:de.crossOriginIframeStyleMirror})}}catch(we){pe.e(we)}finally{pe.f()}vt=new rt({recordCanvas:P,mutationCb:ce,win:window,blockClass:a,blockSelector:l,mirror:bt,sampling:E.canvas,dataURLOptions:L});var he=new qe({mutationCb:se,scrollCb:le,bypassOptions:{blockClass:a,blockSelector:l,maskTextClass:p,maskTextSelector:h,inlineStylesheet:g,maskInputOptions:te,dataURLOptions:L,maskTextFn:x,maskInputFn:w,recordCanvas:P,inlineImages:$,sampling:E,slimDOMOptions:ne,iframeManager:de,stylesheetManager:ue,canvasManager:vt,keepIframeSrcFn:Y},mirror:bt});gt=function(){var e,t,n,r,o,s,c,u,d,f,m,v,y=arguments.length>0&&void 0!==arguments[0]&&arguments[0];mt(ht({type:G.Meta,data:{href:window.location.href,width:D(),height:j()}}),y),ue.reset(),ge.forEach((function(e){return e.lock()}));var b=function(e,t){var n=t||{},r=n.mirror,o=void 0===r?new i:r,a=n.blockClass,s=n.blockSelector,l=n.maskTextClass,c=n.maskTextSelector,u=n.inlineStylesheet,d=n.inlineImages,p=n.recordCanvas,f=n.maskAllInputs,h=void 0!==f&&f,m=n.slimDOM,g=void 0!==m&&m,v=n.keepIframeSrcFn;return A(e,{doc:e,mirror:o,blockClass:void 0===a?"rr-block":a,blockSelector:void 0===s?null:s,maskTextClass:void 0===l?"rr-mask":l,maskTextSelector:void 0===c?null:c,skipChild:!1,inlineStylesheet:void 0===u||u,maskInputOptions:!0===h?{color:!0,date:!0,"datetime-local":!0,email:!0,month:!0,number:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0,textarea:!0,select:!0,password:!0}:!1===h?{password:!0}:h,maskTextFn:n.maskTextFn,maskInputFn:n.maskInputFn,slimDOMOptions:!0===g||"all"===g?{script:!0,comment:!0,headFavicon:!0,headWhitespace:!0,headMetaDescKeywords:"all"===g,headMetaSocial:!0,headMetaRobots:!0,headMetaHttpEquiv:!0,headMetaAuthorship:!0,headMetaVerification:!0}:!1===g?{}:g,dataURLOptions:n.dataURLOptions,inlineImages:void 0!==d&&d,recordCanvas:void 0!==p&&p,preserveWhiteSpace:n.preserveWhiteSpace,onSerialize:n.onSerialize,onIframeLoad:n.onIframeLoad,iframeLoadTimeout:n.iframeLoadTimeout,onStylesheetLoad:n.onStylesheetLoad,stylesheetLoadTimeout:n.stylesheetLoadTimeout,keepIframeSrcFn:void 0===v?function(){return!1}:v,newlyAddedElement:!1})}(document,{mirror:bt,blockClass:a,blockSelector:l,maskTextClass:p,maskTextSelector:h,inlineStylesheet:g,maskAllInputs:te,maskTextFn:x,slimDOM:ne,dataURLOptions:L,recordCanvas:P,inlineImages:$,onSerialize:function(e){q(e,bt)&&de.addIframe(e),H(e,bt)&&ue.trackLinkElement(e),W(e)&&he.addShadowRoot(e.shadowRoot,document)},onIframeLoad:function(e,t){de.attachIframe(e,t),he.observeAttachShadow(e)},onStylesheetLoad:function(e,t){ue.attachLinkElement(e,t)},keepIframeSrcFn:Y});if(!b)return console.warn("Failed to snapshot the document");mt(ht({type:G.FullSnapshot,data:{node:b,initialOffset:{left:void 0!==window.pageXOffset?window.pageXOffset:(null===(e=document)||void 0===e?void 0:e.documentElement.scrollLeft)||(null==(u=null==(c=null===(t=document)||void 0===t?void 0:t.body)?void 0:c.parentElement)?void 0:u.scrollLeft)||(null==(d=null===(n=document)||void 0===n?void 0:n.body)?void 0:d.scrollLeft)||0,top:void 0!==window.pageYOffset?window.pageYOffset:(null===(r=document)||void 0===r?void 0:r.documentElement.scrollTop)||(null==(m=null==(f=null===(o=document)||void 0===o?void 0:o.body)?void 0:f.parentElement)?void 0:m.scrollTop)||(null==(v=null===(s=document)||void 0===s?void 0:s.body)?void 0:v.scrollTop)||0}}})),ge.forEach((function(e){return e.unlock()})),document.adoptedStyleSheets&&document.adoptedStyleSheets.length>0&&ue.adoptStyleSheets(document.adoptedStyleSheets,bt.getId(document))};try{var me=[];me.push(O("DOMContentLoaded",(function(){mt(ht({type:G.DomContentLoaded,data:{}}))})));var ve=function(e){var t;return Oe({mutationCb:se,mousemoveCb:function(e,t){return mt(ht({type:G.IncrementalSnapshot,data:{source:t,positions:e}}))},mouseInteractionCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.MouseInteraction},e)}))},scrollCb:le,viewportResizeCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.ViewportResize},e)}))},inputCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.Input},e)}))},mediaInteractionCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.MediaInteraction},e)}))},styleSheetRuleCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.StyleSheetRule},e)}))},styleDeclarationCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.StyleDeclaration},e)}))},canvasMutationCb:ce,fontCb:function(e){return mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.Font},e)}))},selectionCb:function(e){mt(ht({type:G.IncrementalSnapshot,data:pt({source:V.Selection},e)}))},blockClass:a,ignoreClass:u,maskTextClass:p,maskTextSelector:h,maskInputOptions:te,inlineStylesheet:g,sampling:E,recordCanvas:P,inlineImages:$,userTriggeredOnInput:F,collectFonts:z,doc:e,maskInputFn:w,maskTextFn:x,keepIframeSrcFn:Y,blockSelector:l,slimDOMOptions:ne,dataURLOptions:L,mirror:bt,iframeManager:de,stylesheetManager:ue,shadowDomManager:he,canvasManager:vt,ignoreCSSAttributes:J,plugins:(null==(t=null==K?void 0:K.filter((function(e){return e.observer})))?void 0:t.map((function(e){return{observer:e.observer,options:e.options,callback:function(t){return mt(ht({type:G.Plugin,data:{plugin:e.name,payload:t}}))}}})))||[]},k)};de.addLoadListener((function(e){me.push(ve(e.contentDocument))}));var ye=function(){gt(),me.push(ve(document)),yt=!0};return"interactive"===document.readyState||"complete"===document.readyState?ye():me.push(O("load",(function(){mt(ht({type:G.Load,data:{}})),ye()}),window)),function(){me.forEach((function(e){return e()})),yt=!1}}catch(me){console.warn(me)}}return wt.addCustomEvent=function(e,t){if(!yt)throw new Error("please add custom event after start recording");mt(ht({type:G.Custom,data:{tag:e,payload:t}}))},wt.freezePage=function(){ge.forEach((function(e){return e.freeze()}))},wt.takeFullSnapshot=function(e){if(!yt)throw new Error("please take full snapshot after start recording");gt(e)},wt.mirror=bt,wt}();function kn(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n4e6){var n,r=function(e,t){var n="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!n){if(Array.isArray(e)||(n=function(e,t){if(e){if("string"==typeof e)return kn(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?kn(e,t):void 0}}(e))||t&&e&&"number"==typeof e.length){n&&(e=n);var r=0,o=function(){};return{s:o,n:function(){return r>=e.length?{done:!0}:{done:!1,value:e[r++]}},e:function(e){throw e},f:o}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var a,i=!0,s=!1;return{s:function(){n=n.call(e)},n:function(){var e=n.next();return i=e.done,e},e:function(e){s=!0,a=e},f:function(){try{i||null==n.return||n.return()}finally{if(s)throw a}}}}(t.matchAll(/data:([\w\/\-\.]+);(\w+),([^)"]*)/gim));try{for(r.s();!(n=r.n()).done;){var a=n.value;t="image/"===a[1].toLocaleLowerCase().slice(0,6)?t.replace(a[0],"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAQSURBVHgBAQUA+v8ABRg5/wHSAVZN1mnaAAAAAElFTkSuQmCC"):t.replace(a[0],"")}}catch(o){r.e(o)}finally{r.f()}}return{event:JSON.parse(t),size:t.length}}(t).event;e.push(n)}}))}catch(t){console.error(t)}}},{key:"stop",value:function(){this.stopFunction&&this.stopFunction(),this.startDate=void 0,this.events=[],this.bufferSize=0}},{key:"getReplayData",value:function(){return{startDate:this.startDate,events:this.events,baseUrl:window.location.origin,width:window.innerWidth,height:window.innerHeight,isMobile:w(),type:"rrweb"}}}])&&Tn(t.prototype,n),r&&Tn(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function On(e){return On="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},On(e)}function _n(e,t){for(var n=0;nthis.startPoint.x&&(o=this.startPoint.x),t.y>this.startPoint.y&&(a=this.startPoint.y),this.path.setAttributeNS(null,"x",o),this.path.setAttributeNS(null,"y",a),this.path.setAttributeNS(null,"width",n),this.path.setAttributeNS(null,"height",r)}}},{key:"mouseDownRect",value:function(e){this.path=document.createElementNS("http://www.w3.org/2000/svg","rect"),this.path.setAttribute("fill","none"),this.path.setAttribute("stroke",this.color),this.path.setAttribute("stroke-linecap","round"),this.path.setAttribute("stroke-width",this.strokeWidthRect),this.startPoint=this.getMousePosition(e),this.appendPathToSvg(this.path)}},{key:"mouseDownPen",value:function(e){var t=this.color+"AA",n=this.strokeWidth;"blur"===this.tool&&(t="#000000",n=40),this.path=document.createElementNS("http://www.w3.org/2000/svg","path"),this.path.setAttribute("fill","none"),this.path.setAttribute("stroke",t),this.path.setAttribute("stroke-linecap","round"),this.path.setAttribute("stroke-width",n),this.buffer=[];var r=this.getMousePosition(e);this.appendToBuffer(r),this.strPath="M"+r.x+" "+r.y,this.path.setAttribute("d",this.strPath),this.appendPathToSvg(this.path)}},{key:"setTool",value:function(e){this.tool=e}},{key:"setColor",value:function(e){this.color=e}},{key:"getMousePosition",value:function(e){return e.touches&&e.touches.length>0?{x:e.touches[0].clientX,y:e.touches[0].clientY}:{x:e.clientX,y:e.clientY}}},{key:"getAveragePoint",value:function(e){var t=this.buffer.length;if(t%2==1||t>=this.bufferSize){var n,r,o=0,a=0,i=0;for(r=e;rthis.bufferSize;)this.buffer.shift()}},{key:"appendPathToSvg",value:function(e){this.svgElement.appendChild(e),this.pathBuffer.push(e),this.rerender()}},{key:"removeLastAddedPathFromSvg",value:function(){this.pathBuffer.length<=0||!this.svgElement||(this.svgElement.removeChild(this.pathBuffer[this.pathBuffer.length-1]),this.pathBuffer.pop(),this.rerender())}},{key:"fadeOutToolbar",value:function(){var e=document.querySelector(".bb-capture-toolbar");e&&(e.style.opacity=0,e.style.pointerEvents="none")}},{key:"fadeInToolbar",value:function(){var e=document.querySelector(".bb-capture-toolbar");e&&(e.style.opacity=1,e.style.pointerEvents="auto")}}],n&&_n(t.prototype,n),Object.defineProperty(t,"prototype",{writable:!1}),e}();function Nn(e){return Nn="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Nn(e)}function jn(e,t){for(var n=0;n\n \n
'.concat(u("dismiss"),"
\n
").concat(u("rect"),'
\n
\n ').concat("capture"===this.type?'
\n '.concat(u("recorderon"),"\n ").concat(u("recorderoff"),'\n \n
\n
\n ').concat(u("mic"),'\n \n
\n
2:00
\n
\n
\n ').concat(u("pointer"),"\n
"):"",'\n
\n ').concat(u("rect"),'\n
\n
\n ').concat(u("pen"),'\n
\n
\n ').concat(u("blur"),'\n
\n
\n
\n ').concat(Zn.translateText("pickAColor"),'\n
\n
\n ').concat(u("undo"),'\n ').concat(Zn.translateText("undo"),"\n
\n ").concat("capture"!==this.type?'
'.concat(Zn.translateText("next"),"
"):"",'\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n
\n \n
\n
').concat(Zn.translateText("retry"),'
\n
').concat(Zn.translateText("next"),"
\n
\n
\n
\n "),document.body.appendChild(e),e.setAttribute("dir",Zn.getInstance().isRTLLayout?"rtl":"ltr")}},{key:"unregisterListeners",value:function(){this.escListener&&document.removeEventListener("keydown",this.escListener),this.pageLeaveListener&&window.removeEventListener("beforeunload",this.pageLeaveListener)}},{key:"registerListeners",value:function(){var e=this;this.escListener=function(t){var n=!1,r=!1;"key"in(t=t||window.event)&&(n="Escape"===t.key,r="Enter"===t.key),n&&e.dismiss(),"screenshot"===e.type&&r&&e.showNextStep()},document.addEventListener("keydown",this.escListener),this.pageLeaveListener=function(e){e.preventDefault(),e.returnValue=""},window.addEventListener("beforeunload",this.pageLeaveListener)}},{key:"show",value:function(e){this.callback=e,this.registerListeners(),this.hideWidgetUI(),this.createEditorUI(),this.setupMousePointer(),"screenshot"===this.type?(go.getInstance().setGlobalDataItem("snapshotPosition",{x:window.scrollX,y:window.scrollY}),Bn.disableScroll()):this.setupScreenRecording(),this.screenDrawer=new Rn(this.captureScreenDrawerRerender.bind(this)),this.setupColorPicker(),this.setupToolbar()}},{key:"setupColorPicker",value:function(){for(var t=this,n=document.querySelector(".bb-capture-toolbar-item-selectedcolor"),r=document.querySelectorAll(".bb-capture-toolbar-item-color"),o=document.querySelector(".bb-capture-toolbar-item-colorpicker"),a=function(){var a=r[i],s=a.getAttribute("data-color");a.style.backgroundColor=s,a.onclick=function(){a&&(t.screenDrawer.setColor(s),o&&(o.style.display="none"),n.style.backgroundColor=a.style.backgroundColor,e.setPenColor(s))}},i=0;i0?r.classList.remove(e):r.classList.add(e))}}},{key:"captureRenderer",value:function(){if(this.screenRecorder){this.screenRecorder.file&&go.getInstance().setGlobalDataItem("screenRecordingData",this.screenRecorder.file);var e="bb-capture-editor-item-inactive",t=document.querySelector(".bb-capture-toolbar-item-timer"),n=document.querySelectorAll(".bb-capture-toolbar-item"),r=document.querySelector(".bb-tooltip-screen-recording"),o=document.querySelector(".bb-tooltip-audio-recording"),a=document.querySelector(".bb-capture-editor"),i="bb-capture-editor-recording",s="bb-capture-editor-notrecording";this.screenRecorder.isRecording?(a.classList.add(i),a.classList.remove(s)):(a.classList.add(s),a.classList.remove(i));var l=document.querySelector(".bb-capture-toolbar");document.querySelector(".bb-capture-preview").style.display=this.screenRecorder.file?"flex":"none",l.style.display=this.screenRecorder.file?"none":"flex";for(var c=0;c0&&(e.length>2?this.notifications=e.splice(0,e.length-2):this.notifications=e,this.renderNotifications())}},{key:"setNotificationCount",value:function(e){It.getInstance().isOpened()?(this.unreadCount=0,this.updateTabBarNotificationCount()):this.unreadCount=e,this.updateTabBarNotificationCount(),o.getInstance().updateNotificationBadge(this.unreadCount)}},{key:"showNotification",value:function(e){this.notificationContainer&&e&&e.data&&(this.notifications.find((function(t){return e.outbound===t.outbound}))||(this.notifications.push(e),e.sound&&kr.ping()),this.notifications.length>2&&this.notifications.shift(),E(this.unreadNotificationsKey,this.notifications),this.renderNotifications())}},{key:"renderNotifications",value:function(){var e=this;if(this.notificationContainer){this.clearAllNotifications(!0);var t=document.createElement("div");t.onclick=function(){e.clearAllNotifications()},t.className="gleap-notification-close",t.innerHTML=u("dismiss"),this.notificationContainer.appendChild(t);for(var n,r,o=function(){var t=e.notifications[a];n=(n=t.data.text).replaceAll("{{name}}",qe.getInstance().getName());var o=document.createElement("div");o.onclick=function(){t.data.conversation?go.openConversation(t.data.conversation.shareToken):t.data.news?go.openNewsArticle(t.data.news.id):t.data.checklist?go.openChecklist(t.data.checklist.id):go.open()},t.data.news?(o.className="gleap-notification-item-news",o.innerHTML='\n
\n '.concat(t.data.coverImageUrl&&""!==t.data.coverImageUrl&&!t.data.coverImageUrl.includes("NewsImagePlaceholder")?''):"",'\n
\n
').concat(n,"
\n ").concat(t.data.previewText&&t.data.previewText.length>0?'
'.concat(t.data.previewText,"
"):"".concat(t.data.sender?'\n
\n '.concat(t.data.sender.profileImageUrl&&'')," ").concat(t.data.sender.name,"
"):""),"\n
\n
")):t.data.checklist?((r=Math.round(t.data.currentStep/t.data.totalSteps*100))<100&&(r+=4),o.className="gleap-notification-item-checklist",o.innerHTML='\n
\n
\n
'.concat(t.data.text,'
\n
\n
\n
\n
\n \n \n \n ').concat(t.data.nextStepTitle,"\n
\n
\n
")):(o.className="gleap-notification-item",o.innerHTML="\n ".concat(t.data.sender&&t.data.sender.profileImageUrl&&''),'\n
\n ').concat(t.data.sender?'
'.concat(t.data.sender.name,"
"):"",'\n
').concat(n,"
\n
")),e.notificationContainer.appendChild(o)},a=0;a0&&void 0!==arguments[0]&&arguments[0];if(this.notificationContainer)for(e||(this.notifications=[],E(this.unreadNotificationsKey,this.notifications));this.notificationContainer.firstChild;)this.notificationContainer.removeChild(this.notificationContainer.firstChild)}},{key:"updateContainerStyle",value:function(){if(this.notificationContainer){var e=Qe.getInstance().getFlowConfig(),t="gleap-notification-container--left",n="gleap-notification-container--no-button";this.notificationContainer.classList.remove(t),this.notificationContainer.classList.remove(n),e.feedbackButtonPosition!==o.FEEDBACK_BUTTON_CLASSIC_LEFT&&e.feedbackButtonPosition!==o.FEEDBACK_BUTTON_BOTTOM_LEFT||this.notificationContainer.classList.add(t),null===o.getInstance().buttonHidden?e.feedbackButtonPosition===o.FEEDBACK_BUTTON_NONE&&this.notificationContainer.classList.add(n):o.getInstance().buttonHidden&&this.notificationContainer.classList.add(n),this.notificationContainer.setAttribute("dir",Zn.getInstance().isRTLLayout?"rtl":"ltr")}}}],r=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],n&&sr(t.prototype,n),r&&sr(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function dr(e){return dr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},dr(e)}function pr(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function fr(e){for(var t=1;t'),document.body.appendChild(t),this.bannerContainer=t}},{key:"sendMessage",value:function(e){try{var t=document.querySelector(".gleap-b-frame");t&&t.contentWindow&&t.contentWindow.postMessage(JSON.stringify(fr(fr({},e),{},{type:"banner"})),"*")}catch(n){}}},{key:"showBanner",value:function(e){this.injectBannerUI(e)}}])&&hr(t.prototype,n),r&&hr(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function yr(e){return yr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},yr(e)}function br(e,t){for(var n=0;n{this.mouseX=e.clientX,this.mouseY=e.clientY},this.handleClick=e=>{var t;this.target&&(null===(t=this.options)||void 0===t?void 0:t.onClick)&&this.options.onClick(this.target),e.preventDefault()},this.tick=()=>{this.updateTarget(),this.tickReq=window.requestAnimationFrame(this.tick)},this.active=!1,this.overlay=new Ir(null!=e?e:{})}start(e){var t,n;return!this.active&&(this.active=!0,this.options=e,document.addEventListener("mousemove",this.handleMouseMove,!0),document.addEventListener("click",this.handleClick,!0),this.overlay.addToDOM(null!==(t=e.parentElement)&&void 0!==t?t:document.body,null===(n=e.useShadowDOM)||void 0===n||n),this.tick(),!0)}stop(){this.active=!1,this.options=void 0,document.removeEventListener("mousemove",this.handleMouseMove,!0),document.removeEventListener("click",this.handleClick,!0),this.overlay.removeFromDOM(),this.target=void 0,this.mouseX=void 0,this.mouseY=void 0,this.tickReq&&window.cancelAnimationFrame(this.tickReq)}updateTarget(){var e,t;if(void 0===this.mouseX||void 0===this.mouseY)return;this.overlay.ignoreCursor();const n=document.elementFromPoint(this.mouseX,this.mouseY);if(this.overlay.captureCursor(),!n||n===this.target)return;if((null===(e=this.options)||void 0===e?void 0:e.elementFilter)&&!this.options.elementFilter(n))return this.target=void 0,void this.overlay.setBounds({x:0,y:0,width:0,height:0});this.target=n;const r=(e=>{const t=e.getBoundingClientRect();return{x:window.pageXOffset+t.left,y:window.pageYOffset+t.top,width:e.offsetWidth,height:e.offsetHeight}})(n);this.overlay.setBounds(r),(null===(t=this.options)||void 0===t?void 0:t.onHover)&&this.options.onHover(n)}}var Or=g(924);function _r(e){return _r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},_r(e)}function Pr(e,t){for(var n=0;n0&&void 0!==arguments[0]&&arguments[0])||r(t.gleapCollapseUI,e)&&r(t.gleapFrameContainer,n))&&(t.gleapCollapseUI&&t.gleapCollapseUI.classList.toggle(e),t.gleapFrameContainer&&t.gleapFrameContainer.classList.toggle(n))})),zr(this,"injectCollapseUI",(function(){if(!t.injectedCollapseUI){t.injectedCollapseUI=!0;var e=document.createElement("div");e.className="gleap-admin-collapse-ui",e.innerHTML='
\n '.concat(u("arrowdown"),"\n
"),document.body.appendChild(e),t.gleapCollapseUI=e,e.addEventListener("click",(function(){t.toggleCollapseUI()}))}})),zr(this,"injectFrame",(function(){var e;if(!t.injectedFrame){t.injectedFrame=!0;var n=document.createElement("div");n.className="gleap-admin-frame-container",n.innerHTML=''),document.body.appendChild(n),t.gleapFrameContainer=n,t.gleapFrame=document.querySelector(".gleap-admin-frame")}}))}var t,o,a;return t=e,a=[{key:"getInstance",value:function(){return this.instance||(this.instance=new e),this.instance}}],(o=[{key:"logCurrentPage",value:function(){var e=window.location.href;e&&e!==this.lastUrl&&(this.lastUrl=e,this.sendMessageToTourBuilder({name:"page-changed",data:{page:e}}))}},{key:"startPageListener",value:function(){var e=this;setInterval((function(){e.logCurrentPage()}),1e3)}},{key:"initAdminHelper",value:function(){var e=this;e.adminHelper=new Nr;try{e.adminHelper.onElementPicked=function(t){e.toggleCollapseUI(!0),e.sendMessageToTourBuilder({name:"element-picked",data:{selector:t}})}}catch(t){console.log(t)}e.injectFrame(),e.injectCollapseUI(),e.setFrameHeight("loading")}},{key:"setFrameHeight",value:function(e){if(this.gleapFrameContainer){var t;t="picker"===e||"navigate"===e?"65px":"editor"===e?"100vh":"0px",this.gleapFrameContainer.style.height=t}}},{key:"start",value:function(){var e=this;if("undefined"!=typeof window&&!window.gleapAdminDisabled){var t=this;window.addEventListener("message",(function(o){if(o.origin&&"https://app.gleap.io"!==!o.origin)try{var a=JSON.parse(o.data);if("admin"===a.type&&("load"===a.name&&(t.configData=a.data,t.initAdminHelper()),"smartlink-search-result"===a.name&&e.sendMessageToTourBuilder({name:"smartlink-search-result",data:a.data})),"tourbuilder"===a.type){if("loaddata"===a.name&&e.sendMessageToTourBuilder({name:"data",data:t.configData}),"smartlink-search"===a.name&&e.sendMessage({name:"smartlink-search",data:a.data}),"save"===a.name&&e.sendMessage({name:"save",data:a.data}),"click"===a.name)try{document.querySelector(a.data.selector).click()}catch(n){console.log(n)}"status-changed"===a.name&&(t.status=a.data,e.setFrameHeight(t.status),t.adminHelper.stopPicker(),"picker"===t.status&&t.adminHelper.startPicker())}}catch(r){}})),this.sendMessage({name:"init"}),this.startPageListener()}}},{key:"sendMessage",value:function(e){try{window&&window.opener&&window.opener.postMessage(JSON.stringify(Fr(Fr({},e),{},{type:"admin"})),"*")}catch(t){}}},{key:"sendMessageToTourBuilder",value:function(e){try{this.gleapFrame&&this.gleapFrame.contentWindow&&this.gleapFrame.contentWindow.postMessage(JSON.stringify(Fr(Fr({},e),{},{type:"tourbuilder"})),"*")}catch(t){}}}])&&Br(t.prototype,o),a&&Br(t,a),Object.defineProperty(t,"prototype",{writable:!1}),e}();function Hr(e){return Hr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Hr(e)}function Wr(e){return function(e){if(Array.isArray(e))return $r(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||function(e,t){if(e){if("string"==typeof e)return $r(e,t);var n=Object.prototype.toString.call(e).slice(8,-1);return"Object"===n&&e.constructor&&(n=e.constructor.name),"Map"===n||"Set"===n?Array.from(e):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?$r(e,t):void 0}}(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function $r(e,t){(null==t||t>e.length)&&(t=e.length);for(var n=0,r=new Array(t);n0&&void 0!==arguments[0]?arguments[0]:{})}function n(t){return t?e[t]:e}function r(e,t,n,r){return(e/=r/2)<1?n/2*e*e+t:-n/2*(--e*(e-2)-1)+t}function o(e){var t='a[href]:not([disabled]), button:not([disabled]), textarea:not([disabled]), input[type="text"]:not([disabled]), input[type="radio"]:not([disabled]), input[type="checkbox"]:not([disabled]), select:not([disabled])';return e.flatMap((function(e){var n=e.matches(t),r=Array.from(e.querySelectorAll(t));return[].concat(Wr(n?[e]:[]),r)})).filter((function(e){return"none"!==getComputedStyle(e).pointerEvents&&function(e){return!!(e.offsetWidth||e.offsetHeight||e.getClientRects().length)}(e)}))}function a(e){if(e&&!function(e){var t=e.getBoundingClientRect();return t.top>=0&&t.left>=0&&t.bottom<=(window.innerHeight||document.documentElement.clientHeight)&&t.right<=(window.innerWidth||document.documentElement.clientWidth)}(e)){var t=n("smoothScroll");e.scrollIntoView({behavior:!t||i(e)?"auto":"smooth",inline:"center",block:"center"})}}function i(e){if(e&&e.parentElement){var t=e.parentElement;return t.scrollHeight>t.clientHeight}}var s={};function l(e,t){s[e]=t}function c(e){return e?s[e]:s}function u(){s={}}var d={};function p(e,t){d[e]=t}function f(e){var t;null==(t=d[e])||t.call(d)}function h(e){if(e){var t=e.getBoundingClientRect(),n={x:t.x,y:t.y,width:t.width,height:t.height};l("__activeStagePosition",n),g(n)}}function m(e){var t=function(e){var t=window.innerWidth,r=window.innerHeight,o=document.createElementNS("http://www.w3.org/2000/svg","svg");o.classList.add("gleap-tour-overlay","gleap-tour-overlay-animated"),o.setAttribute("viewBox","0 0 ".concat(t," ").concat(r)),o.setAttribute("xmlSpace","preserve"),o.setAttribute("xmlnsXlink","http://www.w3.org/1999/xlink"),o.setAttribute("version","1.1"),o.setAttribute("preserveAspectRatio","xMinYMin slice"),o.style.fillRule="evenodd",o.style.clipRule="evenodd",o.style.strokeLinejoin="round",o.style.strokeMiterlimit="2",o.style.zIndex="10000",o.style.position="fixed",o.style.top="0",o.style.left="0",o.style.width="100%",o.style.height="100%";var a=document.createElementNS("http://www.w3.org/2000/svg","path");return a.setAttribute("d",v(e)),a.style.fill=n("overlayColor")||"rgb(0,0,0)",a.style.opacity="".concat(n("overlayOpacity")),a.style.pointerEvents="auto",a.style.cursor="auto",o.appendChild(a),o}(e);document.body.appendChild(t),S(t,(function(e){"path"===e.target.tagName&&f("overlayClick")})),l("__overlaySvg",t)}function g(e){var t=c("__overlaySvg");if(t){var n=t.firstElementChild;if("path"!==(null==n?void 0:n.tagName))throw new Error("no path element found in stage svg");n.setAttribute("d",v(e))}else m(e)}function v(e){var t=window.innerWidth,r=window.innerHeight,o=n("stagePadding")||0,a=n("stageRadius")||0,i=e.width+2*o,s=e.height+2*o,l=Math.min(a,i/2,s/2),c=Math.floor(Math.max(l,0)),u=e.x-o+c,d=e.y-o,p=i-2*c,f=s-2*c;return"M".concat(t,",0L0,0L0,").concat(r,"L").concat(t,",").concat(r,"L").concat(t,",0Z\n M").concat(u,",").concat(d," h").concat(p," a").concat(c,",").concat(c," 0 0 1 ").concat(c,",").concat(c," v").concat(f," a").concat(c,",").concat(c," 0 0 1 -").concat(c,",").concat(c," h-").concat(p," a").concat(c,",").concat(c," 0 0 1 -").concat(c,",-").concat(c," v-").concat(f," a").concat(c,",").concat(c," 0 0 1 ").concat(c,",-").concat(c," z")}function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2e3,o=e.element,i="string"==typeof o?document.querySelector(o):o;o&&!i&&t>=0?setTimeout((function(){C(),y(e,t-100)}),100):(i||(i=function(){var e=document.getElementById("gleap-tour-dummy-element");if(e)return e;var t=document.createElement("div");return t.id="gleap-tour-dummy-element",t.style.width="0",t.style.height="0",t.style.pointerEvents="none",t.style.opacity="0",t.style.position="fixed",t.style.top="50%",t.style.left="50%",document.body.appendChild(t),t}()),function(e,t){var o,i,s=400,u=Date.now(),d=c("__activeStep"),p=c("__activeElement")||e,f=!p||p===e,m="gleap-tour-dummy-element"===e.id,v="gleap-tour-dummy-element"===p.id,y=n("animate"),b=t.onHighlightStarted||n("onHighlightStarted"),w=(null==t?void 0:t.onHighlighted)||n("onHighlighted"),x=(null==d?void 0:d.onDeselected)||n("onDeselected"),k=n(),S=c();!f&&x&&x(v?void 0:p,d,{config:k,state:S}),b&&b(m?void 0:e,t,{config:k,state:S});var T=!f&&y,L=!1;C(),l("previousStep",d),l("previousElement",p),l("activeStep",t),l("activeElement",e);var I=function o(){if(c("__transitionCallback")===o){var a=Date.now()-u,i=s-a<=200;t.popover&&i&&!L&&T&&(E(e,t),L=!0),n("animate")&&a0&&M[0].focus()}function T(){var e=c("popover");if(null==e?void 0:e.wrapper){var t=e.wrapper.getBoundingClientRect(),r=n("stagePadding")||0,o=n("popoverOffset")||0;return{width:t.width+r+o,height:t.height+r+o,realWidth:t.width,realHeight:t.height}}}function L(e,t){var n=t.elementDimensions,r=t.popoverDimensions,o=t.popoverPadding,a=t.popoverArrowDimensions;return"start"===e?Math.max(Math.min(n.top-o,window.innerHeight-r.realHeight-a.width),a.width):"end"===e?Math.max(Math.min(n.top-(null==r?void 0:r.realHeight)+n.height+o,window.innerHeight-(null==r?void 0:r.realHeight)-a.width),a.width):"center"===e?Math.max(Math.min(n.top+n.height/2-(null==r?void 0:r.realHeight)/2,window.innerHeight-(null==r?void 0:r.realHeight)-a.width),a.width):0}function I(e,t){var n=t.elementDimensions,r=t.popoverDimensions,o=t.popoverPadding,a=t.popoverArrowDimensions;return"start"===e?Math.max(Math.min(n.left-o,window.innerWidth-r.realWidth-a.width),a.width):"end"===e?Math.max(Math.min(n.left-(null==r?void 0:r.realWidth)+n.width+o,window.innerWidth-(null==r?void 0:r.realWidth)-a.width),a.width):"center"===e?Math.max(Math.min(n.left+n.width/2-(null==r?void 0:r.realWidth)/2,window.innerWidth-(null==r?void 0:r.realWidth)-a.width),a.width):0}function A(e,t){var r=c("popover");if(r){var o=(null==t?void 0:t.popover)||{},a=o.align,i=void 0===a?"start":a,s=o.side,l=void 0===s?"left":s,u=i,d="gleap-tour-dummy-element"===e.id?"over":l,p=n("stagePadding")||0,f=T(),h=r.arrow.getBoundingClientRect(),m=e.getBoundingClientRect(),g=m.top-f.height,v=g>=0,y=window.innerHeight-(m.bottom+f.height),b=y>=0,w=m.left-f.width,x=w>=0,k=window.innerWidth-(m.right+f.width),S=k>=0,C=!(v||b||x||S),E=d;if("top"===d&&v?S=x=b=!1:"bottom"===d&&b?S=x=v=!1:"left"===d&&x?S=v=b=!1:"right"===d&&S&&(x=v=b=!1),"over"===d){var A=window.innerWidth/2-f.realWidth/2,O=window.innerHeight/2-f.realHeight/2;r.wrapper.style.left="".concat(A,"px"),r.wrapper.style.right="auto",r.wrapper.style.top="".concat(O,"px"),r.wrapper.style.bottom="auto"}else if(C){var _=window.innerWidth/2-(null==f?void 0:f.realWidth)/2;r.wrapper.style.left="".concat(_,"px"),r.wrapper.style.right="auto",r.wrapper.style.bottom="".concat(10,"px"),r.wrapper.style.top="auto"}else if(x){var P=Math.min(w,window.innerWidth-(null==f?void 0:f.realWidth)-h.width),M=L(u,{elementDimensions:m,popoverDimensions:f,popoverPadding:p,popoverArrowDimensions:h});r.wrapper.style.left="".concat(P,"px"),r.wrapper.style.top="".concat(M,"px"),r.wrapper.style.bottom="auto",r.wrapper.style.right="auto",E="left"}else if(S){var R=Math.min(k,window.innerWidth-(null==f?void 0:f.realWidth)-h.width),N=L(u,{elementDimensions:m,popoverDimensions:f,popoverPadding:p,popoverArrowDimensions:h});r.wrapper.style.right="".concat(R,"px"),r.wrapper.style.top="".concat(N,"px"),r.wrapper.style.bottom="auto",r.wrapper.style.left="auto",E="right"}else if(v){var j=Math.min(g,window.innerHeight-f.realHeight-h.width),D=I(u,{elementDimensions:m,popoverDimensions:f,popoverPadding:p,popoverArrowDimensions:h});r.wrapper.style.top="".concat(j,"px"),r.wrapper.style.left="".concat(D,"px"),r.wrapper.style.bottom="auto",r.wrapper.style.right="auto",E="top"}else if(b){var F=Math.min(y,window.innerHeight-(null==f?void 0:f.realHeight)-h.width),B=I(u,{elementDimensions:m,popoverDimensions:f,popoverPadding:p,popoverArrowDimensions:h});r.wrapper.style.left="".concat(B,"px"),r.wrapper.style.bottom="".concat(F,"px"),r.wrapper.style.top="auto",r.wrapper.style.right="auto",E="bottom"}C?r.arrow.classList.add("gleap-tour-popover-arrow-none"):function(e,t,n){var r=c("popover");if(r){var o=n.getBoundingClientRect(),a=T(),i=r.arrow,s=a.width,l=window.innerWidth,u=o.width,d=o.left,p=a.height,f=window.innerHeight,h=o.top,m=o.height;i.className="gleap-tour-popover-arrow";var g=t,v=e;"top"===t?(d+u<=0?(g="right",v="end"):d+u-s<=0&&(g="top",v="start"),d>=l?(g="left",v="end"):d+s>=l&&(g="top",v="end")):"bottom"===t?(d+u<=0?(g="right",v="start"):d+u-s<=0&&(g="bottom",v="start"),d>=l?(g="left",v="start"):d+s>=l&&(g="bottom",v="end")):"left"===t?(h+m<=0?(g="bottom",v="end"):h+m-p<=0&&(g="left",v="start"),h>=f?(g="top",v="end"):h+p>=f&&(g="left",v="end")):"right"===t&&(h+m<=0?(g="bottom",v="start"):h+m-p<=0&&(g="right",v="start"),h>=f?(g="top",v="start"):h+p>=f&&(g="right",v="end")),g?(i.classList.add("gleap-tour-popover-arrow-side-".concat(g)),i.classList.add("gleap-tour-popover-arrow-align-".concat(v))):i.classList.add("gleap-tour-popover-arrow-none")}}(u,E,e)}}return function(){function e(){n("allowClose")&&h()}function r(){var e=c("activeIndex"),t=n("steps")||[];if(void 0!==e){var r=e+1;t[r]?f(r):h()}}function o(){var e=c("activeIndex"),t=n("steps")||[];if(void 0!==e){var r=e-1;t[r]?f(r):h()}}function a(){var e;if(!c("__transitionCallback")){var t=c("activeIndex"),r=c("__activeStep"),a=c("__activeElement");if(void 0!==t&&void 0!==r&&void 0!==c("activeIndex")){var i=(null==(e=r.popover)?void 0:e.onPrevClick)||n("onPrevClick");if(i)return i(a,r,{config:n(),state:c()});o()}}}function i(){var e;if(!c("__transitionCallback")){var t=c("activeIndex"),o=c("__activeStep"),a=c("__activeElement");if(void 0!==t&&void 0!==o){var i=(null==(e=o.popover)?void 0:e.onNextClick)||n("onNextClick");if(i)return i(a,o,{config:n(),state:c()});r()}}}function s(){c("isInitialized")||(l("isInitialized",!0),document.body.classList.add("gleap-tour-active",n("animate")?"gleap-tour-fade":"gleap-tour-simple"),window.addEventListener("keyup",k,!1),window.addEventListener("keydown",x,!1),window.addEventListener("resize",w),window.addEventListener("scroll",w),p("overlayClick",e),p("escapePress",e),p("arrowLeftPress",a),p("arrowRightPress",i))}function f(){var e,t,r,o,a,i,s,c,u=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0,d=n("steps");if(!d)return console.error("No steps to drive through"),void h();if(d[u]){l("__activeOnDestroyed",document.activeElement),l("activeIndex",u);var p=d[u],m=d[u+1],g=d[u-1],v=(null==(e=p.popover)?void 0:e.doneBtnText)||n("doneBtnText")||"Done",b=n("allowClose"),w=void 0!==(null==(t=p.popover)?void 0:t.showProgress)?null==(r=p.popover)?void 0:r.showProgress:n("showProgress"),x=((null==(o=p.popover)?void 0:o.progressText)||n("progressText")||"{{current}} of {{total}}").replace("{{current}}","".concat(u+1)).replace("{{total}}","".concat(d.length)),k=(null==(a=p.popover)?void 0:a.showButtons)||n("showButtons"),S=["next","previous"].concat(Wr(b?["close"]:[])).filter((function(e){return!(null==k?void 0:k.length)||k.includes(e)})),C=(null==(i=p.popover)?void 0:i.onNextClick)||n("onNextClick"),E=(null==(s=p.popover)?void 0:s.onPrevClick)||n("onPrevClick"),T=(null==(c=p.popover)?void 0:c.onCloseClick)||n("onCloseClick");y(Vr(Vr({},p),{},{popover:Vr({showButtons:S,nextBtnText:m?void 0:v,disableButtons:Wr(g?[]:["previous"]),showProgress:w,progressText:x,onNextClick:C||function(){m?f(u+1):h()},onPrevClick:E||function(){f(u-1)},onCloseClick:T||function(){h()}},(null==p?void 0:p.popover)||{})}))}else h()}function h(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0],t=c("__activeElement"),r=c("__activeStep"),o=c("__activeOnDestroyed"),a=n("onDestroyStarted");if(e&&a)a(t&&"gleap-tour-dummy-element"!==(null==t?void 0:t.id)?t:void 0,r,{config:n(),state:c()});else{var i,s,l,p=(null==r?void 0:r.onDeselected)||n("onDeselected"),f=n("onDestroyed");if(document.body.classList.remove("gleap-tour-active","gleap-tour-fade","gleap-tour-simple"),window.removeEventListener("keyup",k),window.removeEventListener("resize",w),window.removeEventListener("scroll",w),(s=c("popover"))&&(null==(i=s.wrapper.parentElement)||i.removeChild(s.wrapper)),function(){var e;null==(e=document.getElementById("gleap-tour-dummy-element"))||e.remove(),document.querySelectorAll(".gleap-tour-active-element").forEach((function(e){e.classList.remove("gleap-tour-active-element","gleap-tour-no-interaction"),e.removeAttribute("aria-haspopup"),e.removeAttribute("aria-expanded"),e.removeAttribute("aria-controls")}))}(),(l=c("__overlaySvg"))&&l.remove(),d={},u(),t&&r){var h="gleap-tour-dummy-element"===t.id;p&&p(h?void 0:t,r,{config:n(),state:c()}),f&&f(h?void 0:t,r,{config:n(),state:c()})}o&&o.focus()}}return t(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),{isActive:function(){return c("isInitialized")||!1},refresh:w,drive:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:0;s(),f(e)},setConfig:t,setSteps:function(e){u(),t(Vr(Vr({},n()),{},{steps:e}))},getConfig:n,getState:c,getActiveIndex:function(){return c("activeIndex")},isFirstStep:function(){return 0===c("activeIndex")},isLastStep:function(){var e=n("steps")||[],t=c("activeIndex");return void 0!==t&&t===e.length-1},getActiveStep:function(){return c("activeStep")},getActiveElement:function(){return c("activeElement")},getPreviousElement:function(){return c("previousElement")},getPreviousStep:function(){return c("previousStep")},moveNext:r,movePrevious:o,moveTo:function(e){(n("steps")||[])[e]?f(e):h()},hasNextStep:function(){var e=n("steps")||[],t=c("activeIndex");return void 0!==t&&e[t+1]},hasPreviousStep:function(){var e=n("steps")||[],t=c("activeIndex");return void 0!==t&&e[t-1]},highlight:function(e){s(),y(Vr(Vr({},e),{},{popover:e.popover?Vr({showButtons:[],showProgress:!1,progressText:""},e.popover):void 0}))},destroy:function(){h(!1)}}}}();const Yr=Zr;function Xr(e){return Xr="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},Xr(e)}function Jr(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);t&&(r=r.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,r)}return n}function Qr(e){for(var t=1;t\n \n
').concat(u("unmute"),"
\n ");else{var d="";e.sender&&e.sender.firstName&&(c=!0,d='
\n
\n
').concat(e.sender.firstName,"
\n
")),l="".concat(d,'
').concat(a.message,"
")}var p={disableActiveInteraction:!i&&!s,popover:Qr({description:l,popoverClass:"gleap-tour-popover-".concat(a.type," ").concat(!c&&"gleap-tour-popover-no-sender"," ").concat(e.allowClose&&"gleap-tour-popover-can-close")},i?{showButtons:[]}:{})};a.selector&&a.selector.length>0&&(p.element=a.selector),r.push(p)}var f=["next","close"];e.backButton&&f.push("previous");var h=Yr(to(to(to(to(to(to(to(to({showProgress:!0,steps:r},"showProgress",t.length>1),"allowClose",e.allowClose),"nextBtnText",e.nextText),"doneBtnText",e.doneText),"prevBtnText",e.prevText),"showButtons",f),"onDestroyStarted",(function(){h.hasNextStep()?h.destroy():(h.destroy(),n.onCompletion&&n.onCompletion({tourId:n.productTourId})),document.removeEventListener("click",m)})),"onPopoverRender",(function(e){if(e)for(var t=document.querySelectorAll(".gleap-tour-popover-description img, .gleap-tour-popover-description video"),r=function(){setTimeout((function(){h.refresh()}),500),setTimeout((function(){h.refresh()}),750)},o=0;o1&&void 0!==arguments[1]?arguments[1]:"INFO";zt.getInstance().addLog(e,t)}},{key:"initialize",value:function(t){var n=this.getInstance();if(n.initialized)console.warn("Gleap already initialized.");else{n.initialized=!0;var r=qe.getInstance();r.sdkKey=t,r.setOnSessionReady((function(){setTimeout((function(){Qe.getInstance().start().then((function(){Ve.getInstance().start(),T((function(){o.getInstance().injectFeedbackButton(),ur.getInstance().injectNotificationUI(),e.checkForUrlParams(),rn.notifyEvent("initialized")}))})).catch((function(e){console.warn("Failed to initialize Gleap.")}))}),0)})),r.startSession()}}},{key:"checkForUrlParams",value:function(){if("undefined"!=typeof window&&window.location.search)try{var t=new URLSearchParams(window.location.search),n=t.get("gleap_feedback");n&&n.length>0&&e.startFeedbackFlow(n);var r=t.get("gleap_survey"),o=t.get("gleap_survey_format");r&&r.length>0&&e.showSurvey(r,"survey_full"===o?"survey_full":"survey");var a=t.get("gleap_tour");if(a&&a.length>0){var i=parseInt(t.get("gleap_tour_delay"));isNaN(i)&&(i=4),setTimeout((function(){e.startProductTour(a)}),1e3*i)}}catch(s){}}},{key:"destroy",value:function(){An.getInstance().stop(),Ve.getInstance().stop(),It.getInstance().destroy(),o.getInstance().toggleFeedbackButton(!1),ur.getInstance().clearAllNotifications(!0),qe.getInstance().clearSession(0,!1),vr.getInstance().removeBannerUI()}},{key:"closeBanner",value:function(){vr.getInstance().removeBannerUI()}},{key:"setUseCookies",value:function(e){qe.getInstance().useCookies=e}},{key:"identify",value:function(e,t,n){return qe.getInstance().identifySession(e,x(t),n)}},{key:"updateContact",value:function(e){return qe.getInstance().updateSession(x(e))}},{key:"clearIdentity",value:function(){qe.getInstance().clearSession()}},{key:"getIdentity",value:function(){return qe.getInstance().getSession()}},{key:"isUserIdentified",value:function(){var e=qe.getInstance().session;return!!(e&&e.userId&&e.userId.length>0)}},{key:"isOpened",value:function(){return It.getInstance().isOpened()}},{key:"hide",value:function(){It.getInstance().hideWidget()}},{key:"setMaxNetworkRequests",value:function(e){y.getInstance().setMaxRequests(e)}},{key:"startNetworkLogger",value:function(){y.getInstance().start()}},{key:"setNetworkLogsBlacklist",value:function(e){y.getInstance().setBlacklist(e)}},{key:"setNetworkLogPropsToIgnore",value:function(e){y.getInstance().setFilters(e)}},{key:"setReplayOptions",value:function(e){An.getInstance().setOptions(e)}},{key:"close",value:function(){It.getInstance().hideWidget()}},{key:"open",value:function(){It.getInstance().setAppMode("widget"),It.getInstance().showWidget()}},{key:"trackEvent",value:function(e,t){Ve.getInstance().logEvent(e,t)}},{key:"logEvent",value:function(e,t){Ve.getInstance().logEvent(e,t)}},{key:"preFillForm",value:function(e){var t=x(e);ar.getInstance().formPreFill=t,It.getInstance().sendMessage({name:"prefill-form-data",data:t},!0)}},{key:"on",value:function(e,t){rn.on(e,t)}},{key:"enableShortcuts",value:function(e){e?er.getInstance().start():er.getInstance().stop()}},{key:"showFeedbackButton",value:function(e){o.getInstance().toggleFeedbackButton(e)}},{key:"setAppVersionCode",value:function(e){Mt.setAppVersionCode(e)}},{key:"setAppBuildNumber",value:function(e){Mt.setAppBuildNumber(e)}},{key:"setWSApiUrl",value:function(e){qe.getInstance().wsApiUrl=e}},{key:"setApiUrl",value:function(e){qe.getInstance().apiUrl=e}},{key:"setBannerUrl",value:function(e){vr.getInstance().setBannerUrl(e)}},{key:"setFrameUrl",value:function(e){It.getInstance().frameUrl=e}},{key:"setTicketAttribute",value:function(e,t){Jt.getInstance().setTicketAttribute(e,t)}},{key:"attachCustomData",value:function(e){Jt.getInstance().attachCustomData(e)}},{key:"setCustomData",value:function(e,t){Jt.getInstance().setCustomData(e,t)}},{key:"removeCustomData",value:function(e){Jt.getInstance().removeCustomData(e)}},{key:"clearCustomData",value:function(){Jt.getInstance().clearCustomData()}},{key:"playSound",value:function(e){kr.playSound(e)}},{key:"showTabNotificationBadge",value:function(e){var t=ur.getInstance();t.showNotificationBadge=e,t.updateTabBarNotificationCount()}},{key:"setLanguage",value:function(t){Zn.getInstance().setOverrideLanguage(t),e.getInstance().initialized&&setTimeout((function(){e.getInstance().softReInitialize(),e.updateContact({lang:t})}),1e3)}},{key:"registerCustomAction",value:function(e){cn.registerCustomAction(e)}},{key:"triggerCustomAction",value:function(e){cn.triggerCustomAction(e)}},{key:"setStyles",value:function(e,t,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:"#ffffff",a=arguments.length>4&&void 0!==arguments[4]?arguments[4]:20,i=arguments.length>5&&void 0!==arguments[5]?arguments[5]:20,s=arguments.length>6&&void 0!==arguments[6]?arguments[6]:20,u=arguments.length>7&&void 0!==arguments[7]?arguments[7]:o.FEEDBACK_BUTTON_BOTTOM_LEFT;T((function(){!function(e,t,n,r,a,i,s,u){var d=c(e),p=c(n),f=c(a),h=c(t),m="#ffffff"===f,g=l(t,"#ffffff"===h?-35:-15),v=l(a,m?100:-120),y=l(a,m?30:-12),b=l(a,m?80:-30),w=(r=parseInt(r,10),Math.round(1.05*r)),x=Math.round(.8*r),k=Math.round(.6*r),S=Math.round(.4*r),C=Math.round(.25*r),E=57+s;u===o.FEEDBACK_BUTTON_CLASSIC_BOTTOM?E=s+15:(u&&u.includes("CLASSIC")||u===o.FEEDBACK_BUTTON_NONE)&&(E=s);var T='\n .gleap-font, .gleap-font * {\n font-style: normal;\n font-variant-caps: normal;\n font-variant-ligatures: normal;\n font-variant-numeric: normal;\n font-variant-east-asian: normal;\n font-weight: normal;\n font-stretch: normal;\n font-size: 100%;\n line-height: 1;\n font-family: system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";\n }\n .gleap-frame-container {\n right: '.concat(i,"px;\n bottom: ").concat(61+s,"px;\n width: calc(100% - 40px);\n max-width: 400px;\n position: fixed;\n z-index: ").concat(2147483631,";\n visibility: visible;\n box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.16);\n border-radius: ").concat(x,"px;\n overflow: hidden;\n animation-duration: .3s;\n animation-fill-mode: both;\n animation-name: gleapFadeInUp;\n user-select: none;\n pointer-events: none;\n transition: max-width 0.3s ease-out;\n }\n\n :root {\n --gleap-margin-top: 50px;\n }\n\n .gleap-tooltip-anchor {\n position: relative;\n display: inline-block;\n float: left;\n max-width: 0px;\n width: 17px;\n }\n\n .gleap-tooltip-hotspot {\n position: absolute;\n display: block;\n width: 17px;\n height: 17px;\n cursor: pointer;\n top: 0px;\n left: 0px;\n }\n\n @keyframes gleap-pulse {\n 0% {\n transform: scale(0);\n opacity: 0.25;\n }\n 45% {\n transform: scale(2.5);\n opacity: 0;\n }\n 100% {\n transform: scale(0);\n opacity: 0;\n }\n }\n\n .gleap-tooltip-hotspot-animation {\n position: absolute;\n border-radius: 17px;\n opacity: 0.25;\n display: block;\n width: 17px;\n height: 17px;\n cursor: pointer;\n top: 0px;\n left: 0px;\n animation: gleap-pulse 5s infinite;\n }\n\n .gleap-tooltip-hotspot svg {\n width: 17px;\n height: 17px;\n object-fit: contain;\n display: block;\n }\n\n .gleap-tooltip-inner {\n position: relative;\n overflow: visible;\n font-size: 14px;\n font-weight: normal;\n color: #000;\n line-height: 1.3;\n }\n\n .gleap-tooltip {\n position: absolute;\n background-color: #fff;\n color: #000;\n font-size: 15px;\n line-height: 18px;\n padding: 16px;\n padding-top: 8px;\n padding-bottom: 8px;\n border-radius: 4px;\n max-width: min(350px, 80vw);\n box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.2);\n opacity: 0;\n visibility: hidden;\n transition: opacity 0.2s, visibility 0.2s;\n z-index: ").concat(2147483700,";\n }\n\n .gleap-tooltip a {\n color: ").concat(e,";\n text-decoration: underline;\n display: inline !important;\n margin: 0px !important;\n padding: 0px !important;\n }\n\n .gleap-tooltip ul {\n padding-left: 16px;\n }\n\n .gleap-tooltip b {\n font-weight: 600;\n }\n\n .gleap-tooltip h2 {\n font-size: 18px;\n line-height: 20px;\n font-weight: 600;\n margin-top: 8px;\n margin-bottom: 8px;\n }\n\n .gleap-tooltip h3 {\n font-size: 16px;\n line-height: 18px;\n font-weight: 600;\n margin-top: 8px;\n margin-bottom: 8px;\n }\n\n .gleap-tooltip p {\n padding: 0px;\n margin-top: 8px;\n margin-bottom: 8px;\n }\n\n .gleap-tooltip img {\n max-width: 100%;\n max-height: 300px;\n width: 100%;\n height: auto;\n object-fit: cover;\n margin-top: 8px;\n margin-bottom: 8px;\n border-radius: 4px;\n }\n\n .gleap-tooltip iframe,\n .gleap-tooltip video {\n max-width: 100%;\n width: 100%;\n height: auto;\n min-height: 200px;\n display: block;\n border: none;\n outline: none;\n padding: 0px;\n margin-top: 8px;\n margin-bottom: 8px;\n border-radius: 4px;\n }\n\n .gleap-tooltip-arrow {\n position: absolute;\n width: 20px;\n height: 20px;\n }\n\n .gleap-tooltip-arrow svg {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n\n .gleap-b-frame {\n width: 100%;\n height: 100%;\n border: none;\n pointer-events: auto;\n padding: 0px;\n margin: 0px;\n }\n\n .gleap-b-shown {\n transition: margin 0.3s ease-out;\n margin-top: var(--gleap-margin-top);\n position: relative;\n z-index: 10000;\n }\n\n .gleap-b-f {\n margin-top: 0px;\n }\n\n .gleap-b {\n display: none;\n position: absolute;\n top: calc(-1 * var(--gleap-margin-top));\n left: 0px;\n width: 100vw;\n height: var(--gleap-margin-top);\n }\n\n @keyframes gleapSlideIn {\n from {\n top: calc(-1 * var(--gleap-margin-top));\n }\n to {\n top: 10px;\n }\n }\n\n .gleap-b-f .gleap-b {\n position: fixed;\n top: 10px;\n animation: gleapSlideIn .25s ease-out forwards;\n max-width: 800px;\n width: calc(100% - 20px);\n left: 50%;\n z-index: ").concat(2147483699,";\n transform: translateX(-50%);\n border-radius: ").concat(S,"px;\n overflow: hidden;\n box-shadow: 0px 10px 20px rgba(0, 0, 0, 0.15), 0px 5px 5px rgba(0, 0, 0, 0.05);\n }\n\n .gleap-b-shown .gleap-b {\n display: block;\n }\n\n .gleap-image-view {\n position: fixed;\n top: 0px;\n left: 0px;\n width: 100vw;\n height: 100vh;\n z-index: ").concat(2147483699,";\n background-color: ").concat(f,"cc;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n\n .gleap-image-view-image {\n width: 90%;\n height: auto;\n max-width: 90%;\n max-height: 90%;\n object-fit: contain;\n }\n\n .gleap-image-view-close {\n position: fixed;\n top: 20px;\n right: 20px;\n width: 32px;\n height: 32px;\n opacity: 0.8;\n z-index: ").concat(2147483740,";\n box-shadow: 0px 5px 18px rgba(0, 0, 0, 0.16);\n cursor: pointer;\n }\n\n .gleap-image-view-close:hover {\n opacity: 1;\n }\n\n .gleap-image-view-close svg path {\n fill: ").concat(a,";\n }\n\n [dir=rtl].gleap-frame-container {\n right: auto;\n left: ").concat(i,"px;\n bottom: ").concat(61+s,'px;\n }\n\n .gleap-frame-container--loading iframe {\n opacity: 0;\n }\n\n .gleap-frame-container--loading::before {\n content: " ";\n position: fixed;\n top: 0px;\n left: 0px;\n right: 0px;\n height: 100%;\n max-height: 380px;\n background: linear-gradient(\n 130deg,\n ').concat(g," 0%,\n ").concat(t,' 100%\n );\n }\n \n .gleap-frame-container--loading::after {\n content: " ";\n position: fixed;\n top: 0px;\n left: 0px;\n right: 0px;\n height: 100%;\n height: 100%;\n max-height: 380px;\n background: linear-gradient(\n 180deg,\n transparent 60%,\n ').concat(a,"1A 70%,\n ").concat(a," 100%\n );\n }\n\n .gleap-frame-container--loading-nogradient::before {\n max-height: 340px;\n background: ").concat(t," !important;\n }\n\n .gleap-frame-container--loading-nofade::after {\n display: none !important;\n }\n\n .gleap-frame-container--survey {\n bottom: ").concat(s,"px !important;\n }\n\n .gleap-frame-container--extended {\n max-width: 690px !important;\n }\n\n .gleap-frame-container--survey-full {\n position: fixed;\n top: 0 !important;\n left: 0 !important;\n bottom: 0 !important;\n right: 0 !important;\n width: 100vw !important;\n max-width: 100vw !important;\n height: 100vh !important;\n background-color: rgba(0, 0, 0, 0.5);\n backdrop-filter: blur(6px);\n display: flex !important;\n justify-content: center !important;\n align-items: center !important;\n max-height: 100vh !important;\n border-radius: 0 !important;\n animation-name: none !important;\n }\n\n .gleap-frame-container--survey-full .gleap-frame-container-inner {\n max-width: 640px !important;\n width: calc(100% - 24px);\n border-radius: ").concat(x,"px;\n overflow: hidden;\n }\n\n .gleap-frame-container--classic {\n right: ").concat(i,"px;\n bottom: ").concat(s,"px;\n }\n\n [dir=rtl].gleap-frame-container--classic {\n right: auto;\n left: ").concat(i,"px;\n bottom: ").concat(s,"px;\n }\n\n .gleap-frame-container--no-button {\n bottom: ").concat(s,"px;\n }\n\n [dir=rtl].gleap-frame-container--classic-left {\n bottom: ").concat(s,"px;\n }\n\n .gleap-frame-container--classic-left {\n right: auto;\n left: ").concat(i,"px;\n bottom: ").concat(s,"px;\n }\n\n [dir=rtl].gleap-frame-container--classic-left {\n left: auto;\n right: ").concat(i,"px;\n bottom: ").concat(s,"px;\n }\n\n .gleap-frame-container--modern-left {\n right: auto;\n left: ").concat(i,"px;\n bottom: ").concat(61+s,"px;\n }\n\n [dir=rtl].gleap-frame-container--modern-left {\n left: auto;\n right: ").concat(i,"px;\n bottom: ").concat(61+s,"px;\n }\n\n .gleap-frame-container--animate {\n pointer-events: auto !important;\n }\n\n @keyframes gleapFadeInUp {\n from {\n opacity: 0;\n transform: translate3d(0, 100%, 0);\n }\n to {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n }\n }\n\n @keyframes gleapFadeInUpMobile {\n from {\n opacity: 0;\n transform: translate3d(0, 10%, 0);\n }\n to {\n opacity: 1;\n transform: translate3d(0, 0, 0);\n }\n }\n\n .gleap-notification-container {\n position: fixed;\n bottom: ").concat(E,"px;\n right: ").concat(i,"px;\n z-index: ").concat(2147483630,";\n display: flex;\n flex-direction: column;\n align-items: flex-end;\n width: 100%;\n max-width: min(340px, 80vw);\n }\n\n .gleap-notification-container--left {\n left: ").concat(4+i,"px;\n right: initial !important;\n }\n\n [dir=rtl].gleap-notification-container {\n left: ").concat(4+i,"px;\n right: initial !important;\n }\n\n [dir=rtl].gleap-notification-container--left {\n left: initial !important;\n right: ").concat(i,"px !important;\n align-items: flex-start !important;\n }\n\n .gleap-notification-container--no-button {\n bottom: ").concat(s,"px;\n }\n\n .gleap-notification-item {\n animation-duration: 0.7s;\n animation-fill-mode: both;\n animation-name: bbFadeInOpacity;\n }\n\n .gleap-notification-close {\n border-radius: 100%;\n width: 28px;\n height: 28px;\n background-color: ").concat(v,";\n display: flex;\n justify-content: center;\n align-items: center;\n margin-bottom: 8px;\n cursor: pointer;\n visibility: hidden;\n pointer-events: none;\n }\n\n .gleap-notification-container:hover .gleap-notification-close {\n visibility: visible;\n pointer-events: auto;\n animation-duration: 0.7s;\n animation-fill-mode: both;\n animation-name: bbFadeInOpacity;\n }\n\n @media only screen and (max-width: 450px) {\n .gleap-notification-close {\n visibility: visible;\n pointer-events: auto;\n animation-duration: 0.7s;\n animation-fill-mode: both;\n animation-name: bbFadeInOpacity;\n }\n }\n\n .gleap-notification-close svg {\n width: 45%;\n height: 45%;\n object-fit: contain;\n fill: ").concat(a,";\n }\n\n .gleap-notification-item-checklist-container {\n display: flex;\n animation: fadeIn;\n animation-duration: .45s;\n background-color: ").concat(a,";\n border-radius: ").concat(v,";\n box-sizing: border-box;\n cursor: pointer;\n flex-direction: column;\n overflow: hidden;\n box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.2);\n border-radius: ").concat(k,"px;\n margin-bottom: 12px;\n }\n\n .gleap-notification-item-checklist-content {\n align-items: flex-start;\n display: flex;\n flex-direction: column;\n padding: 15px;\n width: 100%;\n width: min(310px, 70vw);\n max-width: min(310px, 70vw);\n }\n\n .gleap-notification-item-checklist-content-title {\n color: ").concat(f,";\n font-size: 15px;\n font-weight: 500;\n line-height: 21px;\n margin-bottom: 10px;\n max-width: 100%;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .gleap-notification-item-checklist-content-progress {\n width: 100%;\n height: 8px;\n border-radius: 8px;\n background-color: ").concat(y,";\n }\n\n .gleap-notification-item-checklist-content-progress-inner {\n height: 100%;\n border-radius: 8px;\n background-color: ").concat(e,";\n }\n\n .gleap-notification-item-checklist-content-next {\n color: ").concat(v,";\n font-size: 15px;\n font-weight: normal;\n line-height: 21px;\n margin-top: 10px;\n max-width: 100%;\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n display: flex;\n align-items: center;\n }\n\n .gleap-notification-item-checklist-content-next svg {\n height: 18px;\n margin-right: 5px;\n width: auto;\n }\n\n .gleap-notification-item-checklist-content-next b {\n font-size: 15px;\n font-weight: normal;\n color: ").concat(f,";\n }\n\n .gleap-notification-item-news {\n width: 100%;\n cursor: pointer;\n }\n\n .gleap-notification-item-news-content {\n align-items: flex-start;\n display: flex;\n flex-direction: column;\n padding: 15px;\n }\n\n .gleap-notification-item-news-preview {\n color: ").concat(v,";\n font-size: 15px;\n line-height: 21px;\n font-weight: 400;\n overflow-wrap: break-word;\n word-break: break-word;\n display: block;\n display: -webkit-box;\n -webkit-line-clamp: 2;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .gleap-notification-item-news-sender {\n display: flex;\n align-items: center;\n color: ").concat(v,";\n font-size: 15px;\n line-height: 21px;\n font-weight: 400;\n }\n \n .gleap-notification-item-news-content-title {\n color: ").concat(f,";\n font-size: 15px;\n font-weight: 500;\n line-height: 21px;\n margin-bottom: 6px;\n max-width: 100%;\n -webkit-line-clamp: 3;\n -webkit-box-orient: vertical;\n overflow: hidden;\n }\n\n .gleap-notification-item-news-sender img {\n border-radius: 100%;\n height: 20px;\n margin-right: 8px;\n object-fit: cover;\n width: 20px;\n }\n\n [dir=rtl] .gleap-notification-item-news-sender img {\n margin-left: 8px;\n margin-right: 0px !important;\n }\n\n .gleap-notification-item-news-container {\n display: flex;\n animation: fadeIn;\n animation-duration: .45s;\n background-color: ").concat(a,";\n border-radius: ").concat(v,";\n box-sizing: border-box;\n cursor: pointer;\n flex-direction: column;\n overflow: hidden;\n box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.2);\n border-radius: ").concat(k,"px;\n margin-bottom: 12px;\n }\n\n .gleap-notification-item-news-image {\n background-color: ").concat(v,";\n height: 170px;\n object-fit: cover;\n width: 100%;\n }\n\n .gleap-notification-item-news:hover .gleap-notification-item-news-content-title {\n color: ").concat(e,";\n }\n\n .gleap-notification-item {\n display: flex;\n align-items: flex-end;\n cursor: pointer;\n }\n\n .gleap-notification-item img {\n width: 32px;\n height: 32px;\n min-width: 32px;\n border-radius: 100%;\n object-fit: cover;\n margin-right: 8px;\n margin-bottom: 12px;\n cursor: pointer;\n }\n\n [dir=rtl] .gleap-notification-item img {\n margin-left: 8px;\n margin-right: 0px !important;\n }\n\n .gleap-notification-item-container {\n box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.2);\n border-radius: ").concat(k,"px;\n border-bottom-left-radius: 0px;\n padding: 20px;\n background-color: ").concat(a,";\n margin-bottom: 12px;\n cursor: pointer;\n font-size: 15px;\n line-height: 21px;\n color: ").concat(f,';\n position: relative;\n }\n\n .gleap-notification-item-container::after {\n content: " ";\n position: absolute;\n bottom: 0px;\n width: 0px;\n height: 0px;\n left: -6px;\n border-style: solid;\n border-width: 0px 0px 10px 6px;\n border-color: transparent transparent ').concat(a,";\n }\n\n .gleap-notification-item-sender {\n color: ").concat(v,";\n line-height: 20px;\n }\n\n .gleap-notification-item-content {\n line-height: 20px;\n color: ").concat(f,";\n margin-top: 4px;\n min-width: min(200px, 50vw);\n word-wrap: break-word;\n word-break: break-word;\n }\n\n .gleap-frame-container-inner {\n position: relative;\n width: 100%;\n height: calc(100vh - ").concat(130+s,"px);\n max-height: ").concat(700,'px;\n }\n\n .gleap-frame-container--survey .gleap-frame-container-inner {\n height: calc(100vh - 40px);\n }\n \n .gleap-frame-container-inner:before {\n content: " ";\n position: absolute;\n width: 100%;\n height: calc(100% - ').concat(x,"px);\n top: ").concat(x,"px;\n background-color: ").concat(a,";\n z-index: -1;\n }\n \n .gleap-frame-container iframe {\n height: 100% !important;\n width: 100% !important;\n max-width: 100% !important;\n display: block;\n pointer-events: auto;\n }\n \n .gleap-frame-container--hidden {\n display: none !important;\n pointer-events: none;\n animation: none !important;\n }\n \n .bb-feedback-button {\n margin: 0px;\n position: fixed;\n bottom: ").concat(s,"px;\n right: ").concat(i,"px;\n border-radius: 30px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n background-color: transparent;\n color: #000000;\n z-index: ").concat(2147483630,";\n box-sizing: border-box;\n display: flex;\n align-items: center;\n padding: 0px;\n }\n\n [dir=rtl].bb-feedback-button {\n bottom: ").concat(s,"px;\n right: auto;\n left: ").concat(i,"px;\n }\n \n .bb-feedback-button--bottomleft {\n bottom: ").concat(s,"px;\n right: auto;\n left: ").concat(i,"px;\n }\n\n [dir=rtl].bb-feedback-button--bottomleft {\n bottom: ").concat(s,"px;\n right: ").concat(i,'px;\n left: auto;\n }\n \n .bb-feedback-button--disabled {\n display: none !important;\n }\n\n .bb-feedback-button--hidden {\n display: none !important;\n }\n \n .bb-feedback-button-text {\n padding: 8px 12px;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n justify-content: center;\n background-color: #fff;\n border-radius: 8px;\n box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.15);\n position: relative;\n z-index: 99;\n }\n \n .bb-feedback-button-text:before {\n content: "";\n position: absolute;\n box-shadow: rgba(0, 0, 0, 0.04) 6px 6px 5px;\n transform: rotate(315deg);\n bottom: 16px;\n right: -4px;\n border-width: 10px;\n border-style: solid;\n border-color: transparent #fff #fff transparent;\n }\n \n .bb-feedback-button--bottomleft .bb-feedback-button-text:before {\n display: none;\n }\n \n .bb-feedback-button-text:after {\n content: "";\n position: absolute;\n bottom: 12px;\n right: 0px;\n background-color: #fff;\n width: 5px;\n height: 30px;\n }\n \n .bb-feedback-button-text-title {\n font-family: sans-serif;\n font-size: 14px;\n color: #666;\n line-height: 18px;\n max-width: 220px;\n }\n \n .bb-feedback-button-text-title b {\n color: #000000;\n font-weight: 600;\n }\n\n .bb-notification-bubble {\n position: absolute;\n top: -5px;\n right: -5px;\n min-width: 20px;\n padding: 0px 4px;\n height: 20px;\n border-radius: 20px;\n background-color: red;\n color: #fff;\n font-size: 11px;\n font-family: sans-serif;\n text-align: center;\n line-height: 20px;\n }\n\n .bb-notification-bubble--hidden {\n display: none;\n }\n \n .bb-feedback-button-icon {\n width: 48px;\n height: 48px;\n border-radius: 48px;\n background-color: #485bff;\n transition: box-shadow, transform 0.2s ease-in-out;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15), 0px 0px 20px rgba(0, 0, 0, 0.1);\n position: relative;\n }\n \n .bb-feedback-button-classic {\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n top: 50%;\n right: 0px;\n position: fixed;\n transform: rotate(-90deg) translate(50%, -50%);\n transform-origin: 100% 50%;\n padding: 9px 20px;\n text-align: center;\n background-color: #485bff;\n border-top-left-radius: 8px;\n border-top-right-radius: 8px;\n font-family: sans-serif;\n font-size: 16px;\n color: #fff;\n box-shadow: 0px 0px 14px 0px rgba(0, 0, 0, 0.25);\n }\n\n [dir=rtl].bb-feedback-button .bb-feedback-button-classic {\n top: 50%;\n left: 0px;\n right: auto;\n transform: rotate(90deg) translate(-50%, -100%);\n transform-origin: 0% 0%;\n }\n \n .bb-feedback-button-classic--left {\n top: 50%;\n left: 0px;\n right: auto;\n transform: rotate(90deg) translate(-50%, -100%);\n transform-origin: 0% 0%;\n }\n\n [dir=rtl].bb-feedback-button .bb-feedback-button-classic--left {\n top: 50%;\n right: 0px;\n left: auto;\n transform: rotate(-90deg) translate(50%, -50%);\n transform-origin: 100% 50%;\n }\n \n .bb-feedback-button-classic--bottom {\n top: auto;\n bottom: 0px;\n transform: none;\n right: ').concat(i,"px;\n left: auto;\n }\n \n [dir=rtl].bb-feedback-button .bb-feedback-button-classic--bottom {\n top: auto;\n bottom: 0px;\n transform: none;\n left: ").concat(i,"px;\n right: auto;\n }\n\n .bb-feedback-button--classic-button-style {\n animation-duration: 0.2s;\n animation-fill-mode: both;\n animation-name: bbFadeInOpacity;\n }\n \n .bb-feedback-button--open.bb-feedback-button--classic-button-style {\n animation-duration: 0.2s;\n animation-fill-mode: both;\n animation-name: bbFadeOutRight;\n }\n \n .bb-feedback-button .bb-logo-logo {\n position: absolute;\n width: 30px;\n height: 30px;\n top: 9px;\n left: 9px;\n object-fit: contain;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n animation-name: bbZoomIn;\n }\n \n .bb-feedback-button .bb-logo-arrowdown {\n position: absolute;\n width: 14px;\n height: 14px;\n top: 17px;\n left: 17px;\n object-fit: contain;\n animation-duration: 0.3s;\n animation-fill-mode: both;\n }\n \n .bb-feedback-button .bb-logo-arrowdown {\n animation-name: bbZoomOut;\n }\n \n .bb-feedback-button--open .bb-logo-arrowdown {\n animation-name: bbZoomIn;\n }\n \n .bb-feedback-button--open .bb-logo-logo {\n animation-name: bbZoomOut;\n }\n \n .bb-feedback-button-icon:hover {\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.25), 0px 0px 20px rgba(0, 0, 0, 0.2);\n transform: scale(1.1);\n }\n \n .bb-feedback-button--open .bb-feedback-button-text {\n animation-name: bbFadeOutDown;\n }\n \n .bb-feedback-button--open .bb-feedback-button-icon {\n display: flex;\n }\n \n .bb-capture-svg {\n position: fixed;\n z-index: ").concat(2147483614,";\n top: 0px;\n left: 0px;\n right: 0px;\n width: 100%;\n height: 100%;\n padding: 0px;\n margin: 0px;\n cursor: crosshair;\n }\n\n .bb-capture-svg--preview {\n cursor: auto !important;\n }\n \n .bb-rec-on-circle {\n animation-name: bbRecIconFade;\n animation-duration: 2s;\n animation-iteration-count: infinite;\n animation-direction: alternate;\n }\n \n .bb-rec-on-cont {\n animation-name: bbRecIconContFade;\n animation-duration: 2s;\n animation-iteration-count: infinite;\n animation-direction: alternate;\n }\n \n .bb-capture-editor-drag-info {\n position: fixed;\n top: -200px;\n left: 0px;\n z-index: ").concat(2147483616,";\n transition: opacity 0.3s ease-in-out;\n }\n \n .bb-capture-editor-drag-info svg {\n width: 24px;\n height: 24px;\n }\n \n .bb-capture-editor-borderlayer {\n position: fixed;\n top: 0px;\n left: 0px;\n width: 100vw;\n height: 100vh;\n border: 4px solid ").concat(e,";\n cursor: crosshair;\n z-index: ").concat(2147483610,";\n box-sizing: border-box;\n pointer-events: none;\n }\n \n .bb-capture-editor-notrecording .bb-capture-editor-borderlayer {\n background-color: rgba(0, 0, 0, 0.8);\n }\n\n .bb-capture-editor-recording .bb-capture-editor-borderlayer {\n border: 4px solid #eb144c !important;\n }\n \n .bb-capture-editor-recording .bb-capture-dismiss {\n display: none;\n }\n \n .bb-capture-editor-item-inactive {\n opacity: 0.3;\n cursor: not-allowed !important;\n }\n \n .bb-capture-editor-notrecording .bb-capture-toolbar-drawingitem {\n opacity: 0.3;\n cursor: not-allowed !important;\n }\n \n .bb-capture-editor-notrecording .bb-capture-editor-drag-info {\n display: none;\n }\n \n .bb-capture-editor-notrecording .bb-capture-svg {\n pointer-events: none !important;\n }\n \n .bb-capture-toolbar {\n position: fixed;\n top: 20px;\n left: 50%;\n transform: translateX(-50%);\n z-index: ").concat(2147483618,";\n background-color: #fff;\n padding: 5px;\n display: flex;\n align-items: center;\n border-radius: 8px;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15), 0px 0px 20px rgba(0, 0, 0, 0.1);\n transition: opacity 0.3s ease-in-out;\n }\n \n .bb-capture-dismiss {\n position: fixed;\n top: 0px;\n right: 0px;\n z-index: ").concat(2147483618,";\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n width: 36px;\n height: 36px;\n display: flex;\n justify-content: center;\n align-items: center;\n background-color: ").concat(e,";\n border-bottom-left-radius: ").concat(C,"px;\n }\n\n [dir=rtl] .bb-capture-dismiss {\n top: 0px;\n left: 0px;\n right: auto;\n border-bottom-left-radius: 0px !important;\n border-bottom-right-radius: ").concat(C,"px;\n }\n \n .bb-capture-dismiss svg path {\n fill: ").concat(d,';\n }\n \n .bb-capture-dismiss svg {\n width: 20px;\n height: 20px;\n object-fit: contain;\n }\n \n .bb-capture-button-next {\n font-family: sans-serif;\n box-sizing: border-box;\n font-weight: 600;\n text-align: center;\n width: auto;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n margin: 0px;\n line-height: 36px;\n padding: 0px 12px;\n font-size: 15px;\n margin-left: 12px;\n }\n\n [dir=rtl].bb-capture-editor .bb-capture-button-next {\n margin-left: auto;\n margin-right: 12px;\n }\n \n .bb-capture-toolbar-item-spacer {\n width: 1px;\n height: 38px;\n min-width: 1px;\n margin: 0px 5px;\n }\n \n .bb-capture-toolbar-item {\n width: 42px;\n height: 38px;\n min-width: 42px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n position: relative;\n margin-right: 5px;\n }\n \n .bb-capture-toolbar-item svg {\n width: 23px;\n height: 23px;\n object-fit: contain;\n }\n \n .bb-capture-toolbar-item-selectedcolor {\n border-radius: 100%;\n width: 20px;\n height: 20px;\n background-color: #db4035;\n }\n \n .bb-capture-toolbar-item[data-type="undo"] svg {\n width: 18px;\n height: 18px;\n }\n \n .bb-capture-toolbar-item[data-active="true"] {\n position: relative;\n }\n \n .bb-capture-preview {\n display: none;\n background-color: rgba(0, 0, 0, 0.6);\n position: fixed;\n top: 0px;\n left: 0px;\n width: 100vw;\n height: 100vh;\n justify-content: center;\n align-items: center;\n z-index: ').concat(2147483620,";\n }\n \n .bb-capture-preview-inner {\n background-color: #fff;\n padding: 0px;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15), 0px 0px 20px rgba(0, 0, 0, 0.1);\n border-radius: 8px;\n flex-direction: column;\n max-width: 640px;\n width: 100%;\n margin: 20px;\n }\n \n .bb-capture-preview-inner video {\n border-radius: 8px 8px 0px 0px;\n display: block;\n border: 0px;\n outline: none;\n width: 100%;\n max-height: 60vh;\n }\n \n .bb-capture-preview-buttons {\n display: flex;\n justify-content: space-between;\n padding: 14px;\n }\n \n .bb-capture-preview-retrybutton {\n font-family: sans-serif;\n border-radius: 21px;\n box-sizing: border-box;\n padding: 12px 26px;\n font-size: 16px;\n line-height: 19px;\n font-weight: 600;\n text-align: center;\n margin-top: 0px;\n margin-bottom: 0px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n \n .bb-capture-preview-sendbutton {\n font-family: sans-serif;\n border-radius: 21px;\n box-sizing: border-box;\n padding: 12px 26px;\n font-size: 16px;\n line-height: 19px;\n font-weight: 600;\n text-align: center;\n margin-top: 0px;\n margin-bottom: 0px;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n \n .bb-capture-preview-retrybutton:hover,\n .bb-capture-preview-sendbutton:hover {\n opacity: 0.9;\n }\n \n .bb-capture-toolbar-item-recording {\n margin-right: 0px;\n }\n \n .bb-capture-toolbar-item-recording svg {\n width: 33px;\n height: 33px;\n }\n \n .bb-capture-toolbar-item-colorpicker {\n position: fixed;\n top: 70px;\n left: 50%;\n transform: translateX(-50%);\n z-index: ").concat(2147483618,';\n background-color: #fff;\n display: none;\n padding: 10px;\n box-shadow: 0px 1px 3px rgba(0, 0, 0, 0.15), 0px 0px 20px rgba(0, 0, 0, 0.1);\n border-radius: 8px;\n }\n \n .bb-capture-toolbar-item-color {\n width: 20px;\n height: 20px;\n border-radius: 100%;\n margin-right: 12px;\n box-shadow: 0px 0px 3px rgba(0, 0, 0, 0.15);\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n }\n \n .bb-capture-toolbar-item-color:hover {\n box-shadow: 0px 0px 6px rgba(0, 0, 0, 0.25);\n }\n \n .bb-capture-toolbar-item-color:last-of-type {\n margin-right: 0px;\n }\n \n [dir=rtl].bb-capture-editor .bb-capture-toolbar-item-color {\n margin-right: auto;\n margin-left: 12px;\n }\n \n [dir=rtl].bb-capture-editor .bb-capture-toolbar-item-color:last-of-type {\n margin-right: auto;\n margin-left: 0px;\n }\n \n .bb-capture-toolbar-item-recording[data-active="true"] svg:first-of-type {\n display: none;\n }\n \n .bb-capture-toolbar-item-recording[data-active="true"] svg:nth-of-type(2) {\n display: block;\n }\n \n .bb-capture-toolbar-item-recording[data-active="false"] svg:first-of-type {\n display: block;\n }\n \n .bb-capture-toolbar-item-recording[data-active="false"] svg:nth-of-type(2) {\n display: none;\n }\n \n .bb-capture-toolbar-item--active {\n background-color: #eee;\n }\n \n .bb-capture-toolbar-item:hover svg {\n opacity: 1;\n }\n \n .bb-capture-toolbar-item--active {\n background-color: #f8f8f8;\n }\n \n .bb-capture-toolbar-item--active svg {\n opacity: 1;\n }\n \n .bb-capture-toolbar-item--inactivecross::before {\n content: "";\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n height: 3px;\n width: 26px;\n margin: auto;\n border-radius: 4px;\n background-color: #e80000;\n transform: rotate(45deg);\n }\n \n .bb-capture-toolbar-item--inactivecross svg {\n fill: #eee;\n }\n \n .bb-capture-toolbar-item-timer {\n text-align: left;\n line-height: 32px;\n font-size: 14px;\n font-family: sans-serif;\n margin: 5px;\n min-width: 40px;\n display: none;\n }\n \n .bb-capture-toolbar-item .bb-tooltip {\n background-color: #555;\n color: #fff;\n visibility: hidden;\n font-size: 14px;\n font-family: sans-serif;\n text-align: center;\n padding: 5px 10px;\n position: absolute;\n z-index: 1;\n top: 45px;\n left: 0px;\n transform: translateX(calc(-50% + 21px));\n opacity: 0;\n transition: opacity 0.3s;\n white-space: nowrap;\n }\n \n .bb-capture-toolbar-item .bb-tooltip::after {\n content: "";\n position: absolute;\n bottom: 100%;\n left: 50%;\n margin-left: -5px;\n border-width: 5px;\n border-style: solid;\n transform: rotate(180deg);\n border-color: #555 transparent transparent transparent;\n }\n \n .bb-capture-toolbar-item:hover .bb-tooltip {\n visibility: visible;\n opacity: 1;\n }\n \n .bb-capture-options {\n display: none;\n }\n \n .bb-capture-options--active {\n display: flex;\n }\n\n @keyframes bbFadeOutRight {\n from {\n opacity: 1;\n }\n \n to {\n opacity: 0;\n }\n }\n \n @keyframes bbFadeOutDown {\n from {\n opacity: 1;\n }\n \n to {\n opacity: 0;\n transform: translate3d(0, 100%, 0);\n }\n }\n \n @keyframes bbFadeInOpacity {\n from {\n opacity: 0;\n }\n \n to {\n opacity: 1;\n }\n }\n \n @keyframes bbZoomOut {\n from {\n opacity: 1;\n }\n \n 50% {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n \n to {\n opacity: 0;\n }\n }\n \n @keyframes bbZoomIn {\n from {\n opacity: 0;\n transform: scale3d(0.3, 0.3, 0.3);\n }\n \n 50% {\n opacity: 1;\n }\n }\n \n @keyframes bbRecIconContFade {\n 0% {\n fill: #b10802;\n }\n 50% {\n fill: #ff0000;\n }\n 100% {\n fill: #b10802;\n }\n } \n .bb-capture-preview-retrybutton {\n color: ').concat(f,";\n border-radius: ").concat(w,"px;\n background-color: ").concat(y,";\n }\n .bb-capture-preview-retrybutton:hover {\n background-color: ").concat(b,";\n }\n @keyframes bb-suc-fill {\n 100% {\n box-shadow: inset 0px 0px 0px 30px ").concat(e,";\n }\n }\n .bb-capture-toolbar-item-spacer {\n background-color: ").concat(y,";\n }\n .bb-tooltip {\n border-radius: ").concat(S,"px;\n }\n @keyframes bbRecIconFade {\n 0% {\n fill: transparent;\n }\n 50% {\n fill: ").concat(b,";\n }\n 100% {\n fill: transparent;\n }\n }\n .bb-capture-preview-sendbutton {\n color: ").concat(d,";\n background-color: ").concat(e,";\n border-radius: ").concat(w,"px;\n }\n .bb-capture-button-next {\n color: ").concat(d,";\n background-color: ").concat(e,";\n border-radius: ").concat(C,"px;\n }\n .bb-capture-preview-inner {\n background-color: ").concat(a,";\n border-radius: ").concat(S,"px;\n }\n .bb-capture-toolbar-item-timer {\n color: ").concat(v,";\n }\n .bb-svg-path {\n fill: ").concat(f,";\n }\n .bb-capture-toolbar-item {\n border-radius: ").concat(S,"px;\n }\n .bb-capture-toolbar {\n background-color: ").concat(a,";\n border-radius: ").concat(S,"px;\n }\n .bb-capture-toolbar-item-colorpicker {\n background-color: ").concat(a,";\n }\n .bb-capture-toolbar-item--active {\n background-color: ").concat(y,";\n }\n .bb-feedback-button-classic {\n border-top-left-radius: ").concat(S,"px;\n border-top-right-radius: ").concat(S,"px;\n }\n .bb-logo-logo--default path {\n fill: ").concat(p,";\n }\n .bb-logo-arrowdown {\n fill: ").concat(p,";\n }\n .bb-feedback-button-icon {\n background-color: ").concat(n,";\n }\n .bb-feedback-button-classic {\n background-color: ").concat(n,";\n color: ").concat(p,";\n }\n\n @media only screen and (max-width: 450px) {\n [dir=rtl].gleap-frame-container,\n .gleap-frame-container {\n left: 0px;\n right: 0px;\n width: 100vw;\n max-width: 100vw;\n min-height: 100vh;\n min-height: -webkit-fill-available;\n max-height: -webkit-fill-available;\n top: 0px;\n bottom: 0px;\n border-radius: 0px;\n animation-name: gleapFadeInUpMobile;\n }\n\n .gleap-frame-container-inner {\n width: 100vw;\n height: 100%;\n }\n\n .gleap-frame-container:not(.gleap-frame-container--survey):not(.gleap-frame-container--survey-full) .gleap-frame-container-inner {\n max-height: calc(var(--glvh, 1vh) * 100) !important;\n }\n\n .gleap-frame-container--survey {\n height: auto !important;\n top: initial !important;\n bottom: 0px !important;\n min-height: initial !important;\n }\n\n .gleap-frame-container--survey .gleap-frame-container-inner {\n height: 100vh !important;\n }\n\n .bb-tooltip {\n display: none !important;\n }\n \n .bb-capture-toolbar-item-colorpicker {\n top: 75px;\n }\n \n .bb-capture-button-next {\n margin-left: auto;\n }\n \n .bb-capture-dismiss {\n display: none;\n }\n \n .bb-capture-toolbar {\n top: 15px;\n right: 15px;\n left: 15px;\n width: auto;\n transform: none;\n }\n\n .bb-capture-editor-drag-info {\n display: none;\n }\n \n .bb-capture-editor-borderlayer {\n border-width: 4px;\n }\n }\n \n @media print {\n .bb-feedback-button {\n display: none !important;\n }\n \n .gleap-frame-container {\n display: none !important;\n }\n }\n\n .gleap-tour-sender {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n margin-bottom: 20px;\n }\n\n .gleap-tour-sender-image {\n width: 32px;\n height: 32px;\n border-radius: 32px;\n margin-right: 10px;\n background-size: cover;\n background-repeat: no-repeat;\n }\n\n .gleap-tour-popover.gleap-tour-popover-post {\n min-width: 550px;\n max-width: 550px;\n }\n\n @media only screen and (max-width: 450px) {\n .gleap-tour-popover.gleap-tour-popover-post {\n min-width: calc(100vw - 40px);\n max-width: calc(100vw - 40px);\n }\n }\n\n .gleap-tour-message,\n .gleap-tour-message p,\n .gleap-tour-message ul {\n color: ").concat(f,";\n }\n\n .gleap-tour-message p {\n line-height: 1.3;\n }\n\n .gleap-tour-message ul {\n line-height: 1.3;\n padding-left: 20px;\n margin-top: 10px;\n margin-bottom: 10px;\n }\n\n .gleap-tour-message {\n max-height: calc(80vh - 100px) !important;\n overflow-y: auto;\n min-width: 270px;\n }\n\n .gleap-tour-message iframe {\n width: 100%;\n height: 300px;\n margin-top: 10px;\n margin-bottom: 10px;\n border: none;\n outline: none;\n display: block;\n }\n\n .gleap-tour-sender-name {\n font-size: 15px;\n }\n\n .gleap-tour-video {\n width: 100%;\n max-width: 100%;\n }\n\n .gleap-tour-video--playing .gleap-tour-video-playpause {\n opacity: 0;\n }\n \n .gleap-tour-video--playing:hover .gleap-tour-video-playpause {\n opacity: 1;\n }\n\n .gleap-tour-popover-video-pointer {\n padding: 0px !important;\n border-radius: 8px;\n position: relative;\n background-color: transparent !important;\n }\n\n .gleap-tour-popover-video-pointer .gleap-tour-popover-footer {\n position: absolute;\n top: 0px;\n left: 20px;\n right: 20px;\n opacity: 0;\n transition: opacity 200ms ease-in-out;\n }\n\n .gleap-tour-popover-video-pointer .gleap-tour-popover-footer button {\n padding: 5px 12px;\n }\n\n .gleap-tour-popover-video-pointer.gleap-tour-popover-can-close .gleap-tour-popover-footer {\n right: 40px !important;\n }\n\n .gleap-tour-popover-video-pointer:hover .gleap-tour-popover-footer {\n opacity: 1;\n }\n\n .gleap-tour-popover-pointer.gleap-tour-popover-no-sender .gleap-tour-message {\n padding-right: 20px;\n }\n\n .gleap-tour-video video {\n width: 100%;\n max-width: 100%;\n height: auto;\n border: none;\n outline: none;\n display: block;\n border-radius: 8px;\n }\n\n .gleap-admin-collapse-ui {\n z-index: ").concat(2147483635,";\n cursor: pointer;\n position: fixed;\n bottom: 75px;\n right: 20px;\n width: 32px;\n height: 32px;\n border-radius: 100%;\n background-color: #fff;\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: rgba(0, 0, 0, 0.16) 0px 10px 36px 0px, rgba(0, 0, 0, 0.06) 0px 0px 0px 1px;\n }\n\n .gleap-admin-collapse-ui svg {\n width: 20px;\n height: 14px;\n margin-top: 6px;\n fill: #000 !important;\n }\n\n .gleap-admin-collapse-ui-active {\n bottom: 20px !important;\n }\n\n .gleap-admin-collapse-ui-active svg {\n transform: rotate(180deg);\n }\n\n .gleap-admin-frame-container-active {\n display: none !important;\n }\n\n .gleap-admin-frame-container {\n position: fixed;\n bottom: 0px;\n left: 0px;\n right: 0px;\n width: 100vw;\n z-index: ").concat(2147483640,";\n }\n\n .gleap-admin-frame {\n width: 100%;\n height: 100%;\n border: none;\n outline: none;\n display: block;\n }\n \n .gleap-tour-message .linktype-link {\n display: inline-block !important;\n background-color: transparent !important;\n color: ").concat(n," !important;\n }\n\n .gleap-tooltip .linktype-button,\n .gleap-tour-message .linktype-button {\n display: inline-block !important;\n border-radius: 5px;\n box-sizing: border-box;\n padding: 10px 20px !important;\n text-decoration: none !important;\n background-color: ").concat(n," !important;\n color: ").concat(p," !important;\n }\n\n .gleap-tour-message img {\n width: 100%;\n max-width: 100%;\n min-height: 260px;\n height: auto;\n margin-top: 10px;\n margin-bottom: 10px;\n object-fit: cover;\n }\n\n .gleap-tour-active .gleap-tour-overlay {\n pointer-events: none;\n }\n \n .gleap-tour-active * {\n pointer-events: none;\n }\n \n .gleap-tour-active .gleap-tour-active-element,\n .gleap-tour-active .gleap-tour-active-element *,\n .gleap-tour-popover,\n .gleap-tour-popover * {\n pointer-events: auto;\n }\n \n @keyframes animate-fade-in {\n 0% {\n opacity: 0;\n }\n \n to {\n opacity: 1;\n }\n }\n \n .gleap-tour-fade .gleap-tour-overlay {\n animation: animate-fade-in 200ms ease-in-out;\n }\n \n .gleap-tour-fade .gleap-tour-popover {\n animation: animate-fade-in 200ms;\n }\n\n .gleap-tour-video-playpause {\n position: absolute;\n top: 0px;\n left: 0px;\n right: 0px;\n width: 100%;\n height: 100%;\n background-color: rgba(0,0,0,0.5);\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n border-radius: 8px;\n transition: opacity 200ms ease-in-out;\n }\n\n .gleap-tour-popover-video-pointer .gleap-tour-popover-arrow {\n display: none !important;\n }\n\n .gleap-tour-video-playpause svg {\n width: 34px;\n height: auto;\n fill: #fff;\n }\n \n /* Popover styles */\n .gleap-tour-popover {\n all: unset;\n box-sizing: border-box;\n color: #2d2d2d;\n margin: 0;\n padding: 15px;\n border-radius: ").concat(S,'px;\n min-width: 250px;\n max-width: 300px;\n box-shadow: 0 1px 10px #0006;\n z-index: 1000000000;\n position: fixed;\n top: 0;\n right: 0;\n background-color: #fff;\n }\n \n .gleap-tour-popover * {\n font-family: "Helvetica Neue", Inter, ui-sans-serif, "Apple Color Emoji", Helvetica, Arial, sans-serif;\n }\n \n .gleap-tour-popover-title {\n font: 19px / normal sans-serif;\n font-weight: 700;\n display: block;\n position: relative;\n line-height: 1.5;\n zoom: 1;\n margin: 0;\n }\n \n .gleap-tour-popover-close-btn {\n all: unset;\n position: absolute;\n top: 5px;\n right: 5px;\n width: 32px;\n height: 32px;\n cursor: pointer;\n font-size: 30px;\n font-weight: 500;\n line-height: 32px;\n color: #d2d2d2;\n z-index: 1;\n text-align: center;\n transition: color;\n transition-duration: 200ms;\n }\n \n .gleap-tour-popover-close-btn:hover,\n .gleap-tour-popover-close-btn:focus {\n color: #2d2d2d;\n }\n \n .gleap-tour-popover-title[style*="block"] + .gleap-tour-popover-description {\n margin-top: 5px;\n }\n \n .gleap-tour-popover-description {\n margin-bottom: 0;\n font: 15px / normal sans-serif;\n line-height: 1.5;\n font-weight: 400;\n zoom: 1;\n }\n \n .gleap-tour-popover-footer {\n margin-top: 15px;\n text-align: right;\n zoom: 1;\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n \n .gleap-tour-popover-progress-text {\n font-size: 13px;\n font-weight: 400;\n color: #727272;\n zoom: 1;\n }\n \n .gleap-tour-popover-footer button {\n background-color: ').concat(e,";\n color: ").concat(d,";\n border-radius: ").concat(C,"px;\n box-sizing: border-box;\n padding: 10px 20px;\n font-size: 14px;\n font-weight: bold;\n line-height: 21px;\n border: none;\n text-align: center;\n cursor: pointer;\n -webkit-tap-highlight-color: transparent;\n display: flex;\n justify-content: center;\n align-items: center;\n box-shadow: none !important;\n outline: none !important;\n }\n\n .gleap-tour-popover-prev-btn {\n color: ").concat(f," !important;\n background-color: ").concat(y," !important;\n margin-right: 3px;\n }\n\n .gleap-tour-popover-prev-btn:hover {\n background-color: ").concat(e,"22 !important;\n color: ").concat(e,' !important;\n }\n \n .gleap-tour-popover-footer .gleap-tour-popover-btn-disabled {\n opacity: 0.5;\n pointer-events: none;\n }\n \n /* Disable the scrolling of parent element if it has an active element*/\n :not(body):has(> .gleap-tour-active-element) {\n overflow: hidden !important;\n }\n \n .gleap-tour-no-interaction, .gleap-tour-no-interaction * {\n pointer-events: none !important;\n }\n \n .gleap-tour-popover-navigation-btns {\n display: flex;\n flex-grow: 1;\n justify-content: flex-end;\n }\n \n .gleap-tour-popover-navigation-btns button + button {\n margin-left: 4px;\n }\n \n .gleap-tour-popover-arrow {\n content: "";\n position: absolute;\n border: 5px solid #fff;\n }\n \n .gleap-tour-popover-arrow-side-over {\n display: none;\n }\n \n /** Popover Arrow Sides **/\n .gleap-tour-popover-arrow-side-left {\n left: 100%;\n border-right-color: transparent;\n border-bottom-color: transparent;\n border-top-color: transparent;\n }\n \n .gleap-tour-popover-arrow-side-right {\n right: 100%;\n border-left-color: transparent;\n border-bottom-color: transparent;\n border-top-color: transparent;\n }\n \n .gleap-tour-popover-arrow-side-top {\n top: 100%;\n border-right-color: transparent;\n border-bottom-color: transparent;\n border-left-color: transparent;\n }\n \n .gleap-tour-popover-arrow-side-bottom {\n bottom: 100%;\n border-left-color: transparent;\n border-top-color: transparent;\n border-right-color: transparent;\n }\n \n .gleap-tour-popover-arrow-side-center {\n display: none;\n }\n \n /* Left/Start + Right/Start */\n .gleap-tour-popover-arrow-side-left.gleap-tour-popover-arrow-align-start,\n .gleap-tour-popover-arrow-side-right.gleap-tour-popover-arrow-align-start {\n top: 15px;\n }\n \n /* Top/Start + Bottom/Start */\n .gleap-tour-popover-arrow-side-top.gleap-tour-popover-arrow-align-start,\n .gleap-tour-popover-arrow-side-bottom.gleap-tour-popover-arrow-align-start {\n left: 15px;\n }\n \n /* End/Left + End/Right */\n .gleap-tour-popover-arrow-align-end.gleap-tour-popover-arrow-side-left,\n .gleap-tour-popover-arrow-align-end.gleap-tour-popover-arrow-side-right {\n bottom: 15px;\n }\n \n /* Top/End + Bottom/End */\n .gleap-tour-popover-arrow-side-top.gleap-tour-popover-arrow-align-end,\n .gleap-tour-popover-arrow-side-bottom.gleap-tour-popover-arrow-align-end {\n right: 15px;\n }\n \n /* Left/Center + Right/Center */\n .gleap-tour-popover-arrow-side-left.gleap-tour-popover-arrow-align-center,\n .gleap-tour-popover-arrow-side-right.gleap-tour-popover-arrow-align-center {\n top: 50%;\n margin-top: -5px;\n }\n \n /* Top/Center + Bottom/Center */\n .gleap-tour-popover-arrow-side-top.gleap-tour-popover-arrow-align-center,\n .gleap-tour-popover-arrow-side-bottom.gleap-tour-popover-arrow-align-center {\n left: 50%;\n margin-left: -5px;\n }\n \n /* No arrow */\n .gleap-tour-popover-arrow-none {\n display: none;\n } \n '),L=document.querySelector(".gleap-styles");L&&L.remove();var I=document.createElement("style");I.innerHTML=T,I.className="gleap-styles",document.body.appendChild(I)}(e,t,n,a,r,i,s,u)}))}},{key:"sendSilentCrashReport",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:"",n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"MEDIUM",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{screenshot:!0,replays:!0,attachments:!0};return e.sendSilentCrashReportWithFormData({description:t},n,r)}},{key:"sendSilentCrashReportWithFormData",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"MEDIUM",r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{screenshot:!0,replays:!0,attachments:!0};if(!this.silentCrashReportSent){this.silentCrashReportSent=!0,setTimeout((function(){t.silentCrashReportSent=!1}),1e4);var o=r?x(r):{},a=qe.getInstance();if(a.ready){var i=e||{};a.session.email&&(i.reportedBy=a.session.email),new kt("CRASH",n,i,!0,o).sendFeedback().then((function(){})).catch((function(e){}))}}}},{key:"showSurvey",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"survey";e.startFeedbackFlowWithOptions(t,{hideBackButton:!0,format:n},!0)}},{key:"startClassicForm",value:function(t,n){e.startFeedbackFlowWithOptions(t,{hideBackButton:!n})}},{key:"startFeedbackFlow",value:function(t,n){e.startFeedbackFlowWithOptions(t,{hideBackButton:!n})}},{key:"startFeedbackFlowWithOptions",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},r=arguments.length>2&&void 0!==arguments[2]&&arguments[2],o=n.autostartDrawing,a=n.hideBackButton,i=n.format;if(qe.getInstance().ready){e.getInstance().setGlobalDataItem("snapshotPosition",{x:window.scrollX,y:window.scrollY});var s="start-feedbackflow";r&&(s="start-survey"),It.getInstance().setAppMode(r?i:"widget"),It.getInstance().sendMessage({name:s,data:{flow:t,hideBackButton:a,format:i}},!0),o?It.getInstance().showDrawingScreen("screenshot"):It.getInstance().showWidget()}}},{key:"openConversations",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-conversations",data:{hideBackButton:!e}},!0),It.getInstance().showWidget()}},{key:"openConversation",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-conversation",data:{shareToken:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"startConversation",value:function(){var t=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];e.startBot("",t)}},{key:"startBot",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"start-bot",data:{botId:e||"",hideBackButton:!t}},!0),It.getInstance().showWidget()}},{key:"openHelpCenterCollection",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-help-collection",data:{collectionId:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"openHelpCenterArticle",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-help-article",data:{articleId:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"openHelpCenter",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-helpcenter",data:{hideBackButton:!e}},!0),It.getInstance().showWidget()}},{key:"searchHelpCenter",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-helpcenter-search",data:{term:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"openNewsArticle",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-news-article",data:{id:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"openChecklists",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-checklists",data:{hideBackButton:!e}},!0),It.getInstance().showWidget()}},{key:"startChecklist",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];return!!e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"start-checklist",data:{outboundId:e,hideBackButton:!t}},!0),It.getInstance().showWidget(),!0)}},{key:"openChecklist",value:function(e){var t=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];e&&(It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-checklist",data:{id:e,hideBackButton:!t}},!0),It.getInstance().showWidget())}},{key:"openNews",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-news",data:{hideBackButton:!e}},!0),It.getInstance().showWidget()}},{key:"openFeatureRequests",value:function(){var e=!(arguments.length>0&&void 0!==arguments[0])||arguments[0];It.getInstance().setAppMode("widget"),It.getInstance().sendMessage({name:"open-feature-requests",data:{hideBackButton:!e}},!0),It.getInstance().showWidget()}},{key:"startProductTour",value:function(e){var t=this;qe.getInstance().startProductTourConfig(e).then((function(n){t.startProductTourWithConfig(e,n)})).catch((function(e){}))}},{key:"startProductTourWithConfig",value:function(t,n){ro.getInstance().startWithConfig(t,n,(function(t){var n={tourId:t.tourId};rn.notifyEvent("productTourCompleted",n),e.trackEvent("tour-".concat(t.tourId,"-completed"),n)}))}},{key:"showBanner",value:function(e){try{vr.getInstance().showBanner(e)}catch(t){}}},{key:"showNotification",value:function(e){ur.getInstance().showNotification(e)}}],n&&ao(t.prototype,n),r&&ao(t,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();if(lo(uo,"invoked",!0),lo(uo,"silentCrashReportSent",!1),lo(uo,"instance",void 0),"undefined"!=typeof window){var po=window.GleapActions;if(po&&po.length>0)for(var fo=0;fo{y.initialize("dyWs3yourDQZkNztYzV7yZgcyMcWGpaF")}),[]),(0,b.jsx)(b.Fragment,{children:t})}var x=n(74650),k=n(30340),S=n(94887),C=n(13929),E=n(64204),T=n(98878),L=n(4715),I=n(70622),A=n(78946),O=n(43926);function _(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,k.A)(),r=(0,T.o)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,b.jsxs)(x.A,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,b.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,b.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,b.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,b.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function P(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,k.A)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,k.A)(),{pathname:r}=(0,p.zy)();return e+(0,A.applyTrailingSlash)((0,S.Ay)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,b.jsxs)(x.A,{children:[(0,b.jsx)("meta",{property:"og:url",content:o}),(0,b.jsx)("link",{rel:"canonical",href:o})]})}function M(){const{i18n:{currentLocale:e}}=(0,k.A)(),{metadata:t,image:n}=(0,C.p)();return(0,b.jsxs)(b.Fragment,{children:[(0,b.jsxs)(x.A,{children:[(0,b.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,b.jsx)("body",{className:L.w})]}),n&&(0,b.jsx)(E.be,{image:n}),(0,b.jsx)(P,{}),(0,b.jsx)(_,{}),(0,b.jsx)(O.A,{tag:I.Cy,locale:e}),(0,b.jsx)(x.A,{children:t.map(((e,t)=>(0,b.jsx)("meta",{...e},t)))})]})}const R=new Map;var N=n(95143),j=n(5775),D=n(89871);function F(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const B=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,D.A)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),F("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function z(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,f.u)(d.A,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class U extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=c.A.canUseDOM?F("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=F("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),z(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,b.jsx)(B,{previousLocation:this.previousLocation,location:t,children:(0,b.jsx)(p.qh,{location:t,render:()=>e})})}}const q=U,H="__docusaurus-base-url-issue-banner-container",W="__docusaurus-base-url-issue-banner",$="__docusaurus-base-url-issue-banner-suggestion-container";function G(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${H}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{let{route:t}=e;return!0===t.exact})))return R.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return R.set(e.pathname,t),{...e,pathname:t}}((0,p.zy)());return(0,b.jsx)(q,{location:e,children:Q})}function te(){return(0,b.jsx)(Y.A,{children:(0,b.jsx)(j.l,{children:(0,b.jsxs)(N.x,{children:[(0,b.jsxs)(w,{children:[(0,b.jsx)(Z,{}),(0,b.jsx)(M,{}),(0,b.jsx)(K,{}),(0,b.jsx)(ee,{})]}),(0,b.jsx)(J,{})]})})})}var ne=n(84054);const re=function(e){try{return document.createElement("link").relList.supports(e)}catch{return!1}}("prefetch")?function(e){return new Promise(((t,n)=>{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var oe=n(7771);const ae=new Set,ie=new Set,se=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,le={prefetch:e=>{if(!(e=>!se()&&!ie.has(e)&&!ae.has(e))(e))return!1;ae.add(e);const t=(0,f.u)(d.A,e).flatMap((e=>{return t=e.route.path,Object.entries(ne).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,oe.A)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?re(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!se()&&!ie.has(e))(e)&&(ie.add(e),z(e))},ce=Object.freeze(le);function ue(e){let{children:t}=e;return"hash"===l.default.future.experimental_router?(0,b.jsx)(i.I9,{children:t}):(0,b.jsx)(i.Kd,{children:t})}const de=Boolean(!0);if(c.A.canUseDOM){window.docusaurus=ce;const e=document.getElementById("__docusaurus"),t=(0,b.jsx)(a.vd,{children:(0,b.jsx)(ue,{children:(0,b.jsx)(te,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},i=()=>{if(window.docusaurusRoot)window.docusaurusRoot.render(t);else if(de)window.docusaurusRoot=o.hydrateRoot(e,t,{onRecoverableError:n});else{const r=o.createRoot(e,{onRecoverableError:n});r.render(t),window.docusaurusRoot=r}};z(window.location.pathname).then((()=>{(0,r.startTransition)(i)}))}},5775:(e,t,n)=>{"use strict";n.d(t,{o:()=>d,l:()=>p});var r=n(30758),o=n(4784);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"docs":{"path":"/docs","versions":[{"name":"current","label":"Next","isLast":true,"path":"/docs","mainDocId":"index","docs":[{"id":"concepts/architecture/index","path":"/docs/concepts/architecture/","sidebar":"docs"},{"id":"concepts/comparisons/index","path":"/docs/concepts/comparisons/","sidebar":"docs"},{"id":"concepts/features-overview/index","path":"/docs/concepts/features-overview/","sidebar":"docs"},{"id":"concepts/mental-model/index","path":"/docs/concepts/mental-model/","sidebar":"docs"},{"id":"concepts/RFCs/index","path":"/docs/concepts/RFCs/","sidebar":"docs"},{"id":"concepts/RFCs/M0-template","path":"/docs/concepts/RFCs/M0-template","sidebar":"docs"},{"id":"guides/contributing","path":"/docs/guides/contributing","sidebar":"docs"},{"id":"guides/external-functions/index","path":"/docs/guides/external-functions/","sidebar":"docs"},{"id":"guides/files-upload/index","path":"/docs/guides/files-upload/","sidebar":"docs"},{"id":"guides/import-external-modules/index","path":"/docs/guides/import-external-modules/","sidebar":"docs"},{"id":"guides/programmatic-deployment/index","path":"/docs/guides/programmatic-deployment/","sidebar":"docs"},{"id":"guides/rest/index","path":"/docs/guides/rest/","sidebar":"docs"},{"id":"guides/securing-requests/index","path":"/docs/guides/securing-requests/","sidebar":"docs"},{"id":"guides/self-hosting","path":"/docs/guides/self-hosting","sidebar":"docs"},{"id":"guides/test-your-typegraph/index","path":"/docs/guides/test-your-typegraph/","sidebar":"docs"},{"id":"guides/wasm-functions/index","path":"/docs/guides/wasm-functions/","sidebar":"docs"},{"id":"index","path":"/docs/","sidebar":"docs"},{"id":"reference/changelog","path":"/docs/reference/changelog","sidebar":"docs"},{"id":"reference/ecosystem/index","path":"/docs/reference/ecosystem/","sidebar":"docs"},{"id":"reference/meta-cli/available-commands","path":"/docs/reference/meta-cli/available-commands","sidebar":"docs"},{"id":"reference/meta-cli/configuration-file","path":"/docs/reference/meta-cli/configuration-file","sidebar":"docs"},{"id":"reference/meta-cli/embedded-typegate/index","path":"/docs/reference/meta-cli/embedded-typegate/","sidebar":"docs"},{"id":"reference/meta-cli/index","path":"/docs/reference/meta-cli/","sidebar":"docs"},{"id":"reference/metagen/index","path":"/docs/reference/metagen/","sidebar":"docs"},{"id":"reference/policies/index","path":"/docs/reference/policies/","sidebar":"docs"},{"id":"reference/rest/index","path":"/docs/reference/rest/","sidebar":"docs"},{"id":"reference/runtimes/deno/index","path":"/docs/reference/runtimes/deno/","sidebar":"docs"},{"id":"reference/runtimes/graphql/index","path":"/docs/reference/runtimes/graphql/","sidebar":"docs"},{"id":"reference/runtimes/grpc/index","path":"/docs/reference/runtimes/grpc/","sidebar":"docs"},{"id":"reference/runtimes/http/index","path":"/docs/reference/runtimes/http/","sidebar":"docs"},{"id":"reference/runtimes/index","path":"/docs/reference/runtimes/","sidebar":"docs"},{"id":"reference/runtimes/kv/index","path":"/docs/reference/runtimes/kv/","sidebar":"docs"},{"id":"reference/runtimes/prisma/index","path":"/docs/reference/runtimes/prisma/","sidebar":"docs"},{"id":"reference/runtimes/python/index","path":"/docs/reference/runtimes/python/","sidebar":"docs"},{"id":"reference/runtimes/random/index","path":"/docs/reference/runtimes/random/","sidebar":"docs"},{"id":"reference/runtimes/s3/index","path":"/docs/reference/runtimes/s3/","sidebar":"docs"},{"id":"reference/runtimes/substantial/index","path":"/docs/reference/runtimes/substantial/","sidebar":"docs"},{"id":"reference/runtimes/temporal/index","path":"/docs/reference/runtimes/temporal/","sidebar":"docs"},{"id":"reference/runtimes/wasm/index","path":"/docs/reference/runtimes/wasm/","sidebar":"docs"},{"id":"reference/typegate/authentication/index","path":"/docs/reference/typegate/authentication/","sidebar":"docs"},{"id":"reference/typegate/cors/index","path":"/docs/reference/typegate/cors/","sidebar":"docs"},{"id":"reference/typegate/index","path":"/docs/reference/typegate/","sidebar":"docs"},{"id":"reference/typegate/rate-limiting/index","path":"/docs/reference/typegate/rate-limiting/","sidebar":"docs"},{"id":"reference/typegate/synchronization/index","path":"/docs/reference/typegate/synchronization/","sidebar":"docs"},{"id":"reference/typegraph/client/index","path":"/docs/reference/typegraph/client/","sidebar":"docs"},{"id":"reference/typegraph/index","path":"/docs/reference/typegraph/","sidebar":"docs"},{"id":"reference/types/comparison","path":"/docs/reference/types/comparison","sidebar":"docs"},{"id":"reference/types/functions","path":"/docs/reference/types/functions","sidebar":"docs"},{"id":"reference/types/index","path":"/docs/reference/types/","sidebar":"docs"},{"id":"reference/types/injections","path":"/docs/reference/types/injections","sidebar":"docs"},{"id":"reference/types/parameter-transformations","path":"/docs/reference/types/parameter-transformations","sidebar":"docs"},{"id":"tutorials/metatype-basics/index","path":"/docs/tutorials/metatype-basics/","sidebar":"docs"},{"id":"tutorials/quick-start/index","path":"/docs/tutorials/quick-start/","sidebar":"docs"}],"draftIds":[],"sidebars":{"docs":{"link":{"path":"/docs/","label":"index"}}}}],"breadcrumbs":true},"use-cases":{"path":"/use-cases","versions":[{"name":"current","label":"Next","isLast":true,"path":"/use-cases","mainDocId":"automatic-crud-validation/index","docs":[{"id":"automatic-crud-validation/index","path":"/use-cases/automatic-crud-validation/","sidebar":"useCases"},{"id":"backend-for-frontend/index","path":"/use-cases/backend-for-frontend/","sidebar":"useCases"},{"id":"faas-runner/index","path":"/use-cases/faas-runner/","sidebar":"useCases"},{"id":"graphql-server/index","path":"/use-cases/graphql-server/","sidebar":"useCases"},{"id":"iam-provider/index","path":"/use-cases/iam-provider/","sidebar":"useCases"},{"id":"microservice-orchestration/index","path":"/use-cases/microservice-orchestration/","sidebar":"useCases"},{"id":"orm-for-the-edge/index","path":"/use-cases/orm-for-the-edge/","sidebar":"useCases"},{"id":"programmable-api-gateway/index","path":"/use-cases/programmable-api-gateway/","sidebar":"useCases"}],"draftIds":[],"sidebars":{"useCases":{"link":{"path":"/use-cases/automatic-crud-validation/","label":"Instant APIs on your database"}}}}],"breadcrumbs":true}},"docusaurus-lunr-search":{"default":{"fileNames":{"searchDoc":"search-doc-1730805184902.json","lunrIndex":"lunr-index-1730805184902.json"}}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var s=n(22654);const l=JSON.parse('{"docusaurusVersion":"3.4.0","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.4.0"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.4.0"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.4.0"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.4.0"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.4.0"},"docusaurus-plugin-sass":{"type":"package","name":"docusaurus-plugin-sass","version":"0.2.5"},"tailwindcss":{"type":"local"},"custom-code-loader":{"type":"local"},"posthog-docusaurus":{"type":"package","name":"posthog-docusaurus","version":"2.0.0"},"docusaurus-lunr-search":{"type":"package","name":"docusaurus-lunr-search","version":"3.4.0"},"docusaurus-theme-frontmatter":{"type":"package","name":"docusaurus-theme-frontmatter","version":"1.3.0"}}}');var c=n(86070);const u={siteConfig:o.default,siteMetadata:l,globalData:a,i18n:i,codeTranslations:s},d=r.createContext(u);function p(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},82017:(e,t,n)=>{"use strict";n.d(t,{A:()=>m});var r=n(30758),o=n(25283),a=n(74650),i=n(78946),s=n(22653),l=n(17832),c=n(86070);function u(e){let{error:t,tryAgain:n}=e;return(0,c.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,c.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,c.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,c.jsx)(d,{error:t})]})}function d(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,c.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function p(e){let{children:t}=e;return(0,c.jsx)(l.W,{value:{plugin:{name:"docusaurus-core-error-boundary",id:"default"}},children:t})}function f(e){let{error:t,tryAgain:n}=e;return(0,c.jsx)(p,{children:(0,c.jsxs)(m,{fallback:()=>(0,c.jsx)(u,{error:t,tryAgain:n}),children:[(0,c.jsx)(a.A,{children:(0,c.jsx)("title",{children:"Page Error"})}),(0,c.jsx)(s.A,{children:(0,c.jsx)(u,{error:t,tryAgain:n})})]})})}const h=e=>(0,c.jsx)(f,{...e});class m extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.A.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??h)(e)}return e??null}}},25283:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},74650:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(30758);var r=n(70248),o=n(86070);function a(e){return(0,o.jsx)(r.mg,{...e})}},92076:(e,t,n)=>{"use strict";n.d(t,{A:()=>f});var r=n(30758),o=n(41742),a=n(78946),i=n(30340),s=n(51716),l=n(25283),c=n(25880),u=n(94887),d=n(86070);function p(e,t){let{isNavLink:n,to:p,href:f,activeClassName:h,isActive:m,"data-noBrokenLinkCheck":g,autoAddBaseUrl:v=!0,...y}=e;const{siteConfig:b}=(0,i.A)(),{trailingSlash:w,baseUrl:x}=b,k=b.future.experimental_router,{withBaseUrl:S}=(0,u.hH)(),C=(0,c.A)(),E=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>E.current));const T=p||f;const L=(0,s.A)(T),I=T?.replace("pathname://","");let A=void 0!==I?(O=I,v&&(e=>e.startsWith("/"))(O)?S(O):O):void 0;var O;"hash"===k&&A?.startsWith("./")&&(A=A?.slice(1)),A&&L&&(A=(0,a.applyTrailingSlash)(A,{trailingSlash:w,baseUrl:x}));const _=(0,r.useRef)(!1),P=n?o.k2:o.N_,M=l.A.canUseIntersectionObserver,R=(0,r.useRef)(),N=()=>{_.current||null==A||(window.docusaurus.preload(A),_.current=!0)};(0,r.useEffect)((()=>(!M&&L&&null!=A&&window.docusaurus.prefetch(A),()=>{M&&R.current&&R.current.disconnect()})),[R,A,M,L]);const j=A?.startsWith("#")??!1,D=!y.target||"_self"===y.target,F=!A||!L||!D;return g||!j&&F||C.collectLink(A),y.id&&C.collectAnchor(y.id),F?(0,d.jsx)("a",{ref:E,href:A,...T&&!L&&{target:"_blank",rel:"noopener noreferrer"},...y}):(0,d.jsx)(P,{...y,onMouseEnter:N,onTouchStart:N,innerRef:e=>{E.current=e,M&&e&&L&&(R.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(R.current.unobserve(e),R.current.disconnect(),null!=A&&window.docusaurus.prefetch(A))}))})),R.current.observe(e))},to:A,...n&&{isActive:m,activeClassName:h}})}const f=r.forwardRef(p)},88237:(e,t,n)=>{"use strict";n.d(t,{A:()=>c,T:()=>l});var r=n(30758),o=n(86070);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(22654);function s(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function l(e,t){let{message:n,id:r}=e;return a(s({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=s({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},95163:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r="default"},51716:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{A:()=>o,z:()=>r})},94887:(e,t,n)=>{"use strict";n.d(t,{Ay:()=>s,hH:()=>i});var r=n(30758),o=n(30340),a=n(51716);function i(){const{siteConfig:e}=(0,o.A)(),{baseUrl:t,url:n}=e,i=e.future.experimental_router,s=(0,r.useCallback)(((e,r)=>function(e){let{siteUrl:t,baseUrl:n,url:r,options:{forcePrependBaseUrl:o=!1,absolute:i=!1}={},router:s}=e;if(!r||r.startsWith("#")||(0,a.z)(r))return r;if("hash"===s)return r.startsWith("/")?`.${r}`:`./${r}`;if(o)return n+r.replace(/^\//,"");if(r===n.replace(/\/$/,""))return n;const l=r.startsWith(n)?r:n+r.replace(/^\//,"");return i?t+l:l}({siteUrl:n,baseUrl:t,url:e,options:r,router:i})),[n,t,i]);return{withBaseUrl:s}}function s(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},25880:(e,t,n)=>{"use strict";n.d(t,{A:()=>i});var r=n(30758);n(86070);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},30340:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(30758),o=n(5775);function a(){return(0,r.useContext)(o.o)}},39646:(e,t,n)=>{"use strict";n.d(t,{P_:()=>i,kh:()=>a});var r=n(30340),o=n(95163);function a(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,r.A)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}function i(e,t,n){void 0===t&&(t=o.W),void 0===n&&(n={});const r=a(e),i=r?.[t];if(!i&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return i}},5197:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(30758),o=n(95143);function a(){return(0,r.useContext)(o.o)}},89871:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});var r=n(30758);const o=n(25283).A.canUseDOM?r.useLayoutEffect:r.useEffect},80053:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});var r=n(30758),o=n(17832);function a(){const e=r.useContext(o.o);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}},7771:(e,t,n)=>{"use strict";n.d(t,{A:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const s=o?`${o}.${a}`:a;r(i)?e(i,s):t[s]=i}))}(e),t}},17832:(e,t,n)=>{"use strict";n.d(t,{W:()=>i,o:()=>a});var r=n(30758),o=n(86070);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),s=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:s,children:t})}},62939:(e,t,n)=>{"use strict";n.d(t,{zK:()=>f,vT:()=>u,Gy:()=>l,HW:()=>h,ht:()=>c,r7:()=>p,jh:()=>d});var r=n(25557),o=n(39646);const a=e=>e.versions.find((e=>e.isLast));function i(e,t){const n=function(e,t){const n=a(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.B6)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),o=n?.docs.find((e=>!!(0,r.B6)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const s={},l=()=>(0,o.kh)("docusaurus-plugin-content-docs")??s,c=e=>{try{return(0,o.P_)("docusaurus-plugin-content-docs",e,{failfast:!0})}catch(t){throw new Error("You are using a feature of the Docusaurus docs plugin, but this plugin does not seem to be enabled"+("Default"===e?"":` (pluginId=${e}`),{cause:t})}};function u(e){void 0===e&&(e={});const t=l(),{pathname:n}=(0,r.zy)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.B6)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function d(e){return c(e).versions}function p(e){const t=c(e);return a(t)}function f(e){const t=c(e),{pathname:n}=(0,r.zy)();return i(t,n)}function h(e){const t=c(e),{pathname:n}=(0,r.zy)();return function(e,t){const n=a(e);return{latestDocSuggestion:i(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},57316:(e,t,n)=>{"use strict";function r(e,t){e.prototype=Object.create(t.prototype),e.prototype.constructor=e,e.__proto__=t}function o(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}function a(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(){return i=Object.assign||function(e){for(var t=1;t{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(58744),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},16636:(e,t,n)=>{"use strict";n.r(t);var r=n(63477),o=n(4784);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(1274),n(45433)(`./prism-${e}`)})),delete globalThis.Prism}(r.My)},55230:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(30758);var r=n(13526),o=n(88237),a=n(13929),i=n(92076),s=n(25880);const l={anchorWithStickyNavbar:"anchorWithStickyNavbar_gmPS",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_PA6j"};var c=n(86070);function u(e){let{as:t,id:n,...u}=e;const d=(0,s.A)(),{navbar:{hideOnScroll:p}}=(0,a.p)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const f=(0,o.T)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,c.jsxs)(t,{...u,className:(0,r.A)("anchor",p?l.anchorWithHideOnScrollNavbar:l.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.A,{className:"hash-link",to:`#${n}`,"aria-label":f,title:f,children:"\u200b"})]})}},20351:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(30758);const r={iconExternalLink:"iconExternalLink_oKM7"};var o=n(86070);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},22653:(e,t,n)=>{"use strict";n.d(t,{A:()=>yt});var r=n(30758),o=n(13526),a=n(82017),i=n(64204),s=n(25557),l=n(88237),c=n(35623),u=n(86070);const d="__docusaurus_skipToContent_fallback";function p(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function f(){const e=(0,r.useRef)(null),{action:t}=(0,s.W6)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&p(t)}),[]);return(0,c.$)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&p(e.current)})),{containerRef:e,onClick:n}}const h=(0,l.T)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function m(e){const t=e.children??h,{containerRef:n,onClick:r}=f();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":h,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(81274),v=n(4715);const y={skipToContent:"skipToContent_kkJt"};function b(){return(0,u.jsx)(m,{className:y.skipToContent})}var w=n(13929),x=n(67214);function k(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const S={closeButton:"closeButton_YMCa"};function C(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,l.T)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.A)("clean-btn close",S.closeButton,e.className),children:(0,u.jsx)(k,{width:14,height:14,strokeWidth:3.1})})}const E={content:"content_qw9T"};function T(e){const{announcementBar:t}=(0,w.p)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.A)(E.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const L={announcementBar:"announcementBar_sF1Y",announcementBarPlaceholder:"announcementBarPlaceholder_dCav",announcementBarClose:"announcementBarClose_tJzs",announcementBarContent:"announcementBarContent_H5Gj"};function I(){const{announcementBar:e}=(0,w.p)(),{isActive:t,close:n}=(0,x.M)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:L.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:L.announcementBarPlaceholder}),(0,u.jsx)(T,{className:L.announcementBarContent}),a&&(0,u.jsx)(C,{onClick:n,className:L.announcementBarClose})]})}var A=n(14491),O=n(793);var _=n(94259),P=n(831);const M=r.createContext(null);function R(e){let{children:t}=e;const n=function(){const e=(0,A.M)(),t=(0,P.YL)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,_.ZC)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(M.Provider,{value:n,children:t})}function N(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function j(){const e=(0,r.useContext)(M);if(!e)throw new _.dV("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,P.YL)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:N(a)})),[o,a,t])}function D(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=j();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.A)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var F=n(64322),B=n(5197);function z(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function U(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const q={toggle:"toggle_Zzz4",toggleButton:"toggleButton_k661",darkToggleIcon:"darkToggleIcon_WKry",lightToggleIcon:"lightToggleIcon_IKxN",toggleButtonDisabled:"toggleButtonDisabled_Gvex"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,B.A)(),s=(0,l.T)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,l.T)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,l.T)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.A)(q.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.A)("clean-btn",q.toggleButton,!i&&q.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:s,"aria-label":s,"aria-live":"polite",children:[(0,u.jsx)(z,{className:(0,o.A)(q.toggleIcon,q.lightToggleIcon)}),(0,u.jsx)(U,{className:(0,o.A)(q.toggleIcon,q.darkToggleIcon)})]})})}const W=r.memo(H),$={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_tYqz"};function G(e){let{className:t}=e;const n=(0,w.p)().navbar.style,r=(0,w.p)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,F.G)();return r?null:(0,u.jsx)(W,{className:t,buttonClassName:"dark"===n?$.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var V=n(67520);function K(){return(0,u.jsx)(V.A,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Z(){const e=(0,A.M)();return(0,u.jsx)("button",{type:"button","aria-label":(0,l.T)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(k,{color:"var(--ifm-color-emphasis-600)"})})}function Y(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(K,{}),(0,u.jsx)(G,{className:"margin-right--md"}),(0,u.jsx)(Z,{})]})}var X=n(92076),J=n(94887),Q=n(51716);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(20351);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:s,prependBaseUrlToHref:l,...c}=e;const d=(0,J.Ay)(r),p=(0,J.Ay)(t),f=(0,J.Ay)(o,{forcePrependBaseUrl:!0}),h=a&&o&&!(0,Q.A)(o),m=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,h&&(0,u.jsx)(te.A,{...s&&{width:12,height:12}})]})};return o?(0,u.jsx)(X.A,{href:l?f:o,...c,...m}):(0,u.jsx)(X.A,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(p)},...c,...m})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.A)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.A)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(53609),se=n(74768),le=n(30340);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_vUqO"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,se.ys)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...s}=e;const l=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{l.current&&!l.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[l]),(0,u.jsxs)("div",{ref:l,className:(0,o.A)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:s.to?void 0:"#",className:(0,o.A)("navbar__link",a),...s,onClick:s.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:s.children??s.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(Oe,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function pe(e){let{items:t,className:n,position:a,onClick:i,...l}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,le.A)(),{pathname:t}=(0,s.zy)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:p,toggleCollapsed:f,setCollapsed:h}=(0,ie.u)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&h(!d)}),[c,d,h]),(0,u.jsxs)("li",{className:(0,o.A)("menu__list-item",{"menu__list-item--collapsed":p}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.A)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...l,onClick:e=>{e.preventDefault(),f()},children:l.children??l.label}),(0,u.jsx)(ie.N,{lazy:!0,as:"ul",className:"menu__list",collapsed:p,children:t.map(((e,t)=>(0,r.createElement)(Oe,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function fe(e){let{mobile:t=!1,...n}=e;const r=t?pe:de;return(0,u.jsx)(r,{...n})}var he=n(98878);function me(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const ge="iconLanguage_J6eA";var ve=n(68835),ye=n(39646),be=n(91176),we=n.n(be);function xe(){const e=(0,s.zy)(),t=(0,s.W6)(),{siteConfig:{baseUrl:n}}=(0,le.A)(),[o,a]=(0,r.useState)({wordToHighlight:"",isTitleSuggestion:!1,titleText:""});return(0,r.useEffect)((()=>{if(!e.state?.highlightState||0===e.state.highlightState.wordToHighlight.length)return;a(e.state.highlightState);const{highlightState:n,...r}=e.state;t.replace({...e,state:r})}),[e.state?.highlightState,t,e]),(0,r.useEffect)((()=>{if(0===o.wordToHighlight.length)return;const e=document.getElementsByTagName("article")[0]??document.getElementsByTagName("main")[0];if(!e)return;const t=new(we())(e),n={ignoreJoiners:!0};return t.mark(o.wordToHighlight,n),()=>t.unmark(n)}),[o,n]),null}const ke=e=>{const t=(0,r.useRef)(!1),o=(0,r.useRef)(null),[a,i]=(0,r.useState)(!1),l=(0,s.W6)(),{siteConfig:c={}}=(0,le.A)(),d=(c.plugins||[]).find((e=>Array.isArray(e)&&"string"==typeof e[0]&&e[0].includes("docusaurus-lunr-search"))),p=(0,B.A)(),{baseUrl:f}=c,h=d&&d[1]?.assetUrl||f,m=(0,ye.P_)("docusaurus-lunr-search"),g=()=>{t.current||(Promise.all([fetch(`${h}${m.fileNames.searchDoc}`).then((e=>e.json())),fetch(`${h}${m.fileNames.lunrIndex}`).then((e=>e.json())),Promise.all([n.e(7570),n.e(8649)]).then(n.bind(n,26989)),Promise.all([n.e(1869),n.e(1963)]).then(n.bind(n,31963))]).then((e=>{let[t,n,{default:r}]=e;const{searchDocs:o,options:a}=t;o&&0!==o.length&&(((e,t,n,r)=>{new n({searchDocs:e,searchIndex:t,baseUrl:f,inputSelector:"#search_input_react",handleSelected:(e,t,n)=>{const o=n.url||"/";document.createElement("a").href=o,e.setVal(""),t.target.blur();let a="";if(r.highlightResult)try{const e=(n.text||n.subcategory||n.title).match(new RegExp("\\w*","g"));if(e&&e.length>0){const t=document.createElement("div");t.innerHTML=e[0],a=t.textContent}}catch(i){console.log(i)}l.push(o,{highlightState:{wordToHighlight:a}})},maxHits:r.maxHits})})(o,n,r,a),i(!0))})),t.current=!0)},v=(0,r.useCallback)((t=>{o.current.contains(t.target)||o.current.focus(),e.handleSearchBarToggle&&e.handleSearchBarToggle(!e.isSearchBarExpanded)}),[e.isSearchBarExpanded]);let y;return p&&(g(),y=window.navigator.platform.startsWith("Mac")?"Search \u2318+K":"Search Ctrl+K"),(0,r.useEffect)((()=>{e.autoFocus&&a&&o.current.focus()}),[a]),(0,u.jsxs)("div",{className:"navbar__search",children:[(0,u.jsx)("span",{"aria-label":"expand searchbar",role:"button",className:(0,ve.A)("search-icon",{"search-icon-hidden":e.isSearchBarExpanded}),onClick:v,onKeyDown:v,tabIndex:0}),(0,u.jsx)("input",{id:"search_input_react",type:"search",placeholder:a?y:"Loading...","aria-label":"Search",className:(0,ve.A)("navbar__search-input",{"search-bar-expanded":e.isSearchBarExpanded},{"search-bar":!e.isSearchBarExpanded}),onClick:g,onMouseOver:g,onFocus:v,onBlur:v,ref:o,disabled:!a}),(0,u.jsx)(xe,{})]},"search-box")},Se={navbarSearchContainer:"navbarSearchContainer_YXBI"};function Ce(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.A)(n,Se.navbarSearchContainer),children:t})}var Ee=n(62939),Te=n(52295);var Le=n(23432);const Ie=e=>e.docs.find((t=>t.id===e.mainDocId));const Ae={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,le.A)(),p=(0,he.o)(),{search:f,hash:h}=(0,s.zy)(),m=[...n,...c.map((e=>{const n=`${`pathname://${p.createUrl({locale:e,fullyQualified:!1})}`}${f}${h}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,l.T)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(fe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(me,{className:ge}),g]}),items:m})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(Ce,{className:n,children:(0,u.jsx)(ke,{})})},dropdown:fe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.A)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ee.zK)(r),i=(0,Te.QB)(t,r),s=a?.path===i?.path;return null===i||i.unlisted&&!s?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>s||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,Ee.zK)(r),i=(0,Te.fW)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,Te.Vd)(r)[0],i=t??a.label,s=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:s})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:c,hash:d}=(0,s.zy)(),p=(0,Ee.zK)(n),f=(0,Ee.jh)(n),{savePreferredVersionName:h}=(0,Le.g1)(n),m=[...o,...f.map((e=>{const t=p.alternateDocVersions[e.name]??Ie(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===p.activeVersion,onClick:()=>h(e.name)}})),...a],g=(0,Te.Vd)(n)[0],v=t&&m.length>1?(0,l.T)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,y=t&&m.length>1?void 0:Ie(g).path;return m.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:v,to:y,isActive:r?()=>!1:void 0}):(0,u.jsx)(fe,{...i,mobile:t,label:v,to:y,items:m,isActive:r?()=>!1:void 0})}};function Oe(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ae[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function _e(){const e=(0,A.M)(),t=(0,w.p)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(Oe,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Pe(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(l.A,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function Me(){const e=0===(0,w.p)().navbar.items.length,t=j();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Pe,{onClick:()=>t.hide()}),t.content]})}function Re(){const e=(0,A.M)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(D,{header:(0,u.jsx)(Y,{}),primaryMenu:(0,u.jsx)(_e,{}),secondaryMenu:(0,u.jsx)(Me,{})}):null}const Ne={navbarHideable:"navbarHideable_ZRt4",navbarHidden:"navbarHidden__zjS"};function je(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.A)("navbar-sidebar__backdrop",e.className)})}function De(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.p)(),i=(0,A.M)(),{navbarRef:s,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,O.Mq)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=s?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:s,"aria-label":(0,l.T)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.A)("navbar","navbar--fixed-top",n&&[Ne.navbarHideable,!d&&Ne.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(je,{onClick:i.toggle}),(0,u.jsx)(Re,{})]})}var Fe=n(78946);const Be={errorBoundaryError:"errorBoundaryError_FzC7",errorBoundaryFallback:"errorBoundaryFallback_bhT6"};function ze(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(l.A,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function Ue(e){let{error:t}=e;const n=(0,Fe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:Be.errorBoundaryError,children:n})}class qe extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const He="right";function We(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function $e(){const{toggle:e,shown:t}=(0,A.M)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,l.T)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(We,{})})}const Ge={colorModeToggle:"colorModeToggle_CW8R"};function Ve(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(qe,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(Oe,{...e})},t)))})}function Ke(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function Ze(){const e=(0,A.M)(),t=(0,w.p)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??He)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(Ke,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)($e,{}),(0,u.jsx)(K,{}),(0,u.jsx)(Ve,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Ve,{items:r}),(0,u.jsx)(G,{className:Ge.colorModeToggle}),!o&&(0,u.jsx)(Ce,{children:(0,u.jsx)(ke,{})})]})})}function Ye(){return(0,u.jsx)(De,{children:(0,u.jsx)(Ze,{})})}function Xe(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,s=(0,J.Ay)(n),l=(0,J.Ay)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(X.A,{className:"footer__link-item",...r?{href:a?l:r}:{to:s},...i,children:[o,r&&!(0,Q.A)(r)&&(0,u.jsx)(te.A,{})]})}function Je(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(Xe,{item:t})},t.href??t.to)}function Qe(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(Je,{item:e},t)))})]})}function et(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(Qe,{column:e},t)))})}function tt(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function nt(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(Xe,{item:t})}function rt(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(nt,{item:e}),t.length!==n+1&&(0,u.jsx)(tt,{})]},n)))})})}function ot(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(et,{columns:t}):(0,u.jsx)(rt,{links:t})}var at=n(15871);const it={footerLogoLink:"footerLogoLink_D2d8"};function st(e){let{logo:t}=e;const{withBaseUrl:n}=(0,J.hH)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(at.A,{className:(0,o.A)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function lt(e){let{logo:t}=e;return t.href?(0,u.jsx)(X.A,{href:t.href,className:it.footerLogoLink,target:t.target,children:(0,u.jsx)(st,{logo:t})}):(0,u.jsx)(st,{logo:t})}function ct(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function ut(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.A)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function dt(){const{footer:e}=(0,w.p)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(ut,{style:o,links:n&&n.length>0&&(0,u.jsx)(ot,{links:n}),logo:r&&(0,u.jsx)(lt,{logo:r}),copyright:t&&(0,u.jsx)(ct,{copyright:t})})}const pt=r.memo(dt),ft=(0,_.fM)([F.a,x.o,O.Tv,Le.VQ,i.Jx,function(e){let{children:t}=e;return(0,u.jsx)(P.y_,{children:(0,u.jsx)(A.e,{children:(0,u.jsx)(R,{children:t})})})}]);function ht(e){let{children:t}=e;return(0,u.jsx)(ft,{children:t})}var mt=n(55230);function gt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(mt.A,{as:"h1",className:"hero__title",children:(0,u.jsx)(l.A,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(ze,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Ue,{error:t})})]})})})}const vt={mainWrapper:"mainWrapper_Ge4w"};function yt(e){const{children:t,noFooter:n,wrapperClassName:r,title:s,description:l}=e;return(0,v.J)(),(0,u.jsxs)(ht,{children:[(0,u.jsx)(i.be,{title:s,description:l}),(0,u.jsx)(b,{}),(0,u.jsx)(I,{}),(0,u.jsx)(Ye,{}),(0,u.jsx)("div",{id:d,className:(0,o.A)(g.G.wrapper.main,vt.mainWrapper,r),children:(0,u.jsx)(a.A,{fallback:e=>(0,u.jsx)(gt,{...e}),children:t})}),!n&&(0,u.jsx)(pt,{})]})}},67520:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});n(30758);var r=n(92076),o=n(94887),a=n(30340),i=n(13929),s=n(15871),l=n(86070);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.Ay)(t.src),dark:(0,o.Ay)(t.srcDark||t.src)},i=(0,l.jsx)(s.A,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,l.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.A)(),{navbar:{title:n,logo:s}}=(0,i.p)(),{imageClassName:u,titleClassName:d,...p}=e,f=(0,o.Ay)(s?.href||"/"),h=n?"":t,m=s?.alt??h;return(0,l.jsxs)(r.A,{to:f,...p,...s?.target&&{target:s.target},children:[s&&(0,l.jsx)(c,{logo:s,alt:m,imageClassName:u}),null!=n&&(0,l.jsx)("b",{className:d,children:n})]})}},43926:(e,t,n)=>{"use strict";n.d(t,{A:()=>a});n(30758);var r=n(74650),o=n(86070);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.A,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},15871:(e,t,n)=>{"use strict";n.d(t,{A:()=>u});var r=n(30758),o=n(13526),a=n(5197),i=n(64322);const s={themedComponent:"themedComponent_Ev3p","themedComponent--light":"themedComponent--light_IPMc","themedComponent--dark":"themedComponent--dark_olOz"};var l=n(86070);function c(e){let{className:t,children:n}=e;const c=(0,a.A)(),{colorMode:u}=(0,i.G)();return(0,l.jsx)(l.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.A)(t,s.themedComponent,s[`themedComponent--${e}`])});return(0,l.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,l.jsx)(c,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,l.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},53609:(e,t,n)=>{"use strict";n.d(t,{N:()=>v,u:()=>c});var r=n(30758),o=n(25283),a=n(89871),i=n(4746),s=n(86070);const l="ease-in-out";function c(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function p(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function f(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.O)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??l}`,height:`${t}px`}}function s(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return p(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(s(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{s()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function h(e){if(!o.A.canUseDOM)return e?u:d}function m(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:l,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return f({collapsibleRef:u,collapsed:n,animation:a}),(0,s.jsx)(t,{ref:u,style:c?void 0:h(n),onTransitionEnd:e=>{"height"===e.propertyName&&(p(u.current,n),i?.(n))},className:l,children:o})}function g(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[l,c]=(0,r.useState)(t);return(0,a.A)((()=>{t||i(!0)}),[t]),(0,a.A)((()=>{o&&c(t)}),[o,t]),o?(0,s.jsx)(m,{...n,collapsed:l}):null}function v(e){let{lazy:t,...n}=e;const r=t?g:m;return(0,s.jsx)(r,{...n})}},67214:(e,t,n)=>{"use strict";n.d(t,{M:()=>m,o:()=>h});var r=n(30758),o=n(5197),a=n(27311),i=n(94259),s=n(13929),l=n(86070);const c=(0,a.Wf)("docusaurus.announcement.dismiss"),u=(0,a.Wf)("docusaurus.announcement.id"),d=()=>"true"===c.get(),p=e=>c.set(String(e)),f=r.createContext(null);function h(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,s.p)(),t=(0,o.A)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{p(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&p(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,l.jsx)(f.Provider,{value:n,children:t})}function m(){const e=(0,r.useContext)(f);if(!e)throw new i.dV("AnnouncementBarProvider");return e}},64322:(e,t,n)=>{"use strict";n.d(t,{G:()=>v,a:()=>g});var r=n(30758),o=n(25283),a=n(94259),i=n(27311),s=n(13929),l=n(86070);const c=r.createContext(void 0),u="theme",d=(0,i.Wf)(u),p={light:"light",dark:"dark"},f=e=>e===p.dark?p.dark:p.light,h=e=>o.A.canUseDOM?f(document.documentElement.getAttribute("data-theme")):f(e),m=e=>{d.set(f(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,s.p)(),[o,a]=(0,r.useState)(h(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&m(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?p.dark:p.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",f(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(f(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const l=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||l.current?l.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===p.dark},setLightTheme(){i(p.light)},setDarkTheme(){i(p.dark)}})),[o,i])}();return(0,l.jsx)(c.Provider,{value:n,children:t})}function v(){const e=(0,r.useContext)(c);if(null==e)throw new a.dV("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},23432:(e,t,n)=>{"use strict";n.d(t,{VQ:()=>v,g1:()=>b});var r=n(30758),o=n(62939),a=n(95163),i=n(13929),s=n(52295),l=n(94259),c=n(27311),u=n(86070);const d=e=>`docs-preferred-version-${e}`,p={save:(e,t,n)=>{(0,c.Wf)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.Wf)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.Wf)(d(e),{persistence:t}).del()}},f=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const h=r.createContext(null);function m(){const e=(0,o.Gy)(),t=(0,i.p)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,s]=(0,r.useState)((()=>f(n)));(0,r.useEffect)((()=>{s(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=p.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(p.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){p.save(e,t,n),s((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=m();return(0,u.jsx)(h.Provider,{value:n,children:t})}function v(e){let{children:t}=e;return s.C5?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function y(){const e=(0,r.useContext)(h);if(!e)throw new l.dV("DocsPreferredVersionContextProvider");return e}function b(e){void 0===e&&(e=a.W);const t=(0,o.ht)(e),[n,i]=y(),{preferredVersionName:s}=n[e];return{preferredVersion:t.versions.find((e=>e.name===s))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},33471:(e,t,n)=>{"use strict";n.d(t,{V:()=>l,t:()=>c});var r=n(30758),o=n(94259),a=n(86070);const i=Symbol("EmptyContext"),s=r.createContext(i);function l(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(s.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(s);if(e===i)throw new o.dV("DocsSidebarProvider");return e}},19463:(e,t,n)=>{"use strict";n.d(t,{n:()=>s,r:()=>l});var r=n(30758),o=n(94259),a=n(86070);const i=r.createContext(null);function s(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(null===e)throw new o.dV("DocsVersionProvider");return e}},14491:(e,t,n)=>{"use strict";n.d(t,{e:()=>f,M:()=>h});var r=n(30758),o=n(831),a=n(20772),i=n(25557),s=n(94259);function l(e){!function(e){const t=(0,i.W6)(),n=(0,s._q)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}var c=n(13929),u=n(86070);const d=r.createContext(void 0);function p(){const e=function(){const e=(0,o.YL)(),{items:t}=(0,c.p)().navbar;return 0===t.length&&!e.component}(),t=(0,a.l)(),n=!e&&"mobile"===t,[i,s]=(0,r.useState)(!1);l((()=>{if(i)return s(!1),!1}));const u=(0,r.useCallback)((()=>{s((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&s(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:i})),[e,n,u,i])}function f(e){let{children:t}=e;const n=p();return(0,u.jsx)(d.Provider,{value:n,children:t})}function h(){const e=r.useContext(d);if(void 0===e)throw new s.dV("NavbarMobileSidebarProvider");return e}},831:(e,t,n)=>{"use strict";n.d(t,{GX:()=>c,YL:()=>l,y_:()=>s});var r=n(30758),o=n(94259),a=n(86070);const i=r.createContext(null);function s(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function l(){const e=(0,r.useContext)(i);if(!e)throw new o.dV("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.dV("NavbarSecondaryMenuContentProvider");const[,s]=a,l=(0,o.Be)(n);return(0,r.useEffect)((()=>{s({component:t,props:l})}),[s,t,l]),(0,r.useEffect)((()=>()=>s({component:null,props:null})),[s]),null}},4715:(e,t,n)=>{"use strict";n.d(t,{w:()=>o,J:()=>a});var r=n(30758);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},20772:(e,t,n)=>{"use strict";n.d(t,{l:()=>s});var r=n(30758),o=n(25283);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function s(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,s]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){s(function(e){if(!o.A.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},81274:(e,t,n)=>{"use strict";n.d(t,{G:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{blogFooterTagsRow:"theme-blog-footer-tags-row",blogFooterEditMetaRow:"theme-blog-footer-edit-meta-row"},pages:{pageFooterEditMetaRow:"theme-pages-footer-edit-meta-row"}}},4746:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{O:()=>r})},52295:(e,t,n)=>{"use strict";n.d(t,{d1:()=>L,Nr:()=>h,w8:()=>y,C5:()=>p,$S:()=>m,cC:()=>f,B5:()=>T,Vd:()=>S,QB:()=>E,fW:()=>C,OF:()=>k,Y:()=>w});var r=n(30758),o=n(25557),a=n(70389),i=n(62939),s=n(23432),l=n(19463),c=n(33471);function u(e){return Array.from(new Set(e))}var d=n(74768);const p=!!i.Gy;function f(e){const t=(0,l.r)();if(!e)return;const n=t.docs[e];if(!n)throw new Error(`no version doc found by id=${e}`);return n}function h(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=h(t);if(e)return e}}(e):void 0:e.href}function m(){const{pathname:e}=(0,o.zy)(),t=(0,c.t)();if(!t)throw new Error("Unexpected: cant find current sidebar in context");const n=x({sidebarItems:t.items,pathname:e,onlyCategories:!0}).slice(-1)[0];if(!n)throw new Error(`${e} is not associated with a category. useCurrentSidebarCategory() should only be used on category index pages.`);return n}const g=(e,t)=>void 0!==e&&(0,d.ys)(e,t),v=(e,t)=>e.some((e=>y(e,t)));function y(e,t){return"link"===e.type?g(e.href,t):"category"===e.type&&(g(e.href,t)||v(e.items,t))}function b(e,t){switch(e.type){case"category":return y(e,t)||e.items.some((e=>b(e,t)));case"link":return!e.unlisted||y(e,t);default:return!0}}function w(e,t){return(0,r.useMemo)((()=>e.filter((e=>b(e,t)))),[e,t])}function x(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.ys)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.ys)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function k(){const e=(0,c.t)(),{pathname:t}=(0,o.zy)(),n=(0,i.vT)()?.pluginData.breadcrumbs;return!1!==n&&e?x({sidebarItems:e.items,pathname:t}):null}function S(e){const{activeVersion:t}=(0,i.zK)(e),{preferredVersion:n}=(0,s.g1)(e),o=(0,i.r7)(e);return(0,r.useMemo)((()=>u([t,n,o].filter(Boolean))),[t,n,o])}function C(e,t){const n=S(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function E(e,t){const n=S(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${u(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function T(e){let{route:t}=e;const n=(0,o.zy)(),r=(0,l.r)(),i=t.routes,s=i.find((e=>(0,o.B6)(n.pathname,e)));if(!s)return null;const c=s.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.v)(i),sidebarName:c,sidebarItems:u}}function L(e){return e.filter((e=>!("category"===e.type||"link"===e.type)||!!h(e)))}},64204:(e,t,n)=>{"use strict";n.d(t,{e3:()=>p,be:()=>u,Jx:()=>f});var r=n(30758),o=n(13526),a=n(74650),i=n(80053),s=n(94887),l=n(30340);var c=n(86070);function u(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const u=function(e){const{siteConfig:t}=(0,l.A)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,s.hH)(),p=o?d(o,{absolute:!0}):void 0;return(0,c.jsxs)(a.A,{children:[t&&(0,c.jsx)("title",{children:u}),t&&(0,c.jsx)("meta",{property:"og:title",content:u}),n&&(0,c.jsx)("meta",{name:"description",content:n}),n&&(0,c.jsx)("meta",{property:"og:description",content:n}),r&&(0,c.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),p&&(0,c.jsx)("meta",{property:"og:image",content:p}),p&&(0,c.jsx)("meta",{name:"twitter:image",content:p}),i]})}const d=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(d),s=(0,o.A)(i,t);return(0,c.jsxs)(d.Provider,{value:s,children:[(0,c.jsx)(a.A,{children:(0,c.jsx)("html",{className:s})}),n]})}function f(e){let{children:t}=e;const n=(0,i.A)(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,c.jsx)(p,{className:(0,o.A)(r,a),children:t})}},94259:(e,t,n)=>{"use strict";n.d(t,{Be:()=>c,ZC:()=>s,_q:()=>i,dV:()=>l,fM:()=>u});var r=n(30758),o=n(89871),a=n(86070);function i(e){const t=(0,r.useRef)(e);return(0,o.A)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function s(e){const t=(0,r.useRef)();return(0,o.A)((()=>{t.current=e})),t.current}class l extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},74768:(e,t,n)=>{"use strict";n.d(t,{Dt:()=>s,ys:()=>i});var r=n(30758),o=n(68384),a=n(30340);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function s(){const{baseUrl:e}=(0,a.A)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.A,baseUrl:e})),[e])}},793:(e,t,n)=>{"use strict";n.d(t,{Mq:()=>p,Tv:()=>c,gk:()=>f});var r=n(30758),o=n(25283),a=n(5197),i=(n(89871),n(94259)),s=n(86070);const l=r.createContext(void 0);function c(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(l.Provider,{value:n,children:t})}function u(){const e=(0,r.useContext)(l);if(null==e)throw new i.dV("ScrollControllerProvider");return e}const d=()=>o.A.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=u(),o=(0,r.useRef)(d()),a=(0,i._q)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=d();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function f(){const e=(0,r.useRef)(null),t=(0,a.A)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},70622:(e,t,n)=>{"use strict";n.d(t,{Cy:()=>r,tU:()=>o});n(30340);const r="default";function o(e,t){return`docs-${e}-${t}`}},27311:(e,t,n)=>{"use strict";n.d(t,{Wf:()=>c});n(30758);const r=JSON.parse('{"N":"localStorage","M":""}'),o=r.N;function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,s||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),s=!0),null}var t}let s=!1;const l={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){const n=`${e}${r.M}`;if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(n);const o=i(t?.persistence);return null===o?l:{get:()=>{try{return o.getItem(n)}catch(e){return console.error(`Docusaurus storage error, can't get key=${n}`,e),null}},set:e=>{try{const t=o.getItem(n);o.setItem(n,e),a({key:n,oldValue:t,newValue:e,storage:o})}catch(t){console.error(`Docusaurus storage error, can't set ${n}=${e}`,t)}},del:()=>{try{const e=o.getItem(n);o.removeItem(n),a({key:n,oldValue:e,newValue:null,storage:o})}catch(e){console.error(`Docusaurus storage error, can't delete key=${n}`,e)}},listen:e=>{try{const t=t=>{t.storageArea===o&&t.key===n&&e(t)};return window.addEventListener("storage",t),()=>window.removeEventListener("storage",t)}catch(t){return console.error(`Docusaurus storage error, can't listen for changes of key=${n}`,t),()=>{}}}}}},98878:(e,t,n)=>{"use strict";n.d(t,{o:()=>i});var r=n(30340),o=n(25557),a=n(78946);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:s}}=(0,r.A)(),{pathname:l}=(0,o.zy)(),c=(0,a.applyTrailingSlash)(l,{trailingSlash:n,baseUrl:e}),u=s===i?e:e.replace(`/${s}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},35623:(e,t,n)=>{"use strict";n.d(t,{$:()=>i});var r=n(30758),o=n(25557),a=n(94259);function i(e){const t=(0,o.zy)(),n=(0,a.ZC)(t),i=(0,a._q)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},13929:(e,t,n)=>{"use strict";n.d(t,{p:()=>o});var r=n(30340);function o(){return(0,r.A)().siteConfig.themeConfig}},90717:(e,t,n)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=void 0;const r=n(61664);function o(e){return e.endsWith("/")?e:`${e}/`}function a(e){return(0,r.removeSuffix)(e,"/")}t.addTrailingSlash=o,t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[i]=e.split(/[#?]/),s="/"===i||i===r?i:(l=i,n?o(l):a(l));var l;return e.replace(i,s)},t.addLeadingSlash=function(e){return(0,r.addPrefix)(e,"/")},t.removeTrailingSlash=a},435:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},78946:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=t.removeTrailingSlash=t.addLeadingSlash=t.addTrailingSlash=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(90717);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}}),Object.defineProperty(t,"addTrailingSlash",{enumerable:!0,get:function(){return o.addTrailingSlash}}),Object.defineProperty(t,"addLeadingSlash",{enumerable:!0,get:function(){return o.addLeadingSlash}}),Object.defineProperty(t,"removeTrailingSlash",{enumerable:!0,get:function(){return o.removeTrailingSlash}});var a=n(61664);Object.defineProperty(t,"addPrefix",{enumerable:!0,get:function(){return a.addPrefix}}),Object.defineProperty(t,"removeSuffix",{enumerable:!0,get:function(){return a.removeSuffix}}),Object.defineProperty(t,"addSuffix",{enumerable:!0,get:function(){return a.addSuffix}}),Object.defineProperty(t,"removePrefix",{enumerable:!0,get:function(){return a.removePrefix}});var i=n(435);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return i.getErrorCausalChain}})},61664:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.removePrefix=t.addSuffix=t.removeSuffix=t.addPrefix=void 0,t.addPrefix=function(e,t){return e.startsWith(t)?e:`${t}${e}`},t.removeSuffix=function(e,t){return""===t?e:e.endsWith(t)?e.slice(0,-t.length):e},t.addSuffix=function(e,t){return e.endsWith(t)?e:`${e}${t}`},t.removePrefix=function(e,t){return e.startsWith(t)?e.slice(t.length):e}},98222:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>r});const r=n(25283).A.canUseDOM?{onRouteUpdate(){window.posthog.capture("$pageview")}}:null},68835:(e,t,n)=>{"use strict";function r(e){var t,n,o="";if("string"==typeof e||"number"==typeof e)o+=e;else if("object"==typeof e)if(Array.isArray(e))for(t=0;to,A:()=>a});const a=o},83332:(e,t,n)=>{"use strict";n.d(t,{zR:()=>w,TM:()=>T,yJ:()=>f,sC:()=>I,AO:()=>p});var r=n(95265);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;p--){var f=i[p];"."===f?a(i,p):".."===f?(a(i,p),d++):d&&(a(i,p),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&o(i[0])||i.unshift("");var h=i.join("/");return n&&"/"!==h.substr(-1)&&(h+="/"),h};var s=n(25385);function l(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function p(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function f(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.A)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(s){throw s instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):s}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function h(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=f(e,t,m(),w.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},go:b,goBack:function(){b(-1)},goForward:function(){b(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(35959),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},s={};function l(e){return r.isMemo(e)?i:s[e.$$typeof]||o}s[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},s[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,p=Object.getOwnPropertyDescriptor,f=Object.getPrototypeOf,h=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(h){var o=f(n);o&&o!==h&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var s=l(t),m=l(n),g=0;g{"use strict";e.exports=function(e,t,n,r,o,a,i,s){if(!e){var l;if(void 0===t)l=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,a,i,s],u=0;(l=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw l.framesToPop=1,l}}},5526:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},91176:function(e){e.exports=function(){"use strict";var e="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},t=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},n=function(){function e(e,t){for(var n=0;n1&&void 0!==arguments[1])||arguments[1],o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:[],a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:5e3;t(this,e),this.ctx=n,this.iframes=r,this.exclude=o,this.iframesTimeout=a}return n(e,[{key:"getContexts",value:function(){var e=[];return(void 0!==this.ctx&&this.ctx?NodeList.prototype.isPrototypeOf(this.ctx)?Array.prototype.slice.call(this.ctx):Array.isArray(this.ctx)?this.ctx:"string"==typeof this.ctx?Array.prototype.slice.call(document.querySelectorAll(this.ctx)):[this.ctx]:[]).forEach((function(t){var n=e.filter((function(e){return e.contains(t)})).length>0;-1!==e.indexOf(t)||n||e.push(t)})),e}},{key:"getIframeContents",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:function(){},r=void 0;try{var o=e.contentWindow;if(r=o.document,!o||!r)throw new Error("iframe inaccessible")}catch(a){n()}r&&t(r)}},{key:"isIframeBlank",value:function(e){var t="about:blank",n=e.getAttribute("src").trim();return e.contentWindow.location.href===t&&n!==t&&n}},{key:"observeIframeLoad",value:function(e,t,n){var r=this,o=!1,a=null,i=function i(){if(!o){o=!0,clearTimeout(a);try{r.isIframeBlank(e)||(e.removeEventListener("load",i),r.getIframeContents(e,t,n))}catch(s){n()}}};e.addEventListener("load",i),a=setTimeout(i,this.iframesTimeout)}},{key:"onIframeReady",value:function(e,t,n){try{"complete"===e.contentWindow.document.readyState?this.isIframeBlank(e)?this.observeIframeLoad(e,t,n):this.getIframeContents(e,t,n):this.observeIframeLoad(e,t,n)}catch(r){n()}}},{key:"waitForIframes",value:function(e,t){var n=this,r=0;this.forEachIframe(e,(function(){return!0}),(function(e){r++,n.waitForIframes(e.querySelector("html"),(function(){--r||t()}))}),(function(e){e||t()}))}},{key:"forEachIframe",value:function(t,n,r){var o=this,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},i=t.querySelectorAll("iframe"),s=i.length,l=0;i=Array.prototype.slice.call(i);var c=function(){--s<=0&&a(l)};s||c(),i.forEach((function(t){e.matches(t,o.exclude)?c():o.onIframeReady(t,(function(e){n(t)&&(l++,r(e)),c()}),c)}))}},{key:"createIterator",value:function(e,t,n){return document.createNodeIterator(e,t,n,!1)}},{key:"createInstanceOnIframe",value:function(t){return new e(t.querySelector("html"),this.iframes)}},{key:"compareNodeIframe",value:function(e,t,n){if(e.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_PRECEDING){if(null===t)return!0;if(t.compareDocumentPosition(n)&Node.DOCUMENT_POSITION_FOLLOWING)return!0}return!1}},{key:"getIteratorNode",value:function(e){var t=e.previousNode();return{prevNode:t,node:(null===t||e.nextNode())&&e.nextNode()}}},{key:"checkIframeFilter",value:function(e,t,n,r){var o=!1,a=!1;return r.forEach((function(e,t){e.val===n&&(o=t,a=e.handled)})),this.compareNodeIframe(e,t,n)?(!1!==o||a?!1===o||a||(r[o].handled=!0):r.push({val:n,handled:!0}),!0):(!1===o&&r.push({val:n,handled:!1}),!1)}},{key:"handleOpenIframes",value:function(e,t,n,r){var o=this;e.forEach((function(e){e.handled||o.getIframeContents(e.val,(function(e){o.createInstanceOnIframe(e).forEachNode(t,n,r)}))}))}},{key:"iterateThroughNodes",value:function(e,t,n,r,o){for(var a=this,i=this.createIterator(t,e,r),s=[],l=[],c=void 0,u=void 0,d=function(){var e=a.getIteratorNode(i);return u=e.prevNode,c=e.node};d();)this.iframes&&this.forEachIframe(t,(function(e){return a.checkIframeFilter(c,u,e,s)}),(function(t){a.createInstanceOnIframe(t).forEachNode(e,(function(e){return l.push(e)}),r)})),l.push(c);l.forEach((function(e){n(e)})),this.iframes&&this.handleOpenIframes(s,e,n,r),o()}},{key:"forEachNode",value:function(e,t,n){var r=this,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:function(){},a=this.getContexts(),i=a.length;i||o(),a.forEach((function(a){var s=function(){r.iterateThroughNodes(e,a,t,n,(function(){--i<=0&&o()}))};r.iframes?r.waitForIframes(a,s):s()}))}}],[{key:"matches",value:function(e,t){var n="string"==typeof t?[t]:t,r=e.matches||e.matchesSelector||e.msMatchesSelector||e.mozMatchesSelector||e.oMatchesSelector||e.webkitMatchesSelector;if(r){var o=!1;return n.every((function(t){return!r.call(e,t)||(o=!0,!1)})),o}return!1}}]),e}(),a=function(){function a(e){t(this,a),this.ctx=e,this.ie=!1;var n=window.navigator.userAgent;(n.indexOf("MSIE")>-1||n.indexOf("Trident")>-1)&&(this.ie=!0)}return n(a,[{key:"log",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"debug",r=this.opt.log;this.opt.debug&&"object"===(void 0===r?"undefined":e(r))&&"function"==typeof r[n]&&r[n]("mark.js: "+t)}},{key:"escapeStr",value:function(e){return e.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")}},{key:"createRegExp",value:function(e){return"disabled"!==this.opt.wildcards&&(e=this.setupWildcardsRegExp(e)),e=this.escapeStr(e),Object.keys(this.opt.synonyms).length&&(e=this.createSynonymsRegExp(e)),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),this.opt.diacritics&&(e=this.createDiacriticsRegExp(e)),e=this.createMergedBlanksRegExp(e),(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.createJoinersRegExp(e)),"disabled"!==this.opt.wildcards&&(e=this.createWildcardsRegExp(e)),e=this.createAccuracyRegExp(e)}},{key:"createSynonymsRegExp",value:function(e){var t=this.opt.synonyms,n=this.opt.caseSensitive?"":"i",r=this.opt.ignoreJoiners||this.opt.ignorePunctuation.length?"\0":"";for(var o in t)if(t.hasOwnProperty(o)){var a=t[o],i="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(o):this.escapeStr(o),s="disabled"!==this.opt.wildcards?this.setupWildcardsRegExp(a):this.escapeStr(a);""!==i&&""!==s&&(e=e.replace(new RegExp("("+this.escapeStr(i)+"|"+this.escapeStr(s)+")","gm"+n),r+"("+this.processSynomyms(i)+"|"+this.processSynomyms(s)+")"+r))}return e}},{key:"processSynomyms",value:function(e){return(this.opt.ignoreJoiners||this.opt.ignorePunctuation.length)&&(e=this.setupIgnoreJoinersRegExp(e)),e}},{key:"setupWildcardsRegExp",value:function(e){return(e=e.replace(/(?:\\)*\?/g,(function(e){return"\\"===e.charAt(0)?"?":"\x01"}))).replace(/(?:\\)*\*/g,(function(e){return"\\"===e.charAt(0)?"*":"\x02"}))}},{key:"createWildcardsRegExp",value:function(e){var t="withSpaces"===this.opt.wildcards;return e.replace(/\u0001/g,t?"[\\S\\s]?":"\\S?").replace(/\u0002/g,t?"[\\S\\s]*?":"\\S*")}},{key:"setupIgnoreJoinersRegExp",value:function(e){return e.replace(/[^(|)\\]/g,(function(e,t,n){var r=n.charAt(t+1);return/[(|)\\]/.test(r)||""===r?e:e+"\0"}))}},{key:"createJoinersRegExp",value:function(e){var t=[],n=this.opt.ignorePunctuation;return Array.isArray(n)&&n.length&&t.push(this.escapeStr(n.join(""))),this.opt.ignoreJoiners&&t.push("\\u00ad\\u200b\\u200c\\u200d"),t.length?e.split(/\u0000+/).join("["+t.join("")+"]*"):e}},{key:"createDiacriticsRegExp",value:function(e){var t=this.opt.caseSensitive?"":"i",n=this.opt.caseSensitive?["a\xe0\xe1\u1ea3\xe3\u1ea1\u0103\u1eb1\u1eaf\u1eb3\u1eb5\u1eb7\xe2\u1ea7\u1ea5\u1ea9\u1eab\u1ead\xe4\xe5\u0101\u0105","A\xc0\xc1\u1ea2\xc3\u1ea0\u0102\u1eb0\u1eae\u1eb2\u1eb4\u1eb6\xc2\u1ea6\u1ea4\u1ea8\u1eaa\u1eac\xc4\xc5\u0100\u0104","c\xe7\u0107\u010d","C\xc7\u0106\u010c","d\u0111\u010f","D\u0110\u010e","e\xe8\xe9\u1ebb\u1ebd\u1eb9\xea\u1ec1\u1ebf\u1ec3\u1ec5\u1ec7\xeb\u011b\u0113\u0119","E\xc8\xc9\u1eba\u1ebc\u1eb8\xca\u1ec0\u1ebe\u1ec2\u1ec4\u1ec6\xcb\u011a\u0112\u0118","i\xec\xed\u1ec9\u0129\u1ecb\xee\xef\u012b","I\xcc\xcd\u1ec8\u0128\u1eca\xce\xcf\u012a","l\u0142","L\u0141","n\xf1\u0148\u0144","N\xd1\u0147\u0143","o\xf2\xf3\u1ecf\xf5\u1ecd\xf4\u1ed3\u1ed1\u1ed5\u1ed7\u1ed9\u01a1\u1edf\u1ee1\u1edb\u1edd\u1ee3\xf6\xf8\u014d","O\xd2\xd3\u1ece\xd5\u1ecc\xd4\u1ed2\u1ed0\u1ed4\u1ed6\u1ed8\u01a0\u1ede\u1ee0\u1eda\u1edc\u1ee2\xd6\xd8\u014c","r\u0159","R\u0158","s\u0161\u015b\u0219\u015f","S\u0160\u015a\u0218\u015e","t\u0165\u021b\u0163","T\u0164\u021a\u0162","u\xf9\xfa\u1ee7\u0169\u1ee5\u01b0\u1eeb\u1ee9\u1eed\u1eef\u1ef1\xfb\xfc\u016f\u016b","U\xd9\xda\u1ee6\u0168\u1ee4\u01af\u1eea\u1ee8\u1eec\u1eee\u1ef0\xdb\xdc\u016e\u016a","y\xfd\u1ef3\u1ef7\u1ef9\u1ef5\xff","Y\xdd\u1ef2\u1ef6\u1ef8\u1ef4\u0178","z\u017e\u017c\u017a","Z\u017d\u017b\u0179"]:["a\xe0\xe1\u1ea3\xe3\u1ea1\u0103\u1eb1\u1eaf\u1eb3\u1eb5\u1eb7\xe2\u1ea7\u1ea5\u1ea9\u1eab\u1ead\xe4\xe5\u0101\u0105A\xc0\xc1\u1ea2\xc3\u1ea0\u0102\u1eb0\u1eae\u1eb2\u1eb4\u1eb6\xc2\u1ea6\u1ea4\u1ea8\u1eaa\u1eac\xc4\xc5\u0100\u0104","c\xe7\u0107\u010dC\xc7\u0106\u010c","d\u0111\u010fD\u0110\u010e","e\xe8\xe9\u1ebb\u1ebd\u1eb9\xea\u1ec1\u1ebf\u1ec3\u1ec5\u1ec7\xeb\u011b\u0113\u0119E\xc8\xc9\u1eba\u1ebc\u1eb8\xca\u1ec0\u1ebe\u1ec2\u1ec4\u1ec6\xcb\u011a\u0112\u0118","i\xec\xed\u1ec9\u0129\u1ecb\xee\xef\u012bI\xcc\xcd\u1ec8\u0128\u1eca\xce\xcf\u012a","l\u0142L\u0141","n\xf1\u0148\u0144N\xd1\u0147\u0143","o\xf2\xf3\u1ecf\xf5\u1ecd\xf4\u1ed3\u1ed1\u1ed5\u1ed7\u1ed9\u01a1\u1edf\u1ee1\u1edb\u1edd\u1ee3\xf6\xf8\u014dO\xd2\xd3\u1ece\xd5\u1ecc\xd4\u1ed2\u1ed0\u1ed4\u1ed6\u1ed8\u01a0\u1ede\u1ee0\u1eda\u1edc\u1ee2\xd6\xd8\u014c","r\u0159R\u0158","s\u0161\u015b\u0219\u015fS\u0160\u015a\u0218\u015e","t\u0165\u021b\u0163T\u0164\u021a\u0162","u\xf9\xfa\u1ee7\u0169\u1ee5\u01b0\u1eeb\u1ee9\u1eed\u1eef\u1ef1\xfb\xfc\u016f\u016bU\xd9\xda\u1ee6\u0168\u1ee4\u01af\u1eea\u1ee8\u1eec\u1eee\u1ef0\xdb\xdc\u016e\u016a","y\xfd\u1ef3\u1ef7\u1ef9\u1ef5\xffY\xdd\u1ef2\u1ef6\u1ef8\u1ef4\u0178","z\u017e\u017c\u017aZ\u017d\u017b\u0179"],r=[];return e.split("").forEach((function(o){n.every((function(n){if(-1!==n.indexOf(o)){if(r.indexOf(n)>-1)return!1;e=e.replace(new RegExp("["+n+"]","gm"+t),"["+n+"]"),r.push(n)}return!0}))})),e}},{key:"createMergedBlanksRegExp",value:function(e){return e.replace(/[\s]+/gim,"[\\s]+")}},{key:"createAccuracyRegExp",value:function(e){var t=this,n="!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\xa1\xbf",r=this.opt.accuracy,o="string"==typeof r?r:r.value,a="string"==typeof r?[]:r.limiters,i="";switch(a.forEach((function(e){i+="|"+t.escapeStr(e)})),o){case"partially":default:return"()("+e+")";case"complementary":return"()([^"+(i="\\s"+(i||this.escapeStr(n)))+"]*"+e+"[^"+i+"]*)";case"exactly":return"(^|\\s"+i+")("+e+")(?=$|\\s"+i+")"}}},{key:"getSeparatedKeywords",value:function(e){var t=this,n=[];return e.forEach((function(e){t.opt.separateWordSearch?e.split(" ").forEach((function(e){e.trim()&&-1===n.indexOf(e)&&n.push(e)})):e.trim()&&-1===n.indexOf(e)&&n.push(e)})),{keywords:n.sort((function(e,t){return t.length-e.length})),length:n.length}}},{key:"isNumeric",value:function(e){return Number(parseFloat(e))==e}},{key:"checkRanges",value:function(e){var t=this;if(!Array.isArray(e)||"[object Object]"!==Object.prototype.toString.call(e[0]))return this.log("markRanges() will only accept an array of objects"),this.opt.noMatch(e),[];var n=[],r=0;return e.sort((function(e,t){return e.start-t.start})).forEach((function(e){var o=t.callNoMatchOnInvalidRanges(e,r),a=o.start,i=o.end;o.valid&&(e.start=a,e.length=i-a,n.push(e),r=i)})),n}},{key:"callNoMatchOnInvalidRanges",value:function(e,t){var n=void 0,r=void 0,o=!1;return e&&void 0!==e.start?(r=(n=parseInt(e.start,10))+parseInt(e.length,10),this.isNumeric(e.start)&&this.isNumeric(e.length)&&r-t>0&&r-n>0?o=!0:(this.log("Ignoring invalid or overlapping range: "+JSON.stringify(e)),this.opt.noMatch(e))):(this.log("Ignoring invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:n,end:r,valid:o}}},{key:"checkWhitespaceRanges",value:function(e,t,n){var r=void 0,o=!0,a=n.length,i=t-a,s=parseInt(e.start,10)-i;return(r=(s=s>a?a:s)+parseInt(e.length,10))>a&&(r=a,this.log("End range automatically set to the max value of "+a)),s<0||r-s<0||s>a||r>a?(o=!1,this.log("Invalid range: "+JSON.stringify(e)),this.opt.noMatch(e)):""===n.substring(s,r).replace(/\s+/g,"")&&(o=!1,this.log("Skipping whitespace only range: "+JSON.stringify(e)),this.opt.noMatch(e)),{start:s,end:r,valid:o}}},{key:"getTextNodes",value:function(e){var t=this,n="",r=[];this.iterator.forEachNode(NodeFilter.SHOW_TEXT,(function(e){r.push({start:n.length,end:(n+=e.textContent).length,node:e})}),(function(e){return t.matchesExclude(e.parentNode)?NodeFilter.FILTER_REJECT:NodeFilter.FILTER_ACCEPT}),(function(){e({value:n,nodes:r})}))}},{key:"matchesExclude",value:function(e){return o.matches(e,this.opt.exclude.concat(["script","style","title","head","html"]))}},{key:"wrapRangeInTextNode",value:function(e,t,n){var r=this.opt.element?this.opt.element:"mark",o=e.splitText(t),a=o.splitText(n-t),i=document.createElement(r);return i.setAttribute("data-markjs","true"),this.opt.className&&i.setAttribute("class",this.opt.className),i.textContent=o.textContent,o.parentNode.replaceChild(i,o),a}},{key:"wrapRangeInMappedTextNode",value:function(e,t,n,r,o){var a=this;e.nodes.every((function(i,s){var l=e.nodes[s+1];if(void 0===l||l.start>t){if(!r(i.node))return!1;var c=t-i.start,u=(n>i.end?i.end:n)-i.start,d=e.value.substr(0,i.start),p=e.value.substr(u+i.start);if(i.node=a.wrapRangeInTextNode(i.node,c,u),e.value=d+p,e.nodes.forEach((function(t,n){n>=s&&(e.nodes[n].start>0&&n!==s&&(e.nodes[n].start-=u),e.nodes[n].end-=u)})),n-=u,o(i.node.previousSibling,i.start),!(n>i.end))return!1;t=i.end}return!0}))}},{key:"wrapMatches",value:function(e,t,n,r,o){var a=this,i=0===t?0:t+1;this.getTextNodes((function(t){t.nodes.forEach((function(t){t=t.node;for(var o=void 0;null!==(o=e.exec(t.textContent))&&""!==o[i];)if(n(o[i],t)){var s=o.index;if(0!==i)for(var l=1;l{"use strict";n.r(t)},94127:(e,t,n)=>{"use strict";n.r(t)},58744:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),c=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,s((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),l(c,i(e,u,d)),1===e?(l(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){l(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),s=e?"-100":a(n.status||0),c=document.querySelector(r.parent);return l(i,{transition:"all 0 linear",transform:"translate3d("+s+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&f(o),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&f(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var s=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),l=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function c(e,t){return("string"==typeof e?e:p(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=p(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=p(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function p(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function f(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},86150:(e,t,n)=>{var r=n(5526);e.exports=f,e.exports.parse=a,e.exports.compile=function(e,t){return s(a(e,t),t)},e.exports.tokensToFunction=s,e.exports.tokensToRegExp=p;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,i=0,s="",u=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],p=n[1],f=n.index;if(s+=e.slice(i,f),i=f+d.length,p)s+=p[1];else{var h=e[i],m=n[2],g=n[3],v=n[4],y=n[5],b=n[6],w=n[7];s&&(r.push(s),s="");var x=null!=m&&null!=h&&h!==m,k="+"===b||"*"===b,S="?"===b||"*"===b,C=n[2]||u,E=v||y;r.push({name:g||a++,prefix:m||"",delimiter:C,optional:S,repeat:k,partial:x,asterisk:!!w,pattern:E?c(E):w?".*":"[^"+l(C)+"]+?"})}}return i{e.exports&&(e.exports={core:{meta:{path:"components/prism-core.js",option:"mandatory"},core:"Core"},themes:{meta:{path:"themes/{id}.css",link:"index.html?theme={id}",exclusive:!0},prism:{title:"Default",option:"default"},"prism-dark":"Dark","prism-funky":"Funky","prism-okaidia":{title:"Okaidia",owner:"ocodia"},"prism-twilight":{title:"Twilight",owner:"remybach"},"prism-coy":{title:"Coy",owner:"tshedor"},"prism-solarizedlight":{title:"Solarized Light",owner:"hectormatos2011 "},"prism-tomorrow":{title:"Tomorrow Night",owner:"Rosey"}},languages:{meta:{path:"components/prism-{id}",noCSS:!0,examplesPath:"examples/prism-{id}",addCheckAll:!0},markup:{title:"Markup",alias:["html","xml","svg","mathml","ssml","atom","rss"],aliasTitles:{html:"HTML",xml:"XML",svg:"SVG",mathml:"MathML",ssml:"SSML",atom:"Atom",rss:"RSS"},option:"default"},css:{title:"CSS",option:"default",modify:"markup"},clike:{title:"C-like",option:"default"},javascript:{title:"JavaScript",require:"clike",modify:"markup",optional:"regex",alias:"js",option:"default"},abap:{title:"ABAP",owner:"dellagustin"},abnf:{title:"ABNF",owner:"RunDevelopment"},actionscript:{title:"ActionScript",require:"javascript",modify:"markup",owner:"Golmote"},ada:{title:"Ada",owner:"Lucretia"},agda:{title:"Agda",owner:"xy-ren"},al:{title:"AL",owner:"RunDevelopment"},antlr4:{title:"ANTLR4",alias:"g4",owner:"RunDevelopment"},apacheconf:{title:"Apache Configuration",owner:"GuiTeK"},apex:{title:"Apex",require:["clike","sql"],owner:"RunDevelopment"},apl:{title:"APL",owner:"ngn"},applescript:{title:"AppleScript",owner:"Golmote"},aql:{title:"AQL",owner:"RunDevelopment"},arduino:{title:"Arduino",require:"cpp",alias:"ino",owner:"dkern"},arff:{title:"ARFF",owner:"Golmote"},armasm:{title:"ARM Assembly",alias:"arm-asm",owner:"RunDevelopment"},arturo:{title:"Arturo",alias:"art",optional:["bash","css","javascript","markup","markdown","sql"],owner:"drkameleon"},asciidoc:{alias:"adoc",title:"AsciiDoc",owner:"Golmote"},aspnet:{title:"ASP.NET (C#)",require:["markup","csharp"],owner:"nauzilus"},asm6502:{title:"6502 Assembly",owner:"kzurawel"},asmatmel:{title:"Atmel AVR Assembly",owner:"cerkit"},autohotkey:{title:"AutoHotkey",owner:"aviaryan"},autoit:{title:"AutoIt",owner:"Golmote"},avisynth:{title:"AviSynth",alias:"avs",owner:"Zinfidel"},"avro-idl":{title:"Avro IDL",alias:"avdl",owner:"RunDevelopment"},awk:{title:"AWK",alias:"gawk",aliasTitles:{gawk:"GAWK"},owner:"RunDevelopment"},bash:{title:"Bash",alias:["sh","shell"],aliasTitles:{sh:"Shell",shell:"Shell"},owner:"zeitgeist87"},basic:{title:"BASIC",owner:"Golmote"},batch:{title:"Batch",owner:"Golmote"},bbcode:{title:"BBcode",alias:"shortcode",aliasTitles:{shortcode:"Shortcode"},owner:"RunDevelopment"},bbj:{title:"BBj",owner:"hyyan"},bicep:{title:"Bicep",owner:"johnnyreilly"},birb:{title:"Birb",require:"clike",owner:"Calamity210"},bison:{title:"Bison",require:"c",owner:"Golmote"},bnf:{title:"BNF",alias:"rbnf",aliasTitles:{rbnf:"RBNF"},owner:"RunDevelopment"},bqn:{title:"BQN",owner:"yewscion"},brainfuck:{title:"Brainfuck",owner:"Golmote"},brightscript:{title:"BrightScript",owner:"RunDevelopment"},bro:{title:"Bro",owner:"wayward710"},bsl:{title:"BSL (1C:Enterprise)",alias:"oscript",aliasTitles:{oscript:"OneScript"},owner:"Diversus23"},c:{title:"C",require:"clike",owner:"zeitgeist87"},csharp:{title:"C#",require:"clike",alias:["cs","dotnet"],owner:"mvalipour"},cpp:{title:"C++",require:"c",owner:"zeitgeist87"},cfscript:{title:"CFScript",require:"clike",alias:"cfc",owner:"mjclemente"},chaiscript:{title:"ChaiScript",require:["clike","cpp"],owner:"RunDevelopment"},cil:{title:"CIL",owner:"sbrl"},cilkc:{title:"Cilk/C",require:"c",alias:"cilk-c",owner:"OpenCilk"},cilkcpp:{title:"Cilk/C++",require:"cpp",alias:["cilk-cpp","cilk"],owner:"OpenCilk"},clojure:{title:"Clojure",owner:"troglotit"},cmake:{title:"CMake",owner:"mjrogozinski"},cobol:{title:"COBOL",owner:"RunDevelopment"},coffeescript:{title:"CoffeeScript",require:"javascript",alias:"coffee",owner:"R-osey"},concurnas:{title:"Concurnas",alias:"conc",owner:"jasontatton"},csp:{title:"Content-Security-Policy",owner:"ScottHelme"},cooklang:{title:"Cooklang",owner:"ahue"},coq:{title:"Coq",owner:"RunDevelopment"},crystal:{title:"Crystal",require:"ruby",owner:"MakeNowJust"},"css-extras":{title:"CSS Extras",require:"css",modify:"css",owner:"milesj"},csv:{title:"CSV",owner:"RunDevelopment"},cue:{title:"CUE",owner:"RunDevelopment"},cypher:{title:"Cypher",owner:"RunDevelopment"},d:{title:"D",require:"clike",owner:"Golmote"},dart:{title:"Dart",require:"clike",owner:"Golmote"},dataweave:{title:"DataWeave",owner:"machaval"},dax:{title:"DAX",owner:"peterbud"},dhall:{title:"Dhall",owner:"RunDevelopment"},diff:{title:"Diff",owner:"uranusjr"},django:{title:"Django/Jinja2",require:"markup-templating",alias:"jinja2",owner:"romanvm"},"dns-zone-file":{title:"DNS zone file",owner:"RunDevelopment",alias:"dns-zone"},docker:{title:"Docker",alias:"dockerfile",owner:"JustinBeckwith"},dot:{title:"DOT (Graphviz)",alias:"gv",optional:"markup",owner:"RunDevelopment"},ebnf:{title:"EBNF",owner:"RunDevelopment"},editorconfig:{title:"EditorConfig",owner:"osipxd"},eiffel:{title:"Eiffel",owner:"Conaclos"},ejs:{title:"EJS",require:["javascript","markup-templating"],owner:"RunDevelopment",alias:"eta",aliasTitles:{eta:"Eta"}},elixir:{title:"Elixir",owner:"Golmote"},elm:{title:"Elm",owner:"zwilias"},etlua:{title:"Embedded Lua templating",require:["lua","markup-templating"],owner:"RunDevelopment"},erb:{title:"ERB",require:["ruby","markup-templating"],owner:"Golmote"},erlang:{title:"Erlang",owner:"Golmote"},"excel-formula":{title:"Excel Formula",alias:["xlsx","xls"],owner:"RunDevelopment"},fsharp:{title:"F#",require:"clike",owner:"simonreynolds7"},factor:{title:"Factor",owner:"catb0t"},false:{title:"False",owner:"edukisto"},"firestore-security-rules":{title:"Firestore security rules",require:"clike",owner:"RunDevelopment"},flow:{title:"Flow",require:"javascript",owner:"Golmote"},fortran:{title:"Fortran",owner:"Golmote"},ftl:{title:"FreeMarker Template Language",require:"markup-templating",owner:"RunDevelopment"},gml:{title:"GameMaker Language",alias:"gamemakerlanguage",require:"clike",owner:"LiarOnce"},gap:{title:"GAP (CAS)",owner:"RunDevelopment"},gcode:{title:"G-code",owner:"RunDevelopment"},gdscript:{title:"GDScript",owner:"RunDevelopment"},gedcom:{title:"GEDCOM",owner:"Golmote"},gettext:{title:"gettext",alias:"po",owner:"RunDevelopment"},gherkin:{title:"Gherkin",owner:"hason"},git:{title:"Git",owner:"lgiraudel"},glsl:{title:"GLSL",require:"c",owner:"Golmote"},gn:{title:"GN",alias:"gni",owner:"RunDevelopment"},"linker-script":{title:"GNU Linker Script",alias:"ld",owner:"RunDevelopment"},go:{title:"Go",require:"clike",owner:"arnehormann"},"go-module":{title:"Go module",alias:"go-mod",owner:"RunDevelopment"},gradle:{title:"Gradle",require:"clike",owner:"zeabdelkhalek-badido18"},graphql:{title:"GraphQL",optional:"markdown",owner:"Golmote"},groovy:{title:"Groovy",require:"clike",owner:"robfletcher"},haml:{title:"Haml",require:"ruby",optional:["css","css-extras","coffeescript","erb","javascript","less","markdown","scss","textile"],owner:"Golmote"},handlebars:{title:"Handlebars",require:"markup-templating",alias:["hbs","mustache"],aliasTitles:{mustache:"Mustache"},owner:"Golmote"},haskell:{title:"Haskell",alias:"hs",owner:"bholst"},haxe:{title:"Haxe",require:"clike",optional:"regex",owner:"Golmote"},hcl:{title:"HCL",owner:"outsideris"},hlsl:{title:"HLSL",require:"c",owner:"RunDevelopment"},hoon:{title:"Hoon",owner:"matildepark"},http:{title:"HTTP",optional:["csp","css","hpkp","hsts","javascript","json","markup","uri"],owner:"danielgtaylor"},hpkp:{title:"HTTP Public-Key-Pins",owner:"ScottHelme"},hsts:{title:"HTTP Strict-Transport-Security",owner:"ScottHelme"},ichigojam:{title:"IchigoJam",owner:"BlueCocoa"},icon:{title:"Icon",owner:"Golmote"},"icu-message-format":{title:"ICU Message Format",owner:"RunDevelopment"},idris:{title:"Idris",alias:"idr",owner:"KeenS",require:"haskell"},ignore:{title:".ignore",owner:"osipxd",alias:["gitignore","hgignore","npmignore"],aliasTitles:{gitignore:".gitignore",hgignore:".hgignore",npmignore:".npmignore"}},inform7:{title:"Inform 7",owner:"Golmote"},ini:{title:"Ini",owner:"aviaryan"},io:{title:"Io",owner:"AlesTsurko"},j:{title:"J",owner:"Golmote"},java:{title:"Java",require:"clike",owner:"sherblot"},javadoc:{title:"JavaDoc",require:["markup","java","javadoclike"],modify:"java",optional:"scala",owner:"RunDevelopment"},javadoclike:{title:"JavaDoc-like",modify:["java","javascript","php"],owner:"RunDevelopment"},javastacktrace:{title:"Java stack trace",owner:"RunDevelopment"},jexl:{title:"Jexl",owner:"czosel"},jolie:{title:"Jolie",require:"clike",owner:"thesave"},jq:{title:"JQ",owner:"RunDevelopment"},jsdoc:{title:"JSDoc",require:["javascript","javadoclike","typescript"],modify:"javascript",optional:["actionscript","coffeescript"],owner:"RunDevelopment"},"js-extras":{title:"JS Extras",require:"javascript",modify:"javascript",optional:["actionscript","coffeescript","flow","n4js","typescript"],owner:"RunDevelopment"},json:{title:"JSON",alias:"webmanifest",aliasTitles:{webmanifest:"Web App Manifest"},owner:"CupOfTea696"},json5:{title:"JSON5",require:"json",owner:"RunDevelopment"},jsonp:{title:"JSONP",require:"json",owner:"RunDevelopment"},jsstacktrace:{title:"JS stack trace",owner:"sbrl"},"js-templates":{title:"JS Templates",require:"javascript",modify:"javascript",optional:["css","css-extras","graphql","markdown","markup","sql"],owner:"RunDevelopment"},julia:{title:"Julia",owner:"cdagnino"},keepalived:{title:"Keepalived Configure",owner:"dev-itsheng"},keyman:{title:"Keyman",owner:"mcdurdin"},kotlin:{title:"Kotlin",alias:["kt","kts"],aliasTitles:{kts:"Kotlin Script"},require:"clike",owner:"Golmote"},kumir:{title:"KuMir (\u041a\u0443\u041c\u0438\u0440)",alias:"kum",owner:"edukisto"},kusto:{title:"Kusto",owner:"RunDevelopment"},latex:{title:"LaTeX",alias:["tex","context"],aliasTitles:{tex:"TeX",context:"ConTeXt"},owner:"japborst"},latte:{title:"Latte",require:["clike","markup-templating","php"],owner:"nette"},less:{title:"Less",require:"css",optional:"css-extras",owner:"Golmote"},lilypond:{title:"LilyPond",require:"scheme",alias:"ly",owner:"RunDevelopment"},liquid:{title:"Liquid",require:"markup-templating",owner:"cinhtau"},lisp:{title:"Lisp",alias:["emacs","elisp","emacs-lisp"],owner:"JuanCaicedo"},livescript:{title:"LiveScript",owner:"Golmote"},llvm:{title:"LLVM IR",owner:"porglezomp"},log:{title:"Log file",optional:"javastacktrace",owner:"RunDevelopment"},lolcode:{title:"LOLCODE",owner:"Golmote"},lua:{title:"Lua",owner:"Golmote"},magma:{title:"Magma (CAS)",owner:"RunDevelopment"},makefile:{title:"Makefile",owner:"Golmote"},markdown:{title:"Markdown",require:"markup",optional:"yaml",alias:"md",owner:"Golmote"},"markup-templating":{title:"Markup templating",require:"markup",owner:"Golmote"},mata:{title:"Mata",owner:"RunDevelopment"},matlab:{title:"MATLAB",owner:"Golmote"},maxscript:{title:"MAXScript",owner:"RunDevelopment"},mel:{title:"MEL",owner:"Golmote"},mermaid:{title:"Mermaid",owner:"RunDevelopment"},metafont:{title:"METAFONT",owner:"LaeriExNihilo"},mizar:{title:"Mizar",owner:"Golmote"},mongodb:{title:"MongoDB",owner:"airs0urce",require:"javascript"},monkey:{title:"Monkey",owner:"Golmote"},moonscript:{title:"MoonScript",alias:"moon",owner:"RunDevelopment"},n1ql:{title:"N1QL",owner:"TMWilds"},n4js:{title:"N4JS",require:"javascript",optional:"jsdoc",alias:"n4jsd",owner:"bsmith-n4"},"nand2tetris-hdl":{title:"Nand To Tetris HDL",owner:"stephanmax"},naniscript:{title:"Naninovel Script",owner:"Elringus",alias:"nani"},nasm:{title:"NASM",owner:"rbmj"},neon:{title:"NEON",owner:"nette"},nevod:{title:"Nevod",owner:"nezaboodka"},nginx:{title:"nginx",owner:"volado"},nim:{title:"Nim",owner:"Golmote"},nix:{title:"Nix",owner:"Golmote"},nsis:{title:"NSIS",owner:"idleberg"},objectivec:{title:"Objective-C",require:"c",alias:"objc",owner:"uranusjr"},ocaml:{title:"OCaml",owner:"Golmote"},odin:{title:"Odin",owner:"edukisto"},opencl:{title:"OpenCL",require:"c",modify:["c","cpp"],owner:"Milania1"},openqasm:{title:"OpenQasm",alias:"qasm",owner:"RunDevelopment"},oz:{title:"Oz",owner:"Golmote"},parigp:{title:"PARI/GP",owner:"Golmote"},parser:{title:"Parser",require:"markup",owner:"Golmote"},pascal:{title:"Pascal",alias:"objectpascal",aliasTitles:{objectpascal:"Object Pascal"},owner:"Golmote"},pascaligo:{title:"Pascaligo",owner:"DefinitelyNotAGoat"},psl:{title:"PATROL Scripting Language",owner:"bertysentry"},pcaxis:{title:"PC-Axis",alias:"px",owner:"RunDevelopment"},peoplecode:{title:"PeopleCode",alias:"pcode",owner:"RunDevelopment"},perl:{title:"Perl",owner:"Golmote"},php:{title:"PHP",require:"markup-templating",owner:"milesj"},phpdoc:{title:"PHPDoc",require:["php","javadoclike"],modify:"php",owner:"RunDevelopment"},"php-extras":{title:"PHP Extras",require:"php",modify:"php",owner:"milesj"},"plant-uml":{title:"PlantUML",alias:"plantuml",owner:"RunDevelopment"},plsql:{title:"PL/SQL",require:"sql",owner:"Golmote"},powerquery:{title:"PowerQuery",alias:["pq","mscript"],owner:"peterbud"},powershell:{title:"PowerShell",owner:"nauzilus"},processing:{title:"Processing",require:"clike",owner:"Golmote"},prolog:{title:"Prolog",owner:"Golmote"},promql:{title:"PromQL",owner:"arendjr"},properties:{title:".properties",owner:"Golmote"},protobuf:{title:"Protocol Buffers",require:"clike",owner:"just-boris"},pug:{title:"Pug",require:["markup","javascript"],optional:["coffeescript","ejs","handlebars","less","livescript","markdown","scss","stylus","twig"],owner:"Golmote"},puppet:{title:"Puppet",owner:"Golmote"},pure:{title:"Pure",optional:["c","cpp","fortran"],owner:"Golmote"},purebasic:{title:"PureBasic",require:"clike",alias:"pbfasm",owner:"HeX0R101"},purescript:{title:"PureScript",require:"haskell",alias:"purs",owner:"sriharshachilakapati"},python:{title:"Python",alias:"py",owner:"multipetros"},qsharp:{title:"Q#",require:"clike",alias:"qs",owner:"fedonman"},q:{title:"Q (kdb+ database)",owner:"Golmote"},qml:{title:"QML",require:"javascript",owner:"RunDevelopment"},qore:{title:"Qore",require:"clike",owner:"temnroegg"},r:{title:"R",owner:"Golmote"},racket:{title:"Racket",require:"scheme",alias:"rkt",owner:"RunDevelopment"},cshtml:{title:"Razor C#",alias:"razor",require:["markup","csharp"],optional:["css","css-extras","javascript","js-extras"],owner:"RunDevelopment"},jsx:{title:"React JSX",require:["markup","javascript"],optional:["jsdoc","js-extras","js-templates"],owner:"vkbansal"},tsx:{title:"React TSX",require:["jsx","typescript"]},reason:{title:"Reason",require:"clike",owner:"Golmote"},regex:{title:"Regex",owner:"RunDevelopment"},rego:{title:"Rego",owner:"JordanSh"},renpy:{title:"Ren'py",alias:"rpy",owner:"HyuchiaDiego"},rescript:{title:"ReScript",alias:"res",owner:"vmarcosp"},rest:{title:"reST (reStructuredText)",owner:"Golmote"},rip:{title:"Rip",owner:"ravinggenius"},roboconf:{title:"Roboconf",owner:"Golmote"},robotframework:{title:"Robot Framework",alias:"robot",owner:"RunDevelopment"},ruby:{title:"Ruby",require:"clike",alias:"rb",owner:"samflores"},rust:{title:"Rust",owner:"Golmote"},sas:{title:"SAS",optional:["groovy","lua","sql"],owner:"Golmote"},sass:{title:"Sass (Sass)",require:"css",optional:"css-extras",owner:"Golmote"},scss:{title:"Sass (SCSS)",require:"css",optional:"css-extras",owner:"MoOx"},scala:{title:"Scala",require:"java",owner:"jozic"},scheme:{title:"Scheme",owner:"bacchus123"},"shell-session":{title:"Shell session",require:"bash",alias:["sh-session","shellsession"],owner:"RunDevelopment"},smali:{title:"Smali",owner:"RunDevelopment"},smalltalk:{title:"Smalltalk",owner:"Golmote"},smarty:{title:"Smarty",require:"markup-templating",optional:"php",owner:"Golmote"},sml:{title:"SML",alias:"smlnj",aliasTitles:{smlnj:"SML/NJ"},owner:"RunDevelopment"},solidity:{title:"Solidity (Ethereum)",alias:"sol",require:"clike",owner:"glachaud"},"solution-file":{title:"Solution file",alias:"sln",owner:"RunDevelopment"},soy:{title:"Soy (Closure Template)",require:"markup-templating",owner:"Golmote"},sparql:{title:"SPARQL",require:"turtle",owner:"Triply-Dev",alias:"rq"},"splunk-spl":{title:"Splunk SPL",owner:"RunDevelopment"},sqf:{title:"SQF: Status Quo Function (Arma 3)",require:"clike",owner:"RunDevelopment"},sql:{title:"SQL",owner:"multipetros"},squirrel:{title:"Squirrel",require:"clike",owner:"RunDevelopment"},stan:{title:"Stan",owner:"RunDevelopment"},stata:{title:"Stata Ado",require:["mata","java","python"],owner:"RunDevelopment"},iecst:{title:"Structured Text (IEC 61131-3)",owner:"serhioromano"},stylus:{title:"Stylus",owner:"vkbansal"},supercollider:{title:"SuperCollider",alias:"sclang",owner:"RunDevelopment"},swift:{title:"Swift",owner:"chrischares"},systemd:{title:"Systemd configuration file",owner:"RunDevelopment"},"t4-templating":{title:"T4 templating",owner:"RunDevelopment"},"t4-cs":{title:"T4 Text Templates (C#)",require:["t4-templating","csharp"],alias:"t4",owner:"RunDevelopment"},"t4-vb":{title:"T4 Text Templates (VB)",require:["t4-templating","vbnet"],owner:"RunDevelopment"},tap:{title:"TAP",owner:"isaacs",require:"yaml"},tcl:{title:"Tcl",owner:"PeterChaplin"},tt2:{title:"Template Toolkit 2",require:["clike","markup-templating"],owner:"gflohr"},textile:{title:"Textile",require:"markup",optional:"css",owner:"Golmote"},toml:{title:"TOML",owner:"RunDevelopment"},tremor:{title:"Tremor",alias:["trickle","troy"],owner:"darach",aliasTitles:{trickle:"trickle",troy:"troy"}},turtle:{title:"Turtle",alias:"trig",aliasTitles:{trig:"TriG"},owner:"jakubklimek"},twig:{title:"Twig",require:"markup-templating",owner:"brandonkelly"},typescript:{title:"TypeScript",require:"javascript",optional:"js-templates",alias:"ts",owner:"vkbansal"},typoscript:{title:"TypoScript",alias:"tsconfig",aliasTitles:{tsconfig:"TSConfig"},owner:"dkern"},unrealscript:{title:"UnrealScript",alias:["uscript","uc"],owner:"RunDevelopment"},uorazor:{title:"UO Razor Script",owner:"jaseowns"},uri:{title:"URI",alias:"url",aliasTitles:{url:"URL"},owner:"RunDevelopment"},v:{title:"V",require:"clike",owner:"taggon"},vala:{title:"Vala",require:"clike",optional:"regex",owner:"TemplarVolk"},vbnet:{title:"VB.Net",require:"basic",owner:"Bigsby"},velocity:{title:"Velocity",require:"markup",owner:"Golmote"},verilog:{title:"Verilog",owner:"a-rey"},vhdl:{title:"VHDL",owner:"a-rey"},vim:{title:"vim",owner:"westonganger"},"visual-basic":{title:"Visual Basic",alias:["vb","vba"],aliasTitles:{vba:"VBA"},owner:"Golmote"},warpscript:{title:"WarpScript",owner:"RunDevelopment"},wasm:{title:"WebAssembly",owner:"Golmote"},"web-idl":{title:"Web IDL",alias:"webidl",owner:"RunDevelopment"},wgsl:{title:"WGSL",owner:"Dr4gonthree"},wiki:{title:"Wiki markup",require:"markup",owner:"Golmote"},wolfram:{title:"Wolfram language",alias:["mathematica","nb","wl"],aliasTitles:{mathematica:"Mathematica",nb:"Mathematica Notebook"},owner:"msollami"},wren:{title:"Wren",owner:"clsource"},xeora:{title:"Xeora",require:"markup",alias:"xeoracube",aliasTitles:{xeoracube:"XeoraCube"},owner:"freakmaxi"},"xml-doc":{title:"XML doc (.net)",require:"markup",modify:["csharp","fsharp","vbnet"],owner:"RunDevelopment"},xojo:{title:"Xojo (REALbasic)",owner:"Golmote"},xquery:{title:"XQuery",require:"markup",owner:"Golmote"},yaml:{title:"YAML",alias:"yml",owner:"hason"},yang:{title:"YANG",owner:"RunDevelopment"},zig:{title:"Zig",owner:"RunDevelopment"}},plugins:{meta:{path:"plugins/{id}/prism-{id}",link:"plugins/{id}/"},"line-highlight":{title:"Line Highlight",description:"Highlights specific lines and/or line ranges."},"line-numbers":{title:"Line Numbers",description:"Line number at the beginning of code lines.",owner:"kuba-kubula"},"show-invisibles":{title:"Show Invisibles",description:"Show hidden characters such as tabs and line breaks.",optional:["autolinker","data-uri-highlight"]},autolinker:{title:"Autolinker",description:"Converts URLs and emails in code to clickable links. Parses Markdown links in comments."},wpd:{title:"WebPlatform Docs",description:'Makes tokens link to WebPlatform.org documentation. The links open in a new tab.'},"custom-class":{title:"Custom Class",description:"This plugin allows you to prefix Prism's default classes (.comment can become .namespace--comment) or replace them with your defined ones (like .editor__comment). You can even add new classes.",owner:"dvkndn",noCSS:!0},"file-highlight":{title:"File Highlight",description:"Fetch external files and highlight them with Prism. Used on the Prism website itself.",noCSS:!0},"show-language":{title:"Show Language",description:"Display the highlighted language in code blocks (inline code does not show the label).",owner:"nauzilus",noCSS:!0,require:"toolbar"},"jsonp-highlight":{title:"JSONP Highlight",description:"Fetch content with JSONP and highlight some interesting content (e.g. GitHub/Gists or Bitbucket API).",noCSS:!0,owner:"nauzilus"},"highlight-keywords":{title:"Highlight Keywords",description:"Adds special CSS classes for each keyword for fine-grained highlighting.",owner:"vkbansal",noCSS:!0},"remove-initial-line-feed":{title:"Remove initial line feed",description:"Removes the initial line feed in code blocks.",owner:"Golmote",noCSS:!0},"inline-color":{title:"Inline color",description:"Adds a small inline preview for colors in style sheets.",require:"css-extras",owner:"RunDevelopment"},previewers:{title:"Previewers",description:"Previewers for angles, colors, gradients, easing and time.",require:"css-extras",owner:"Golmote"},autoloader:{title:"Autoloader",description:"Automatically loads the needed languages to highlight the code blocks.",owner:"Golmote",noCSS:!0},"keep-markup":{title:"Keep Markup",description:"Prevents custom markup from being dropped out during highlighting.",owner:"Golmote",optional:"normalize-whitespace",noCSS:!0},"command-line":{title:"Command Line",description:"Display a command line with a prompt and, optionally, the output/response from the commands.",owner:"chriswells0"},"unescaped-markup":{title:"Unescaped Markup",description:"Write markup without having to escape anything."},"normalize-whitespace":{title:"Normalize Whitespace",description:"Supports multiple operations to normalize whitespace in code blocks.",owner:"zeitgeist87",optional:"unescaped-markup",noCSS:!0},"data-uri-highlight":{title:"Data-URI Highlight",description:"Highlights data-URI contents.",owner:"Golmote",noCSS:!0},toolbar:{title:"Toolbar",description:"Attach a toolbar for plugins to easily register buttons on the top of a code block.",owner:"mAAdhaTTah"},"copy-to-clipboard":{title:"Copy to Clipboard Button",description:"Add a button that copies the code block to the clipboard when clicked.",owner:"mAAdhaTTah",require:"toolbar",noCSS:!0},"download-button":{title:"Download Button",description:"A button in the toolbar of a code block adding a convenient way to download a code file.",owner:"Golmote",require:"toolbar",noCSS:!0},"match-braces":{title:"Match braces",description:"Highlights matching braces.",owner:"RunDevelopment"},"diff-highlight":{title:"Diff Highlight",description:"Highlights the code inside diff blocks.",owner:"RunDevelopment",require:"diff"},"filter-highlight-all":{title:"Filter highlightAll",description:"Filters the elements the highlightAll and highlightAllUnder methods actually highlight.",owner:"RunDevelopment",noCSS:!0},treeview:{title:"Treeview",description:"A language with special styles to highlight file system tree structures.",owner:"Golmote"}}})},46532:(e,t,n)=>{const r=n(39227),o=n(29670),a=new Set;function i(e){void 0===e?e=Object.keys(r.languages).filter((e=>"meta"!=e)):Array.isArray(e)||(e=[e]);const t=[...a,...Object.keys(Prism.languages)];o(r,e,t).load((e=>{if(!(e in r.languages))return void(i.silent||console.warn("Language does not exist: "+e));const t="./prism-"+e;delete n.c[n(57507).resolve(t)],delete Prism.languages[e],n(57507)(t),a.add(e)}))}i.silent=!1,e.exports=i},1274:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,s=i.length;-1!==n.code.indexOf(o=t(r,s));)++s;return i[s]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(s){for(var l=0;l=a.length);l++){var c=s[l];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=a[o],d=n.tokenStack[u],p="string"==typeof c?c:c.content,f=t(r,u),h=p.indexOf(f);if(h>-1){++o;var m=p.substring(0,h),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),v=p.substring(h+f.length),y=[];m&&y.push.apply(y,i([m])),y.push(g),v&&y.push.apply(y,i([v])),"string"==typeof c?s.splice.apply(s,[l,1].concat(y)):c.content=y}}else c.content&&i(c.content)}return s}(n.tokens)}}}})}(Prism)},57507:(e,t,n)=>{var r={"./":46532};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=57507},29670:e=>{"use strict";var t=function(){var e=function(){};function t(e,t){Array.isArray(e)?e.forEach(t):null!=e&&t(e,0)}function n(e){for(var t={},n=0,r=e.length;n "));var s={},l=e[r];if(l){function c(t){if(!(t in e))throw new Error(r+" depends on an unknown component "+t);if(!(t in s))for(var i in o(t,a),s[t]=!0,n[t])s[i]=!0}t(l.require,c),t(l.optional,c),t(l.modify,c)}n[r]=s,a.pop()}}return function(e){var t=n[e];return t||(o(e,r),t=n[e]),t}}function o(e){for(var t in e)return!0;return!1}return function(a,i,s){var l=function(e){var t={};for(var n in e){var r=e[n];for(var o in r)if("meta"!=o){var a=r[o];t[o]="string"==typeof a?{title:a}:a}}return t}(a),c=function(e){var n;return function(r){if(r in e)return r;if(!n)for(var o in n={},e){var a=e[o];t(a&&a.alias,(function(t){if(t in n)throw new Error(t+" cannot be alias for both "+o+" and "+n[t]);if(t in e)throw new Error(t+" cannot be alias of "+o+" because it is a component.");n[t]=o}))}return n[r]||r}}(l);i=i.map(c),s=(s||[]).map(c);var u=n(i),d=n(s);i.forEach((function e(n){var r=l[n];t(r&&r.require,(function(t){t in d||(u[t]=!0,e(t))}))}));for(var p,f=r(l),h=u;o(h);){for(var m in p={},h){var g=l[m];t(g&&g.modify,(function(e){e in d&&(p[e]=!0)}))}for(var v in d)if(!(v in u))for(var y in f(v))if(y in u){p[v]=!0;break}for(var b in h=p)u[b]=!0}var w={getIds:function(){var e=[];return w.load((function(t){e.push(t)})),e},load:function(t,n){return function(t,n,r,o){var a=o?o.series:void 0,i=o?o.parallel:e,s={},l={};function c(e){if(e in s)return s[e];l[e]=!0;var o,u=[];for(var d in t(e))d in n&&u.push(d);if(0===u.length)o=r(e);else{var p=i(u.map((function(e){var t=c(e);return delete l[e],t})));a?o=a(p,(function(){return r(e)})):r(e)}return s[e]=o}for(var u in n)c(u);var d=[];for(var p in l)d.push(s[p]);return i(d)}(f,u,t,n)}};return w}}();e.exports=t},16186:(e,t,n)=>{"use strict";var r=n(62985);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var s=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw s.name="Invariant Violation",s}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},2736:(e,t,n)=>{e.exports=n(16186)()},62985:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},19481:(e,t,n)=>{"use strict";var r=n(30758),o=n(31896);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n